aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/Archive/IhexHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--CPP/7zip/Archive/IhexHandler.cpp162
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
19namespace NArchive { 19namespace NArchive {
20namespace NIhex { 20namespace 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
102static 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
110static int Parse(const Byte *p) 104static 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):
122static const unsigned k_NumSpaces_LIMIT = 16 + 1;
123
124#define IS_LINE_DELIMITER(c) (/* (c) == 0 || */ (c) == 10 || (c) == 13)
127 125
128API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size) 126API_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
220Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *)) 218Z7_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
412Z7_COM7F_IMF(CHandler::Close()) 427Z7_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
487REGISTER_ARC_I_NO_SIG( 487REGISTER_ARC_I_NO_SIG(
488 "IHex", "ihex", NULL, 0xCD, 488 "IHex", "ihex", NULL, 0xCD,