aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/Archive/7z/7zOut.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--CPP/7zip/Archive/7z/7zOut.cpp309
1 files changed, 190 insertions, 119 deletions
diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp
index 7f8fa5b..d0c8cf2 100644
--- a/CPP/7zip/Archive/7z/7zOut.cpp
+++ b/CPP/7zip/Archive/7z/7zOut.cpp
@@ -3,14 +3,34 @@
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include "../../../../C/7zCrc.h" 5#include "../../../../C/7zCrc.h"
6#include "../../../../C/CpuArch.h"
6 7
7#include "../../../Common/AutoPtr.h" 8#include "../../../Common/AutoPtr.h"
8// #include "../../../Common/UTFConvert.h" 9// #include "../../../Common/UTFConvert.h"
9 10
10#include "../../Common/StreamObjects.h" 11#include "../../Common/StreamObjects.h"
12#include "../Common/OutStreamWithCRC.h"
11 13
12#include "7zOut.h" 14#include "7zOut.h"
13 15
16unsigned BoolVector_CountSum(const CBoolVector &v);
17
18static UInt64 UInt64Vector_CountSum(const CRecordVector<UInt64> &v)
19{
20 UInt64 sum = 0;
21 const unsigned size = v.Size();
22 if (size)
23 {
24 const UInt64 *p = v.ConstData();
25 const UInt64 * const lim = p + size;
26 do
27 sum += *p++;
28 while (p != lim);
29 }
30 return sum;
31}
32
33
14namespace NArchive { 34namespace NArchive {
15namespace N7z { 35namespace N7z {
16 36
@@ -133,7 +153,7 @@ void COutArchive::WriteBytes(const void *data, size_t size)
133 else if (_writeToStream) 153 else if (_writeToStream)
134 { 154 {
135 _outByte.WriteBytes(data, size); 155 _outByte.WriteBytes(data, size);
136 _crc = CrcUpdate(_crc, data, size); 156 // _crc = CrcUpdate(_crc, data, size);
137 } 157 }
138 else 158 else
139 _outByte2.WriteBytes(data, size); 159 _outByte2.WriteBytes(data, size);
@@ -144,14 +164,12 @@ void COutArchive::WriteByte(Byte b)
144 if (_countMode) 164 if (_countMode)
145 _countSize++; 165 _countSize++;
146 else if (_writeToStream) 166 else if (_writeToStream)
147 { 167 WriteByte_ToStream(b);
148 _outByte.WriteByte(b);
149 _crc = CRC_UPDATE_BYTE(_crc, b);
150 }
151 else 168 else
152 _outByte2.WriteByte(b); 169 _outByte2.WriteByte(b);
153} 170}
154 171
172/*
155void COutArchive::WriteUInt32(UInt32 value) 173void COutArchive::WriteUInt32(UInt32 value)
156{ 174{
157 for (int i = 0; i < 4; i++) 175 for (int i = 0; i < 4; i++)
@@ -169,6 +187,7 @@ void COutArchive::WriteUInt64(UInt64 value)
169 value >>= 8; 187 value >>= 8;
170 } 188 }
171} 189}
190*/
172 191
173void COutArchive::WriteNumber(UInt64 value) 192void COutArchive::WriteNumber(UInt64 value)
174{ 193{
@@ -288,7 +307,7 @@ void COutArchive::WriteFolder(const CFolder &folder)
288 WriteNumber(folder.PackStreams[i]); 307 WriteNumber(folder.PackStreams[i]);
289} 308}
290 309
291void COutArchive::WriteBoolVector(const CBoolVector &boolVector) 310void COutArchive::Write_BoolVector(const CBoolVector &boolVector)
292{ 311{
293 Byte b = 0; 312 Byte b = 0;
294 Byte mask = 0x80; 313 Byte mask = 0x80;
@@ -314,31 +333,32 @@ void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector)
314{ 333{
315 WriteByte(id); 334 WriteByte(id);
316 WriteNumber(Bv_GetSizeInBytes(boolVector)); 335 WriteNumber(Bv_GetSizeInBytes(boolVector));
317 WriteBoolVector(boolVector); 336 Write_BoolVector(boolVector);
337}
338
339void COutArchive::Write_BoolVector_numDefined(const CBoolVector &boolVector, unsigned numDefined)
340{
341 if (numDefined == boolVector.Size())
342 WriteByte(1);
343 else
344 {
345 WriteByte(0);
346 Write_BoolVector(boolVector);
347 }
318} 348}
319 349
320unsigned BoolVector_CountSum(const CBoolVector &v);
321 350
322void COutArchive::WriteHashDigests(const CUInt32DefVector &digests) 351void COutArchive::WriteHashDigests(const CUInt32DefVector &digests)
323{ 352{
324 const unsigned numDefined = BoolVector_CountSum(digests.Defs); 353 const unsigned numDefined = BoolVector_CountSum(digests.Defs);
325 if (numDefined == 0) 354 if (numDefined == 0)
326 return; 355 return;
327
328 WriteByte(NID::kCRC); 356 WriteByte(NID::kCRC);
329 if (numDefined == digests.Defs.Size()) 357 Write_BoolVector_numDefined(digests.Defs, numDefined);
330 WriteByte(1); 358 Write_UInt32DefVector_numDefined(digests, numDefined);
331 else
332 {
333 WriteByte(0);
334 WriteBoolVector(digests.Defs);
335 }
336
337 for (unsigned i = 0; i < digests.Defs.Size(); i++)
338 if (digests.Defs[i])
339 WriteUInt32(digests.Vals[i]);
340} 359}
341 360
361
342void COutArchive::WritePackInfo( 362void COutArchive::WritePackInfo(
343 UInt64 dataOffset, 363 UInt64 dataOffset,
344 const CRecordVector<UInt64> &packSizes, 364 const CRecordVector<UInt64> &packSizes,
@@ -467,17 +487,42 @@ void COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, B
467 487
468 WriteByte(type); 488 WriteByte(type);
469 WriteNumber(dataSize); 489 WriteNumber(dataSize);
470 if (numDefined == v.Size()) 490 Write_BoolVector_numDefined(v, numDefined);
471 WriteByte(1); 491 WriteByte(0); // 0 means no switching to external stream
472 else 492}
493
494
495void COutArchive::Write_UInt32DefVector_numDefined(const CUInt32DefVector &v, unsigned numDefined)
496{
497 if (_countMode)
473 { 498 {
474 WriteByte(0); 499 _countSize += (size_t)numDefined * 4;
475 WriteBoolVector(v); 500 return;
476 } 501 }
477 WriteByte(0); // 0 means no switching to external stream 502
503 const bool * const defs = v.Defs.ConstData();
504 const UInt32 * const vals = v.Vals.ConstData();
505 const size_t num = v.Defs.Size();
506
507 for (size_t i = 0; i < num; i++)
508 if (defs[i])
509 {
510 UInt32 value = vals[i];
511 for (int k = 0; k < 4; k++)
512 {
513 if (_writeToStream)
514 WriteByte_ToStream((Byte)value);
515 else
516 _outByte2.WriteByte((Byte)value);
517 // WriteByte((Byte)value);
518 value >>= 8;
519 }
520 // WriteUInt32(v.Vals[i]);
521 }
478} 522}
479 523
480void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type) 524
525void COutArchive::Write_UInt64DefVector_type(const CUInt64DefVector &v, Byte type)
481{ 526{
482 const unsigned numDefined = BoolVector_CountSum(v.Defs); 527 const unsigned numDefined = BoolVector_CountSum(v.Defs);
483 if (numDefined == 0) 528 if (numDefined == 0)
@@ -485,18 +530,40 @@ void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)
485 530
486 WriteAlignedBools(v.Defs, numDefined, type, 3); 531 WriteAlignedBools(v.Defs, numDefined, type, 3);
487 532
488 for (unsigned i = 0; i < v.Defs.Size(); i++) 533 if (_countMode)
489 if (v.Defs[i]) 534 {
490 WriteUInt64(v.Vals[i]); 535 _countSize += (size_t)numDefined * 8;
536 return;
537 }
538
539 const bool * const defs = v.Defs.ConstData();
540 const UInt64 * const vals = v.Vals.ConstData();
541 const size_t num = v.Defs.Size();
542
543 for (size_t i = 0; i < num; i++)
544 if (defs[i])
545 {
546 UInt64 value = vals[i];
547 for (int k = 0; k < 8; k++)
548 {
549 if (_writeToStream)
550 WriteByte_ToStream((Byte)value);
551 else
552 _outByte2.WriteByte((Byte)value);
553 // WriteByte((Byte)value);
554 value >>= 8;
555 }
556 // WriteUInt64(v.Vals[i]);
557 }
491} 558}
492 559
560
493HRESULT COutArchive::EncodeStream( 561HRESULT COutArchive::EncodeStream(
494 DECL_EXTERNAL_CODECS_LOC_VARS 562 DECL_EXTERNAL_CODECS_LOC_VARS
495 CEncoder &encoder, const CByteBuffer &data, 563 CEncoder &encoder, const CByteBuffer &data,
496 CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders) 564 CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders)
497{ 565{
498 CBufInStream *streamSpec = new CBufInStream; 566 CMyComPtr2_Create<ISequentialInStream, CBufInStream> streamSpec;
499 CMyComPtr<ISequentialInStream> stream = streamSpec;
500 streamSpec->Init(data, data.Size()); 567 streamSpec->Init(data, data.Size());
501 outFolders.FolderUnpackCRCs.Defs.Add(true); 568 outFolders.FolderUnpackCRCs.Defs.Add(true);
502 outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size())); 569 outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size()));
@@ -505,7 +572,7 @@ HRESULT COutArchive::EncodeStream(
505 const UInt64 expectSize = data.Size(); 572 const UInt64 expectSize = data.Size();
506 RINOK(encoder.Encode1( 573 RINOK(encoder.Encode1(
507 EXTERNAL_CODECS_LOC_VARS 574 EXTERNAL_CODECS_LOC_VARS
508 stream, 575 streamSpec,
509 // NULL, 576 // NULL,
510 &dataSize64, // inSizeForReduce 577 &dataSize64, // inSizeForReduce
511 expectSize, 578 expectSize,
@@ -528,13 +595,7 @@ void COutArchive::WriteHeader(
528 */ 595 */
529 _useAlign = true; 596 _useAlign = true;
530 597
531 { 598 headerOffset = UInt64Vector_CountSum(db.PackSizes);
532 UInt64 packSize = 0;
533 FOR_VECTOR (i, db.PackSizes)
534 packSize += db.PackSizes[i];
535 headerOffset = packSize;
536 }
537
538 599
539 WriteByte(NID::kHeader); 600 WriteByte(NID::kHeader);
540 601
@@ -655,81 +716,97 @@ void COutArchive::WriteHeader(
655 { 716 {
656 /* ---------- Names ---------- */ 717 /* ---------- Names ---------- */
657 718
658 unsigned numDefined = 0;
659 size_t namesDataSize = 0; 719 size_t namesDataSize = 0;
660 FOR_VECTOR (i, db.Files)
661 { 720 {
662 const UString &name = db.Names[i]; 721 FOR_VECTOR (i, db.Files)
663 if (!name.IsEmpty()) 722 {
664 numDefined++; 723 const UString &name = db.Names[i];
665 const size_t numUtfChars = 724 const size_t numUtfChars =
666 /* 725 /*
667 #if WCHAR_MAX > 0xffff 726 #if WCHAR_MAX > 0xffff
668 Get_Num_Utf16_chars_from_wchar_string(name.Ptr()); 727 Get_Num_Utf16_chars_from_wchar_string(name.Ptr());
669 #else 728 #else
670 */ 729 */
671 name.Len(); 730 name.Len();
672 // #endif 731 // #endif
673 namesDataSize += (numUtfChars + 1) * 2; 732 namesDataSize += numUtfChars;
733 }
674 } 734 }
675 735 if (namesDataSize)
676 if (numDefined > 0)
677 { 736 {
678 namesDataSize++; 737 namesDataSize += db.Files.Size(); // we will write tail zero wchar for each name
738 namesDataSize *= 2; // 2 bytes per wchar for UTF16 encoding
739 namesDataSize++; // for additional switch byte (zero value)
679 SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4); 740 SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4);
680
681 WriteByte(NID::kName); 741 WriteByte(NID::kName);
682 WriteNumber(namesDataSize); 742 WriteNumber(namesDataSize);
683 WriteByte(0); 743
684 FOR_VECTOR (i, db.Files) 744 if (_countMode)
745 _countSize += namesDataSize;
746 else
685 { 747 {
686 const UString &name = db.Names[i]; 748 WriteByte(0);
687 for (unsigned t = 0; t <= name.Len(); t++) 749 FOR_VECTOR (i, db.Files)
688 { 750 {
689 wchar_t c = name[t]; 751 const UString &name = db.Names[i];
690 752 const wchar_t *p = name.Ptr();
691 /* 753 const size_t len = (size_t)name.Len() + 1;
692 #if WCHAR_MAX > 0xffff 754 const wchar_t * const lim = p + len;
693 if (c >= 0x10000) 755 if (_writeToStream)
694 { 756 {
695 c -= 0x10000; 757 do
696 if (c < (1 << 20))
697 { 758 {
698 unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF); 759 const wchar_t c = *p++;
699 WriteByte((Byte)c0); 760 WriteByte_ToStream((Byte)c);
700 WriteByte((Byte)(c0 >> 8)); 761 WriteByte_ToStream((Byte)(c >> 8));
701 c = 0xdc00 + (c & 0x3FF);
702 } 762 }
703 else 763 while (p != lim);
704 c = '_'; // we change character unsupported by UTF16 764 }
765 else
766 {
767 Byte *dest = _outByte2.GetDest_and_Update(len * 2);
768 do
769 {
770 /*
771 #if WCHAR_MAX > 0xffff
772 if (c >= 0x10000)
773 {
774 c -= 0x10000;
775 if (c < (1 << 20))
776 {
777 unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF);
778 WriteByte((Byte)c0);
779 WriteByte((Byte)(c0 >> 8));
780 c = 0xdc00 + (c & 0x3FF);
781 }
782 else
783 c = '_'; // we change character unsupported by UTF16
784 }
785 #endif
786 */
787 const wchar_t c = *p++;
788 SetUi16(dest, (UInt16)c)
789 dest += 2;
790 }
791 while (p != lim);
705 } 792 }
706 #endif
707 */
708
709 WriteByte((Byte)c);
710 WriteByte((Byte)(c >> 8));
711 } 793 }
712 } 794 }
713 } 795 }
714 } 796 }
715 797
716 /* if (headerOptions.WriteCTime) */ WriteUInt64DefVector(db.CTime, NID::kCTime); 798 /* if (headerOptions.WriteCTime) */ Write_UInt64DefVector_type(db.CTime, NID::kCTime);
717 /* if (headerOptions.WriteATime) */ WriteUInt64DefVector(db.ATime, NID::kATime); 799 /* if (headerOptions.WriteATime) */ Write_UInt64DefVector_type(db.ATime, NID::kATime);
718 /* if (headerOptions.WriteMTime) */ WriteUInt64DefVector(db.MTime, NID::kMTime); 800 /* if (headerOptions.WriteMTime) */ Write_UInt64DefVector_type(db.MTime, NID::kMTime);
719 WriteUInt64DefVector(db.StartPos, NID::kStartPos); 801 Write_UInt64DefVector_type(db.StartPos, NID::kStartPos);
720 802
721 { 803 {
722 /* ---------- Write Attrib ---------- */ 804 /* ---------- Write Attrib ---------- */
723 const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs); 805 const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs);
724
725 if (numDefined != 0) 806 if (numDefined != 0)
726 { 807 {
727 WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2); 808 WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2);
728 FOR_VECTOR (i, db.Attrib.Defs) 809 Write_UInt32DefVector_numDefined(db.Attrib, numDefined);
729 {
730 if (db.Attrib.Defs[i])
731 WriteUInt32(db.Attrib.Vals[i]);
732 }
733 } 810 }
734 } 811 }
735 812
@@ -765,13 +842,7 @@ void COutArchive::WriteHeader(
765 842
766 WriteByte(NID::kParent); 843 WriteByte(NID::kParent);
767 WriteNumber(dataSize); 844 WriteNumber(dataSize);
768 if (numIsDir == boolVector.Size()) 845 Write_BoolVector_numDefined(boolVector, numIsDir);
769 WriteByte(1);
770 else
771 {
772 WriteByte(0);
773 WriteBoolVector(boolVector);
774 }
775 for (i = 0; i < db.Files.Size(); i++) 846 for (i = 0; i < db.Files.Size(); i++)
776 { 847 {
777 const CFileItem &file = db.Files[i]; 848 const CFileItem &file = db.Files[i];
@@ -818,17 +889,17 @@ HRESULT COutArchive::WriteDatabase(
818 if (!db.CheckNumFiles()) 889 if (!db.CheckNumFiles())
819 return E_FAIL; 890 return E_FAIL;
820 891
821 UInt64 headerOffset; 892 CStartHeader sh;
822 UInt32 headerCRC; 893 sh.NextHeaderOffset = 0;
823 UInt64 headerSize; 894 sh.NextHeaderSize = 0;
824 if (db.IsEmpty()) 895 sh.NextHeaderCRC = 0; // CrcCalc(NULL, 0);
825 { 896
826 headerSize = 0; 897 if (!db.IsEmpty())
827 headerOffset = 0;
828 headerCRC = CrcCalc(NULL, 0);
829 }
830 else
831 { 898 {
899 CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> crcStream;
900 crcStream->SetStream(SeqStream);
901 crcStream->Init();
902
832 bool encodeHeaders = false; 903 bool encodeHeaders = false;
833 if (options) 904 if (options)
834 if (options->IsEmpty()) 905 if (options->IsEmpty())
@@ -837,13 +908,15 @@ HRESULT COutArchive::WriteDatabase(
837 if (options->PasswordIsDefined || headerOptions.CompressMainHeader) 908 if (options->PasswordIsDefined || headerOptions.CompressMainHeader)
838 encodeHeaders = true; 909 encodeHeaders = true;
839 910
840 _outByte.SetStream(SeqStream); 911 if (!_outByte.Create(1 << 16))
912 return E_OUTOFMEMORY;
913 _outByte.SetStream(crcStream.Interface());
841 _outByte.Init(); 914 _outByte.Init();
842 _crc = CRC_INIT_VAL; 915 // _crc = CRC_INIT_VAL;
843 _countMode = encodeHeaders; 916 _countMode = encodeHeaders;
844 _writeToStream = true; 917 _writeToStream = true;
845 _countSize = 0; 918 _countSize = 0;
846 WriteHeader(db, /* headerOptions, */ headerOffset); 919 WriteHeader(db, /* headerOptions, */ sh.NextHeaderOffset);
847 920
848 if (encodeHeaders) 921 if (encodeHeaders)
849 { 922 {
@@ -852,7 +925,7 @@ HRESULT COutArchive::WriteDatabase(
852 925
853 _countMode = false; 926 _countMode = false;
854 _writeToStream = false; 927 _writeToStream = false;
855 WriteHeader(db, /* headerOptions, */ headerOffset); 928 WriteHeader(db, /* headerOptions, */ sh.NextHeaderOffset);
856 929
857 if (_countSize != _outByte2.GetPos()) 930 if (_countSize != _outByte2.GetPos())
858 return E_FAIL; 931 return E_FAIL;
@@ -876,15 +949,17 @@ HRESULT COutArchive::WriteDatabase(
876 throw 1; 949 throw 1;
877 950
878 WriteID(NID::kEncodedHeader); 951 WriteID(NID::kEncodedHeader);
879 WritePackInfo(headerOffset, packSizes, CUInt32DefVector()); 952 WritePackInfo(sh.NextHeaderOffset, packSizes, CUInt32DefVector());
880 WriteUnpackInfo(folders, outFolders); 953 WriteUnpackInfo(folders, outFolders);
881 WriteByte(NID::kEnd); 954 WriteByte(NID::kEnd);
882 FOR_VECTOR (i, packSizes) 955
883 headerOffset += packSizes[i]; 956 sh.NextHeaderOffset += UInt64Vector_CountSum(packSizes);
884 } 957 }
885 RINOK(_outByte.Flush()) 958 RINOK(_outByte.Flush())
886 headerCRC = CRC_GET_DIGEST(_crc); 959 sh.NextHeaderCRC = crcStream->GetCRC();
887 headerSize = _outByte.GetProcessedSize(); 960 // sh.NextHeaderCRC = CRC_GET_DIGEST(_crc);
961 // if (CRC_GET_DIGEST(_crc) != sh.NextHeaderCRC) throw 1;
962 sh.NextHeaderSize = _outByte.GetProcessedSize();
888 } 963 }
889 #ifdef Z7_7Z_VOL 964 #ifdef Z7_7Z_VOL
890 if (_endMarker) 965 if (_endMarker)
@@ -904,12 +979,8 @@ HRESULT COutArchive::WriteDatabase(
904 #endif 979 #endif
905 if (Stream) 980 if (Stream)
906 { 981 {
907 CStartHeader h;
908 h.NextHeaderSize = headerSize;
909 h.NextHeaderCRC = headerCRC;
910 h.NextHeaderOffset = headerOffset;
911 RINOK(Stream->Seek((Int64)_signatureHeaderPos, STREAM_SEEK_SET, NULL)) 982 RINOK(Stream->Seek((Int64)_signatureHeaderPos, STREAM_SEEK_SET, NULL))
912 return WriteStartHeader(h); 983 return WriteStartHeader(sh);
913 } 984 }
914 return S_OK; 985 return S_OK;
915} 986}