1*f6dc9357SAndroid Build Coastguard Worker // 7zOut.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/7zCrc.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/CpuArch.h"
7*f6dc9357SAndroid Build Coastguard Worker
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/AutoPtr.h"
9*f6dc9357SAndroid Build Coastguard Worker // #include "../../../Common/UTFConvert.h"
10*f6dc9357SAndroid Build Coastguard Worker
11*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamObjects.h"
12*f6dc9357SAndroid Build Coastguard Worker #include "../Common/OutStreamWithCRC.h"
13*f6dc9357SAndroid Build Coastguard Worker
14*f6dc9357SAndroid Build Coastguard Worker #include "7zOut.h"
15*f6dc9357SAndroid Build Coastguard Worker
16*f6dc9357SAndroid Build Coastguard Worker unsigned BoolVector_CountSum(const CBoolVector &v);
17*f6dc9357SAndroid Build Coastguard Worker
UInt64Vector_CountSum(const CRecordVector<UInt64> & v)18*f6dc9357SAndroid Build Coastguard Worker static UInt64 UInt64Vector_CountSum(const CRecordVector<UInt64> &v)
19*f6dc9357SAndroid Build Coastguard Worker {
20*f6dc9357SAndroid Build Coastguard Worker UInt64 sum = 0;
21*f6dc9357SAndroid Build Coastguard Worker const unsigned size = v.Size();
22*f6dc9357SAndroid Build Coastguard Worker if (size)
23*f6dc9357SAndroid Build Coastguard Worker {
24*f6dc9357SAndroid Build Coastguard Worker const UInt64 *p = v.ConstData();
25*f6dc9357SAndroid Build Coastguard Worker const UInt64 * const lim = p + size;
26*f6dc9357SAndroid Build Coastguard Worker do
27*f6dc9357SAndroid Build Coastguard Worker sum += *p++;
28*f6dc9357SAndroid Build Coastguard Worker while (p != lim);
29*f6dc9357SAndroid Build Coastguard Worker }
30*f6dc9357SAndroid Build Coastguard Worker return sum;
31*f6dc9357SAndroid Build Coastguard Worker }
32*f6dc9357SAndroid Build Coastguard Worker
33*f6dc9357SAndroid Build Coastguard Worker
34*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
35*f6dc9357SAndroid Build Coastguard Worker namespace N7z {
36*f6dc9357SAndroid Build Coastguard Worker
FillSignature(Byte * buf)37*f6dc9357SAndroid Build Coastguard Worker static void FillSignature(Byte *buf)
38*f6dc9357SAndroid Build Coastguard Worker {
39*f6dc9357SAndroid Build Coastguard Worker memcpy(buf, kSignature, kSignatureSize);
40*f6dc9357SAndroid Build Coastguard Worker buf[kSignatureSize] = kMajorVersion;
41*f6dc9357SAndroid Build Coastguard Worker buf[kSignatureSize + 1] = 4;
42*f6dc9357SAndroid Build Coastguard Worker }
43*f6dc9357SAndroid Build Coastguard Worker
44*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_7Z_VOL
WriteFinishSignature()45*f6dc9357SAndroid Build Coastguard Worker HRESULT COutArchive::WriteFinishSignature()
46*f6dc9357SAndroid Build Coastguard Worker {
47*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteDirect(kFinishSignature, kSignatureSize));
48*f6dc9357SAndroid Build Coastguard Worker CArchiveVersion av;
49*f6dc9357SAndroid Build Coastguard Worker av.Major = kMajorVersion;
50*f6dc9357SAndroid Build Coastguard Worker av.Minor = 2;
51*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteDirectByte(av.Major));
52*f6dc9357SAndroid Build Coastguard Worker return WriteDirectByte(av.Minor);
53*f6dc9357SAndroid Build Coastguard Worker }
54*f6dc9357SAndroid Build Coastguard Worker #endif
55*f6dc9357SAndroid Build Coastguard Worker
SetUInt32(Byte * p,UInt32 d)56*f6dc9357SAndroid Build Coastguard Worker static void SetUInt32(Byte *p, UInt32 d)
57*f6dc9357SAndroid Build Coastguard Worker {
58*f6dc9357SAndroid Build Coastguard Worker for (int i = 0; i < 4; i++, d >>= 8)
59*f6dc9357SAndroid Build Coastguard Worker p[i] = (Byte)d;
60*f6dc9357SAndroid Build Coastguard Worker }
61*f6dc9357SAndroid Build Coastguard Worker
SetUInt64(Byte * p,UInt64 d)62*f6dc9357SAndroid Build Coastguard Worker static void SetUInt64(Byte *p, UInt64 d)
63*f6dc9357SAndroid Build Coastguard Worker {
64*f6dc9357SAndroid Build Coastguard Worker for (int i = 0; i < 8; i++, d >>= 8)
65*f6dc9357SAndroid Build Coastguard Worker p[i] = (Byte)d;
66*f6dc9357SAndroid Build Coastguard Worker }
67*f6dc9357SAndroid Build Coastguard Worker
WriteStartHeader(const CStartHeader & h)68*f6dc9357SAndroid Build Coastguard Worker HRESULT COutArchive::WriteStartHeader(const CStartHeader &h)
69*f6dc9357SAndroid Build Coastguard Worker {
70*f6dc9357SAndroid Build Coastguard Worker Byte buf[32];
71*f6dc9357SAndroid Build Coastguard Worker FillSignature(buf);
72*f6dc9357SAndroid Build Coastguard Worker SetUInt64(buf + 8 + 4, h.NextHeaderOffset);
73*f6dc9357SAndroid Build Coastguard Worker SetUInt64(buf + 8 + 12, h.NextHeaderSize);
74*f6dc9357SAndroid Build Coastguard Worker SetUInt32(buf + 8 + 20, h.NextHeaderCRC);
75*f6dc9357SAndroid Build Coastguard Worker SetUInt32(buf + 8, CrcCalc(buf + 8 + 4, 20));
76*f6dc9357SAndroid Build Coastguard Worker return WriteDirect(buf, sizeof(buf));
77*f6dc9357SAndroid Build Coastguard Worker }
78*f6dc9357SAndroid Build Coastguard Worker
79*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_7Z_VOL
WriteFinishHeader(const CFinishHeader & h)80*f6dc9357SAndroid Build Coastguard Worker HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h)
81*f6dc9357SAndroid Build Coastguard Worker {
82*f6dc9357SAndroid Build Coastguard Worker CCRC crc;
83*f6dc9357SAndroid Build Coastguard Worker crc.UpdateUInt64(h.NextHeaderOffset);
84*f6dc9357SAndroid Build Coastguard Worker crc.UpdateUInt64(h.NextHeaderSize);
85*f6dc9357SAndroid Build Coastguard Worker crc.UpdateUInt32(h.NextHeaderCRC);
86*f6dc9357SAndroid Build Coastguard Worker crc.UpdateUInt64(h.ArchiveStartOffset);
87*f6dc9357SAndroid Build Coastguard Worker crc.UpdateUInt64(h.AdditionalStartBlockSize);
88*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteDirectUInt32(crc.GetDigest()));
89*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteDirectUInt64(h.NextHeaderOffset));
90*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteDirectUInt64(h.NextHeaderSize));
91*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteDirectUInt32(h.NextHeaderCRC));
92*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteDirectUInt64(h.ArchiveStartOffset));
93*f6dc9357SAndroid Build Coastguard Worker return WriteDirectUInt64(h.AdditionalStartBlockSize);
94*f6dc9357SAndroid Build Coastguard Worker }
95*f6dc9357SAndroid Build Coastguard Worker #endif
96*f6dc9357SAndroid Build Coastguard Worker
Create_and_WriteStartPrefix(ISequentialOutStream * stream)97*f6dc9357SAndroid Build Coastguard Worker HRESULT COutArchive::Create_and_WriteStartPrefix(ISequentialOutStream *stream /* , bool endMarker */)
98*f6dc9357SAndroid Build Coastguard Worker {
99*f6dc9357SAndroid Build Coastguard Worker Close();
100*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_7Z_VOL
101*f6dc9357SAndroid Build Coastguard Worker // endMarker = false;
102*f6dc9357SAndroid Build Coastguard Worker _endMarker = endMarker;
103*f6dc9357SAndroid Build Coastguard Worker #endif
104*f6dc9357SAndroid Build Coastguard Worker SeqStream = stream;
105*f6dc9357SAndroid Build Coastguard Worker // if (!endMarker)
106*f6dc9357SAndroid Build Coastguard Worker {
107*f6dc9357SAndroid Build Coastguard Worker SeqStream.QueryInterface(IID_IOutStream, &Stream);
108*f6dc9357SAndroid Build Coastguard Worker if (!Stream)
109*f6dc9357SAndroid Build Coastguard Worker {
110*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
111*f6dc9357SAndroid Build Coastguard Worker // endMarker = true;
112*f6dc9357SAndroid Build Coastguard Worker }
113*f6dc9357SAndroid Build Coastguard Worker RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_signatureHeaderPos))
114*f6dc9357SAndroid Build Coastguard Worker Byte buf[32];
115*f6dc9357SAndroid Build Coastguard Worker FillSignature(buf);
116*f6dc9357SAndroid Build Coastguard Worker memset(&buf[8], 0, 32 - 8);
117*f6dc9357SAndroid Build Coastguard Worker return WriteDirect(buf, sizeof(buf));
118*f6dc9357SAndroid Build Coastguard Worker }
119*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_7Z_VOL
120*f6dc9357SAndroid Build Coastguard Worker if (endMarker)
121*f6dc9357SAndroid Build Coastguard Worker {
122*f6dc9357SAndroid Build Coastguard Worker /*
123*f6dc9357SAndroid Build Coastguard Worker CStartHeader sh;
124*f6dc9357SAndroid Build Coastguard Worker sh.NextHeaderOffset = (UInt32)(Int32)-1;
125*f6dc9357SAndroid Build Coastguard Worker sh.NextHeaderSize = (UInt32)(Int32)-1;
126*f6dc9357SAndroid Build Coastguard Worker sh.NextHeaderCRC = 0;
127*f6dc9357SAndroid Build Coastguard Worker WriteStartHeader(sh);
128*f6dc9357SAndroid Build Coastguard Worker return S_OK;
129*f6dc9357SAndroid Build Coastguard Worker */
130*f6dc9357SAndroid Build Coastguard Worker }
131*f6dc9357SAndroid Build Coastguard Worker #endif
132*f6dc9357SAndroid Build Coastguard Worker }
133*f6dc9357SAndroid Build Coastguard Worker
Close()134*f6dc9357SAndroid Build Coastguard Worker void COutArchive::Close()
135*f6dc9357SAndroid Build Coastguard Worker {
136*f6dc9357SAndroid Build Coastguard Worker SeqStream.Release();
137*f6dc9357SAndroid Build Coastguard Worker Stream.Release();
138*f6dc9357SAndroid Build Coastguard Worker }
139*f6dc9357SAndroid Build Coastguard Worker
GetPos() const140*f6dc9357SAndroid Build Coastguard Worker UInt64 COutArchive::GetPos() const
141*f6dc9357SAndroid Build Coastguard Worker {
142*f6dc9357SAndroid Build Coastguard Worker if (_countMode)
143*f6dc9357SAndroid Build Coastguard Worker return _countSize;
144*f6dc9357SAndroid Build Coastguard Worker if (_writeToStream)
145*f6dc9357SAndroid Build Coastguard Worker return _outByte.GetProcessedSize();
146*f6dc9357SAndroid Build Coastguard Worker return _outByte2.GetPos();
147*f6dc9357SAndroid Build Coastguard Worker }
148*f6dc9357SAndroid Build Coastguard Worker
WriteBytes(const void * data,size_t size)149*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteBytes(const void *data, size_t size)
150*f6dc9357SAndroid Build Coastguard Worker {
151*f6dc9357SAndroid Build Coastguard Worker if (_countMode)
152*f6dc9357SAndroid Build Coastguard Worker _countSize += size;
153*f6dc9357SAndroid Build Coastguard Worker else if (_writeToStream)
154*f6dc9357SAndroid Build Coastguard Worker {
155*f6dc9357SAndroid Build Coastguard Worker _outByte.WriteBytes(data, size);
156*f6dc9357SAndroid Build Coastguard Worker // _crc = CrcUpdate(_crc, data, size);
157*f6dc9357SAndroid Build Coastguard Worker }
158*f6dc9357SAndroid Build Coastguard Worker else
159*f6dc9357SAndroid Build Coastguard Worker _outByte2.WriteBytes(data, size);
160*f6dc9357SAndroid Build Coastguard Worker }
161*f6dc9357SAndroid Build Coastguard Worker
WriteByte(Byte b)162*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteByte(Byte b)
163*f6dc9357SAndroid Build Coastguard Worker {
164*f6dc9357SAndroid Build Coastguard Worker if (_countMode)
165*f6dc9357SAndroid Build Coastguard Worker _countSize++;
166*f6dc9357SAndroid Build Coastguard Worker else if (_writeToStream)
167*f6dc9357SAndroid Build Coastguard Worker WriteByte_ToStream(b);
168*f6dc9357SAndroid Build Coastguard Worker else
169*f6dc9357SAndroid Build Coastguard Worker _outByte2.WriteByte(b);
170*f6dc9357SAndroid Build Coastguard Worker }
171*f6dc9357SAndroid Build Coastguard Worker
172*f6dc9357SAndroid Build Coastguard Worker /*
173*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteUInt32(UInt32 value)
174*f6dc9357SAndroid Build Coastguard Worker {
175*f6dc9357SAndroid Build Coastguard Worker for (int i = 0; i < 4; i++)
176*f6dc9357SAndroid Build Coastguard Worker {
177*f6dc9357SAndroid Build Coastguard Worker WriteByte((Byte)value);
178*f6dc9357SAndroid Build Coastguard Worker value >>= 8;
179*f6dc9357SAndroid Build Coastguard Worker }
180*f6dc9357SAndroid Build Coastguard Worker }
181*f6dc9357SAndroid Build Coastguard Worker
182*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteUInt64(UInt64 value)
183*f6dc9357SAndroid Build Coastguard Worker {
184*f6dc9357SAndroid Build Coastguard Worker for (int i = 0; i < 8; i++)
185*f6dc9357SAndroid Build Coastguard Worker {
186*f6dc9357SAndroid Build Coastguard Worker WriteByte((Byte)value);
187*f6dc9357SAndroid Build Coastguard Worker value >>= 8;
188*f6dc9357SAndroid Build Coastguard Worker }
189*f6dc9357SAndroid Build Coastguard Worker }
190*f6dc9357SAndroid Build Coastguard Worker */
191*f6dc9357SAndroid Build Coastguard Worker
WriteNumber(UInt64 value)192*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteNumber(UInt64 value)
193*f6dc9357SAndroid Build Coastguard Worker {
194*f6dc9357SAndroid Build Coastguard Worker Byte firstByte = 0;
195*f6dc9357SAndroid Build Coastguard Worker Byte mask = 0x80;
196*f6dc9357SAndroid Build Coastguard Worker int i;
197*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < 8; i++)
198*f6dc9357SAndroid Build Coastguard Worker {
199*f6dc9357SAndroid Build Coastguard Worker if (value < ((UInt64(1) << ( 7 * (i + 1)))))
200*f6dc9357SAndroid Build Coastguard Worker {
201*f6dc9357SAndroid Build Coastguard Worker firstByte |= Byte(value >> (8 * i));
202*f6dc9357SAndroid Build Coastguard Worker break;
203*f6dc9357SAndroid Build Coastguard Worker }
204*f6dc9357SAndroid Build Coastguard Worker firstByte |= mask;
205*f6dc9357SAndroid Build Coastguard Worker mask = (Byte)(mask >> 1);
206*f6dc9357SAndroid Build Coastguard Worker }
207*f6dc9357SAndroid Build Coastguard Worker WriteByte(firstByte);
208*f6dc9357SAndroid Build Coastguard Worker for (; i > 0; i--)
209*f6dc9357SAndroid Build Coastguard Worker {
210*f6dc9357SAndroid Build Coastguard Worker WriteByte((Byte)value);
211*f6dc9357SAndroid Build Coastguard Worker value >>= 8;
212*f6dc9357SAndroid Build Coastguard Worker }
213*f6dc9357SAndroid Build Coastguard Worker }
214*f6dc9357SAndroid Build Coastguard Worker
GetBigNumberSize(UInt64 value)215*f6dc9357SAndroid Build Coastguard Worker static unsigned GetBigNumberSize(UInt64 value)
216*f6dc9357SAndroid Build Coastguard Worker {
217*f6dc9357SAndroid Build Coastguard Worker unsigned i;
218*f6dc9357SAndroid Build Coastguard Worker for (i = 1; i < 9; i++)
219*f6dc9357SAndroid Build Coastguard Worker if (value < (((UInt64)1 << (i * 7))))
220*f6dc9357SAndroid Build Coastguard Worker break;
221*f6dc9357SAndroid Build Coastguard Worker return i;
222*f6dc9357SAndroid Build Coastguard Worker }
223*f6dc9357SAndroid Build Coastguard Worker
224*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_7Z_VOL
GetVolHeadersSize(UInt64 dataSize,int nameLength,bool props)225*f6dc9357SAndroid Build Coastguard Worker UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props)
226*f6dc9357SAndroid Build Coastguard Worker {
227*f6dc9357SAndroid Build Coastguard Worker UInt32 result = GetBigNumberSize(dataSize) * 2 + 41;
228*f6dc9357SAndroid Build Coastguard Worker if (nameLength != 0)
229*f6dc9357SAndroid Build Coastguard Worker {
230*f6dc9357SAndroid Build Coastguard Worker nameLength = (nameLength + 1) * 2;
231*f6dc9357SAndroid Build Coastguard Worker result += nameLength + GetBigNumberSize(nameLength) + 2;
232*f6dc9357SAndroid Build Coastguard Worker }
233*f6dc9357SAndroid Build Coastguard Worker if (props)
234*f6dc9357SAndroid Build Coastguard Worker {
235*f6dc9357SAndroid Build Coastguard Worker result += 20;
236*f6dc9357SAndroid Build Coastguard Worker }
237*f6dc9357SAndroid Build Coastguard Worker if (result >= 128)
238*f6dc9357SAndroid Build Coastguard Worker result++;
239*f6dc9357SAndroid Build Coastguard Worker result += kSignatureSize + 2 + kFinishHeaderSize;
240*f6dc9357SAndroid Build Coastguard Worker return result;
241*f6dc9357SAndroid Build Coastguard Worker }
242*f6dc9357SAndroid Build Coastguard Worker
GetVolPureSize(UInt64 volSize,int nameLength,bool props)243*f6dc9357SAndroid Build Coastguard Worker UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props)
244*f6dc9357SAndroid Build Coastguard Worker {
245*f6dc9357SAndroid Build Coastguard Worker UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props);
246*f6dc9357SAndroid Build Coastguard Worker int testSize;
247*f6dc9357SAndroid Build Coastguard Worker if (volSize > headersSizeBase)
248*f6dc9357SAndroid Build Coastguard Worker testSize = volSize - headersSizeBase;
249*f6dc9357SAndroid Build Coastguard Worker else
250*f6dc9357SAndroid Build Coastguard Worker testSize = 1;
251*f6dc9357SAndroid Build Coastguard Worker UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props);
252*f6dc9357SAndroid Build Coastguard Worker UInt64 pureSize = 1;
253*f6dc9357SAndroid Build Coastguard Worker if (volSize > headersSize)
254*f6dc9357SAndroid Build Coastguard Worker pureSize = volSize - headersSize;
255*f6dc9357SAndroid Build Coastguard Worker return pureSize;
256*f6dc9357SAndroid Build Coastguard Worker }
257*f6dc9357SAndroid Build Coastguard Worker #endif
258*f6dc9357SAndroid Build Coastguard Worker
WriteFolder(const CFolder & folder)259*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteFolder(const CFolder &folder)
260*f6dc9357SAndroid Build Coastguard Worker {
261*f6dc9357SAndroid Build Coastguard Worker WriteNumber(folder.Coders.Size());
262*f6dc9357SAndroid Build Coastguard Worker unsigned i;
263*f6dc9357SAndroid Build Coastguard Worker
264*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < folder.Coders.Size(); i++)
265*f6dc9357SAndroid Build Coastguard Worker {
266*f6dc9357SAndroid Build Coastguard Worker const CCoderInfo &coder = folder.Coders[i];
267*f6dc9357SAndroid Build Coastguard Worker {
268*f6dc9357SAndroid Build Coastguard Worker UInt64 id = coder.MethodID;
269*f6dc9357SAndroid Build Coastguard Worker unsigned idSize;
270*f6dc9357SAndroid Build Coastguard Worker for (idSize = 1; idSize < sizeof(id); idSize++)
271*f6dc9357SAndroid Build Coastguard Worker if ((id >> (8 * idSize)) == 0)
272*f6dc9357SAndroid Build Coastguard Worker break;
273*f6dc9357SAndroid Build Coastguard Worker // idSize &= 0xF; // idSize is smaller than 16 already
274*f6dc9357SAndroid Build Coastguard Worker Byte temp[16];
275*f6dc9357SAndroid Build Coastguard Worker for (unsigned t = idSize; t != 0; t--, id >>= 8)
276*f6dc9357SAndroid Build Coastguard Worker temp[t] = (Byte)(id & 0xFF);
277*f6dc9357SAndroid Build Coastguard Worker
278*f6dc9357SAndroid Build Coastguard Worker unsigned b = idSize;
279*f6dc9357SAndroid Build Coastguard Worker const bool isComplex = !coder.IsSimpleCoder();
280*f6dc9357SAndroid Build Coastguard Worker b |= (isComplex ? 0x10 : 0);
281*f6dc9357SAndroid Build Coastguard Worker
282*f6dc9357SAndroid Build Coastguard Worker const size_t propsSize = coder.Props.Size();
283*f6dc9357SAndroid Build Coastguard Worker b |= ((propsSize != 0) ? 0x20 : 0);
284*f6dc9357SAndroid Build Coastguard Worker temp[0] = (Byte)b;
285*f6dc9357SAndroid Build Coastguard Worker WriteBytes(temp, idSize + 1);
286*f6dc9357SAndroid Build Coastguard Worker if (isComplex)
287*f6dc9357SAndroid Build Coastguard Worker {
288*f6dc9357SAndroid Build Coastguard Worker WriteNumber(coder.NumStreams);
289*f6dc9357SAndroid Build Coastguard Worker WriteNumber(1); // NumOutStreams;
290*f6dc9357SAndroid Build Coastguard Worker }
291*f6dc9357SAndroid Build Coastguard Worker if (propsSize == 0)
292*f6dc9357SAndroid Build Coastguard Worker continue;
293*f6dc9357SAndroid Build Coastguard Worker WriteNumber(propsSize);
294*f6dc9357SAndroid Build Coastguard Worker WriteBytes(coder.Props, propsSize);
295*f6dc9357SAndroid Build Coastguard Worker }
296*f6dc9357SAndroid Build Coastguard Worker }
297*f6dc9357SAndroid Build Coastguard Worker
298*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < folder.Bonds.Size(); i++)
299*f6dc9357SAndroid Build Coastguard Worker {
300*f6dc9357SAndroid Build Coastguard Worker const CBond &bond = folder.Bonds[i];
301*f6dc9357SAndroid Build Coastguard Worker WriteNumber(bond.PackIndex);
302*f6dc9357SAndroid Build Coastguard Worker WriteNumber(bond.UnpackIndex);
303*f6dc9357SAndroid Build Coastguard Worker }
304*f6dc9357SAndroid Build Coastguard Worker
305*f6dc9357SAndroid Build Coastguard Worker if (folder.PackStreams.Size() > 1)
306*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < folder.PackStreams.Size(); i++)
307*f6dc9357SAndroid Build Coastguard Worker WriteNumber(folder.PackStreams[i]);
308*f6dc9357SAndroid Build Coastguard Worker }
309*f6dc9357SAndroid Build Coastguard Worker
Write_BoolVector(const CBoolVector & boolVector)310*f6dc9357SAndroid Build Coastguard Worker void COutArchive::Write_BoolVector(const CBoolVector &boolVector)
311*f6dc9357SAndroid Build Coastguard Worker {
312*f6dc9357SAndroid Build Coastguard Worker Byte b = 0;
313*f6dc9357SAndroid Build Coastguard Worker Byte mask = 0x80;
314*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, boolVector)
315*f6dc9357SAndroid Build Coastguard Worker {
316*f6dc9357SAndroid Build Coastguard Worker if (boolVector[i])
317*f6dc9357SAndroid Build Coastguard Worker b |= mask;
318*f6dc9357SAndroid Build Coastguard Worker mask = (Byte)(mask >> 1);
319*f6dc9357SAndroid Build Coastguard Worker if (mask == 0)
320*f6dc9357SAndroid Build Coastguard Worker {
321*f6dc9357SAndroid Build Coastguard Worker WriteByte(b);
322*f6dc9357SAndroid Build Coastguard Worker mask = 0x80;
323*f6dc9357SAndroid Build Coastguard Worker b = 0;
324*f6dc9357SAndroid Build Coastguard Worker }
325*f6dc9357SAndroid Build Coastguard Worker }
326*f6dc9357SAndroid Build Coastguard Worker if (mask != 0x80)
327*f6dc9357SAndroid Build Coastguard Worker WriteByte(b);
328*f6dc9357SAndroid Build Coastguard Worker }
329*f6dc9357SAndroid Build Coastguard Worker
Bv_GetSizeInBytes(const CBoolVector & v)330*f6dc9357SAndroid Build Coastguard Worker static inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; }
331*f6dc9357SAndroid Build Coastguard Worker
WritePropBoolVector(Byte id,const CBoolVector & boolVector)332*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector)
333*f6dc9357SAndroid Build Coastguard Worker {
334*f6dc9357SAndroid Build Coastguard Worker WriteByte(id);
335*f6dc9357SAndroid Build Coastguard Worker WriteNumber(Bv_GetSizeInBytes(boolVector));
336*f6dc9357SAndroid Build Coastguard Worker Write_BoolVector(boolVector);
337*f6dc9357SAndroid Build Coastguard Worker }
338*f6dc9357SAndroid Build Coastguard Worker
Write_BoolVector_numDefined(const CBoolVector & boolVector,unsigned numDefined)339*f6dc9357SAndroid Build Coastguard Worker void COutArchive::Write_BoolVector_numDefined(const CBoolVector &boolVector, unsigned numDefined)
340*f6dc9357SAndroid Build Coastguard Worker {
341*f6dc9357SAndroid Build Coastguard Worker if (numDefined == boolVector.Size())
342*f6dc9357SAndroid Build Coastguard Worker WriteByte(1);
343*f6dc9357SAndroid Build Coastguard Worker else
344*f6dc9357SAndroid Build Coastguard Worker {
345*f6dc9357SAndroid Build Coastguard Worker WriteByte(0);
346*f6dc9357SAndroid Build Coastguard Worker Write_BoolVector(boolVector);
347*f6dc9357SAndroid Build Coastguard Worker }
348*f6dc9357SAndroid Build Coastguard Worker }
349*f6dc9357SAndroid Build Coastguard Worker
350*f6dc9357SAndroid Build Coastguard Worker
WriteHashDigests(const CUInt32DefVector & digests)351*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteHashDigests(const CUInt32DefVector &digests)
352*f6dc9357SAndroid Build Coastguard Worker {
353*f6dc9357SAndroid Build Coastguard Worker const unsigned numDefined = BoolVector_CountSum(digests.Defs);
354*f6dc9357SAndroid Build Coastguard Worker if (numDefined == 0)
355*f6dc9357SAndroid Build Coastguard Worker return;
356*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kCRC);
357*f6dc9357SAndroid Build Coastguard Worker Write_BoolVector_numDefined(digests.Defs, numDefined);
358*f6dc9357SAndroid Build Coastguard Worker Write_UInt32DefVector_numDefined(digests, numDefined);
359*f6dc9357SAndroid Build Coastguard Worker }
360*f6dc9357SAndroid Build Coastguard Worker
361*f6dc9357SAndroid Build Coastguard Worker
WritePackInfo(UInt64 dataOffset,const CRecordVector<UInt64> & packSizes,const CUInt32DefVector & packCRCs)362*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WritePackInfo(
363*f6dc9357SAndroid Build Coastguard Worker UInt64 dataOffset,
364*f6dc9357SAndroid Build Coastguard Worker const CRecordVector<UInt64> &packSizes,
365*f6dc9357SAndroid Build Coastguard Worker const CUInt32DefVector &packCRCs)
366*f6dc9357SAndroid Build Coastguard Worker {
367*f6dc9357SAndroid Build Coastguard Worker if (packSizes.IsEmpty())
368*f6dc9357SAndroid Build Coastguard Worker return;
369*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kPackInfo);
370*f6dc9357SAndroid Build Coastguard Worker WriteNumber(dataOffset);
371*f6dc9357SAndroid Build Coastguard Worker WriteNumber(packSizes.Size());
372*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kSize);
373*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, packSizes)
374*f6dc9357SAndroid Build Coastguard Worker WriteNumber(packSizes[i]);
375*f6dc9357SAndroid Build Coastguard Worker
376*f6dc9357SAndroid Build Coastguard Worker WriteHashDigests(packCRCs);
377*f6dc9357SAndroid Build Coastguard Worker
378*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kEnd);
379*f6dc9357SAndroid Build Coastguard Worker }
380*f6dc9357SAndroid Build Coastguard Worker
WriteUnpackInfo(const CObjectVector<CFolder> & folders,const COutFolders & outFolders)381*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders, const COutFolders &outFolders)
382*f6dc9357SAndroid Build Coastguard Worker {
383*f6dc9357SAndroid Build Coastguard Worker if (folders.IsEmpty())
384*f6dc9357SAndroid Build Coastguard Worker return;
385*f6dc9357SAndroid Build Coastguard Worker
386*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kUnpackInfo);
387*f6dc9357SAndroid Build Coastguard Worker
388*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kFolder);
389*f6dc9357SAndroid Build Coastguard Worker WriteNumber(folders.Size());
390*f6dc9357SAndroid Build Coastguard Worker {
391*f6dc9357SAndroid Build Coastguard Worker WriteByte(0);
392*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, folders)
393*f6dc9357SAndroid Build Coastguard Worker WriteFolder(folders[i]);
394*f6dc9357SAndroid Build Coastguard Worker }
395*f6dc9357SAndroid Build Coastguard Worker
396*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kCodersUnpackSize);
397*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, outFolders.CoderUnpackSizes)
398*f6dc9357SAndroid Build Coastguard Worker WriteNumber(outFolders.CoderUnpackSizes[i]);
399*f6dc9357SAndroid Build Coastguard Worker
400*f6dc9357SAndroid Build Coastguard Worker WriteHashDigests(outFolders.FolderUnpackCRCs);
401*f6dc9357SAndroid Build Coastguard Worker
402*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kEnd);
403*f6dc9357SAndroid Build Coastguard Worker }
404*f6dc9357SAndroid Build Coastguard Worker
WriteSubStreamsInfo(const CObjectVector<CFolder> & folders,const COutFolders & outFolders,const CRecordVector<UInt64> & unpackSizes,const CUInt32DefVector & digests)405*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteSubStreamsInfo(const CObjectVector<CFolder> &folders,
406*f6dc9357SAndroid Build Coastguard Worker const COutFolders &outFolders,
407*f6dc9357SAndroid Build Coastguard Worker const CRecordVector<UInt64> &unpackSizes,
408*f6dc9357SAndroid Build Coastguard Worker const CUInt32DefVector &digests)
409*f6dc9357SAndroid Build Coastguard Worker {
410*f6dc9357SAndroid Build Coastguard Worker const CRecordVector<CNum> &numUnpackStreamsInFolders = outFolders.NumUnpackStreamsVector;
411*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kSubStreamsInfo);
412*f6dc9357SAndroid Build Coastguard Worker
413*f6dc9357SAndroid Build Coastguard Worker unsigned i;
414*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
415*f6dc9357SAndroid Build Coastguard Worker if (numUnpackStreamsInFolders[i] != 1)
416*f6dc9357SAndroid Build Coastguard Worker {
417*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kNumUnpackStream);
418*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
419*f6dc9357SAndroid Build Coastguard Worker WriteNumber(numUnpackStreamsInFolders[i]);
420*f6dc9357SAndroid Build Coastguard Worker break;
421*f6dc9357SAndroid Build Coastguard Worker }
422*f6dc9357SAndroid Build Coastguard Worker
423*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
424*f6dc9357SAndroid Build Coastguard Worker if (numUnpackStreamsInFolders[i] > 1)
425*f6dc9357SAndroid Build Coastguard Worker {
426*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kSize);
427*f6dc9357SAndroid Build Coastguard Worker CNum index = 0;
428*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
429*f6dc9357SAndroid Build Coastguard Worker {
430*f6dc9357SAndroid Build Coastguard Worker CNum num = numUnpackStreamsInFolders[i];
431*f6dc9357SAndroid Build Coastguard Worker for (CNum j = 0; j < num; j++)
432*f6dc9357SAndroid Build Coastguard Worker {
433*f6dc9357SAndroid Build Coastguard Worker if (j + 1 != num)
434*f6dc9357SAndroid Build Coastguard Worker WriteNumber(unpackSizes[index]);
435*f6dc9357SAndroid Build Coastguard Worker index++;
436*f6dc9357SAndroid Build Coastguard Worker }
437*f6dc9357SAndroid Build Coastguard Worker }
438*f6dc9357SAndroid Build Coastguard Worker break;
439*f6dc9357SAndroid Build Coastguard Worker }
440*f6dc9357SAndroid Build Coastguard Worker
441*f6dc9357SAndroid Build Coastguard Worker CUInt32DefVector digests2;
442*f6dc9357SAndroid Build Coastguard Worker
443*f6dc9357SAndroid Build Coastguard Worker unsigned digestIndex = 0;
444*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < folders.Size(); i++)
445*f6dc9357SAndroid Build Coastguard Worker {
446*f6dc9357SAndroid Build Coastguard Worker unsigned numSubStreams = (unsigned)numUnpackStreamsInFolders[i];
447*f6dc9357SAndroid Build Coastguard Worker if (numSubStreams == 1 && outFolders.FolderUnpackCRCs.ValidAndDefined(i))
448*f6dc9357SAndroid Build Coastguard Worker digestIndex++;
449*f6dc9357SAndroid Build Coastguard Worker else
450*f6dc9357SAndroid Build Coastguard Worker for (unsigned j = 0; j < numSubStreams; j++, digestIndex++)
451*f6dc9357SAndroid Build Coastguard Worker {
452*f6dc9357SAndroid Build Coastguard Worker digests2.Defs.Add(digests.Defs[digestIndex]);
453*f6dc9357SAndroid Build Coastguard Worker digests2.Vals.Add(digests.Vals[digestIndex]);
454*f6dc9357SAndroid Build Coastguard Worker }
455*f6dc9357SAndroid Build Coastguard Worker }
456*f6dc9357SAndroid Build Coastguard Worker WriteHashDigests(digests2);
457*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kEnd);
458*f6dc9357SAndroid Build Coastguard Worker }
459*f6dc9357SAndroid Build Coastguard Worker
460*f6dc9357SAndroid Build Coastguard Worker // 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field.
461*f6dc9357SAndroid Build Coastguard Worker
SkipToAligned(unsigned pos,unsigned alignShifts)462*f6dc9357SAndroid Build Coastguard Worker void COutArchive::SkipToAligned(unsigned pos, unsigned alignShifts)
463*f6dc9357SAndroid Build Coastguard Worker {
464*f6dc9357SAndroid Build Coastguard Worker if (!_useAlign)
465*f6dc9357SAndroid Build Coastguard Worker return;
466*f6dc9357SAndroid Build Coastguard Worker
467*f6dc9357SAndroid Build Coastguard Worker const unsigned alignSize = (unsigned)1 << alignShifts;
468*f6dc9357SAndroid Build Coastguard Worker pos += (unsigned)GetPos();
469*f6dc9357SAndroid Build Coastguard Worker pos &= (alignSize - 1);
470*f6dc9357SAndroid Build Coastguard Worker if (pos == 0)
471*f6dc9357SAndroid Build Coastguard Worker return;
472*f6dc9357SAndroid Build Coastguard Worker unsigned skip = alignSize - pos;
473*f6dc9357SAndroid Build Coastguard Worker if (skip < 2)
474*f6dc9357SAndroid Build Coastguard Worker skip += alignSize;
475*f6dc9357SAndroid Build Coastguard Worker skip -= 2;
476*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kDummy);
477*f6dc9357SAndroid Build Coastguard Worker WriteByte((Byte)skip);
478*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < skip; i++)
479*f6dc9357SAndroid Build Coastguard Worker WriteByte(0);
480*f6dc9357SAndroid Build Coastguard Worker }
481*f6dc9357SAndroid Build Coastguard Worker
WriteAlignedBools(const CBoolVector & v,unsigned numDefined,Byte type,unsigned itemSizeShifts)482*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts)
483*f6dc9357SAndroid Build Coastguard Worker {
484*f6dc9357SAndroid Build Coastguard Worker const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v);
485*f6dc9357SAndroid Build Coastguard Worker const UInt64 dataSize = ((UInt64)numDefined << itemSizeShifts) + bvSize + 2;
486*f6dc9357SAndroid Build Coastguard Worker SkipToAligned(3 + bvSize + GetBigNumberSize(dataSize), itemSizeShifts);
487*f6dc9357SAndroid Build Coastguard Worker
488*f6dc9357SAndroid Build Coastguard Worker WriteByte(type);
489*f6dc9357SAndroid Build Coastguard Worker WriteNumber(dataSize);
490*f6dc9357SAndroid Build Coastguard Worker Write_BoolVector_numDefined(v, numDefined);
491*f6dc9357SAndroid Build Coastguard Worker WriteByte(0); // 0 means no switching to external stream
492*f6dc9357SAndroid Build Coastguard Worker }
493*f6dc9357SAndroid Build Coastguard Worker
494*f6dc9357SAndroid Build Coastguard Worker
Write_UInt32DefVector_numDefined(const CUInt32DefVector & v,unsigned numDefined)495*f6dc9357SAndroid Build Coastguard Worker void COutArchive::Write_UInt32DefVector_numDefined(const CUInt32DefVector &v, unsigned numDefined)
496*f6dc9357SAndroid Build Coastguard Worker {
497*f6dc9357SAndroid Build Coastguard Worker if (_countMode)
498*f6dc9357SAndroid Build Coastguard Worker {
499*f6dc9357SAndroid Build Coastguard Worker _countSize += (size_t)numDefined * 4;
500*f6dc9357SAndroid Build Coastguard Worker return;
501*f6dc9357SAndroid Build Coastguard Worker }
502*f6dc9357SAndroid Build Coastguard Worker
503*f6dc9357SAndroid Build Coastguard Worker const bool * const defs = v.Defs.ConstData();
504*f6dc9357SAndroid Build Coastguard Worker const UInt32 * const vals = v.Vals.ConstData();
505*f6dc9357SAndroid Build Coastguard Worker const size_t num = v.Defs.Size();
506*f6dc9357SAndroid Build Coastguard Worker
507*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0; i < num; i++)
508*f6dc9357SAndroid Build Coastguard Worker if (defs[i])
509*f6dc9357SAndroid Build Coastguard Worker {
510*f6dc9357SAndroid Build Coastguard Worker UInt32 value = vals[i];
511*f6dc9357SAndroid Build Coastguard Worker for (int k = 0; k < 4; k++)
512*f6dc9357SAndroid Build Coastguard Worker {
513*f6dc9357SAndroid Build Coastguard Worker if (_writeToStream)
514*f6dc9357SAndroid Build Coastguard Worker WriteByte_ToStream((Byte)value);
515*f6dc9357SAndroid Build Coastguard Worker else
516*f6dc9357SAndroid Build Coastguard Worker _outByte2.WriteByte((Byte)value);
517*f6dc9357SAndroid Build Coastguard Worker // WriteByte((Byte)value);
518*f6dc9357SAndroid Build Coastguard Worker value >>= 8;
519*f6dc9357SAndroid Build Coastguard Worker }
520*f6dc9357SAndroid Build Coastguard Worker // WriteUInt32(v.Vals[i]);
521*f6dc9357SAndroid Build Coastguard Worker }
522*f6dc9357SAndroid Build Coastguard Worker }
523*f6dc9357SAndroid Build Coastguard Worker
524*f6dc9357SAndroid Build Coastguard Worker
Write_UInt64DefVector_type(const CUInt64DefVector & v,Byte type)525*f6dc9357SAndroid Build Coastguard Worker void COutArchive::Write_UInt64DefVector_type(const CUInt64DefVector &v, Byte type)
526*f6dc9357SAndroid Build Coastguard Worker {
527*f6dc9357SAndroid Build Coastguard Worker const unsigned numDefined = BoolVector_CountSum(v.Defs);
528*f6dc9357SAndroid Build Coastguard Worker if (numDefined == 0)
529*f6dc9357SAndroid Build Coastguard Worker return;
530*f6dc9357SAndroid Build Coastguard Worker
531*f6dc9357SAndroid Build Coastguard Worker WriteAlignedBools(v.Defs, numDefined, type, 3);
532*f6dc9357SAndroid Build Coastguard Worker
533*f6dc9357SAndroid Build Coastguard Worker if (_countMode)
534*f6dc9357SAndroid Build Coastguard Worker {
535*f6dc9357SAndroid Build Coastguard Worker _countSize += (size_t)numDefined * 8;
536*f6dc9357SAndroid Build Coastguard Worker return;
537*f6dc9357SAndroid Build Coastguard Worker }
538*f6dc9357SAndroid Build Coastguard Worker
539*f6dc9357SAndroid Build Coastguard Worker const bool * const defs = v.Defs.ConstData();
540*f6dc9357SAndroid Build Coastguard Worker const UInt64 * const vals = v.Vals.ConstData();
541*f6dc9357SAndroid Build Coastguard Worker const size_t num = v.Defs.Size();
542*f6dc9357SAndroid Build Coastguard Worker
543*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0; i < num; i++)
544*f6dc9357SAndroid Build Coastguard Worker if (defs[i])
545*f6dc9357SAndroid Build Coastguard Worker {
546*f6dc9357SAndroid Build Coastguard Worker UInt64 value = vals[i];
547*f6dc9357SAndroid Build Coastguard Worker for (int k = 0; k < 8; k++)
548*f6dc9357SAndroid Build Coastguard Worker {
549*f6dc9357SAndroid Build Coastguard Worker if (_writeToStream)
550*f6dc9357SAndroid Build Coastguard Worker WriteByte_ToStream((Byte)value);
551*f6dc9357SAndroid Build Coastguard Worker else
552*f6dc9357SAndroid Build Coastguard Worker _outByte2.WriteByte((Byte)value);
553*f6dc9357SAndroid Build Coastguard Worker // WriteByte((Byte)value);
554*f6dc9357SAndroid Build Coastguard Worker value >>= 8;
555*f6dc9357SAndroid Build Coastguard Worker }
556*f6dc9357SAndroid Build Coastguard Worker // WriteUInt64(v.Vals[i]);
557*f6dc9357SAndroid Build Coastguard Worker }
558*f6dc9357SAndroid Build Coastguard Worker }
559*f6dc9357SAndroid Build Coastguard Worker
560*f6dc9357SAndroid Build Coastguard Worker
EncodeStream(DECL_EXTERNAL_CODECS_LOC_VARS CEncoder & encoder,const CByteBuffer & data,CRecordVector<UInt64> & packSizes,CObjectVector<CFolder> & folders,COutFolders & outFolders)561*f6dc9357SAndroid Build Coastguard Worker HRESULT COutArchive::EncodeStream(
562*f6dc9357SAndroid Build Coastguard Worker DECL_EXTERNAL_CODECS_LOC_VARS
563*f6dc9357SAndroid Build Coastguard Worker CEncoder &encoder, const CByteBuffer &data,
564*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders)
565*f6dc9357SAndroid Build Coastguard Worker {
566*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CBufInStream> streamSpec;
567*f6dc9357SAndroid Build Coastguard Worker streamSpec->Init(data, data.Size());
568*f6dc9357SAndroid Build Coastguard Worker outFolders.FolderUnpackCRCs.Defs.Add(true);
569*f6dc9357SAndroid Build Coastguard Worker outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size()));
570*f6dc9357SAndroid Build Coastguard Worker // outFolders.NumUnpackStreamsVector.Add(1);
571*f6dc9357SAndroid Build Coastguard Worker const UInt64 dataSize64 = data.Size();
572*f6dc9357SAndroid Build Coastguard Worker const UInt64 expectSize = data.Size();
573*f6dc9357SAndroid Build Coastguard Worker RINOK(encoder.Encode1(
574*f6dc9357SAndroid Build Coastguard Worker EXTERNAL_CODECS_LOC_VARS
575*f6dc9357SAndroid Build Coastguard Worker streamSpec,
576*f6dc9357SAndroid Build Coastguard Worker // NULL,
577*f6dc9357SAndroid Build Coastguard Worker &dataSize64, // inSizeForReduce
578*f6dc9357SAndroid Build Coastguard Worker expectSize,
579*f6dc9357SAndroid Build Coastguard Worker folders.AddNew(),
580*f6dc9357SAndroid Build Coastguard Worker // outFolders.CoderUnpackSizes, unpackSize,
581*f6dc9357SAndroid Build Coastguard Worker SeqStream, packSizes, NULL))
582*f6dc9357SAndroid Build Coastguard Worker if (!streamSpec->WasFinished())
583*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
584*f6dc9357SAndroid Build Coastguard Worker encoder.Encode_Post(dataSize64, outFolders.CoderUnpackSizes);
585*f6dc9357SAndroid Build Coastguard Worker return S_OK;
586*f6dc9357SAndroid Build Coastguard Worker }
587*f6dc9357SAndroid Build Coastguard Worker
WriteHeader(const CArchiveDatabaseOut & db,UInt64 & headerOffset)588*f6dc9357SAndroid Build Coastguard Worker void COutArchive::WriteHeader(
589*f6dc9357SAndroid Build Coastguard Worker const CArchiveDatabaseOut &db,
590*f6dc9357SAndroid Build Coastguard Worker // const CHeaderOptions &headerOptions,
591*f6dc9357SAndroid Build Coastguard Worker UInt64 &headerOffset)
592*f6dc9357SAndroid Build Coastguard Worker {
593*f6dc9357SAndroid Build Coastguard Worker /*
594*f6dc9357SAndroid Build Coastguard Worker bool thereIsSecure = (db.SecureBuf.Size() != 0);
595*f6dc9357SAndroid Build Coastguard Worker */
596*f6dc9357SAndroid Build Coastguard Worker _useAlign = true;
597*f6dc9357SAndroid Build Coastguard Worker
598*f6dc9357SAndroid Build Coastguard Worker headerOffset = UInt64Vector_CountSum(db.PackSizes);
599*f6dc9357SAndroid Build Coastguard Worker
600*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kHeader);
601*f6dc9357SAndroid Build Coastguard Worker
602*f6dc9357SAndroid Build Coastguard Worker /*
603*f6dc9357SAndroid Build Coastguard Worker {
604*f6dc9357SAndroid Build Coastguard Worker // It's example for per archive properies writing
605*f6dc9357SAndroid Build Coastguard Worker
606*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kArchiveProperties);
607*f6dc9357SAndroid Build Coastguard Worker
608*f6dc9357SAndroid Build Coastguard Worker // you must use random 40-bit number that will identify you
609*f6dc9357SAndroid Build Coastguard Worker // then you can use same kDeveloperID for any properties and methods
610*f6dc9357SAndroid Build Coastguard Worker const UInt64 kDeveloperID = 0x123456789A; // change that value to real random 40-bit number
611*f6dc9357SAndroid Build Coastguard Worker
612*f6dc9357SAndroid Build Coastguard Worker #define GENERATE_7Z_ID(developerID, subID) (((UInt64)0x3F << 56) | ((UInt64)developerID << 16) | subID)
613*f6dc9357SAndroid Build Coastguard Worker
614*f6dc9357SAndroid Build Coastguard Worker {
615*f6dc9357SAndroid Build Coastguard Worker const UInt64 kSubID = 0x1; // you can use small number for subID
616*f6dc9357SAndroid Build Coastguard Worker const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID);
617*f6dc9357SAndroid Build Coastguard Worker WriteNumber(kID);
618*f6dc9357SAndroid Build Coastguard Worker const unsigned kPropsSize = 3; // it's example size
619*f6dc9357SAndroid Build Coastguard Worker WriteNumber(kPropsSize);
620*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < kPropsSize; i++)
621*f6dc9357SAndroid Build Coastguard Worker WriteByte((Byte)(i & 0xFF));
622*f6dc9357SAndroid Build Coastguard Worker }
623*f6dc9357SAndroid Build Coastguard Worker {
624*f6dc9357SAndroid Build Coastguard Worker const UInt64 kSubID = 0x2; // you can use small number for subID
625*f6dc9357SAndroid Build Coastguard Worker const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID);
626*f6dc9357SAndroid Build Coastguard Worker WriteNumber(kID);
627*f6dc9357SAndroid Build Coastguard Worker const unsigned kPropsSize = 5; // it's example size
628*f6dc9357SAndroid Build Coastguard Worker WriteNumber(kPropsSize);
629*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < kPropsSize; i++)
630*f6dc9357SAndroid Build Coastguard Worker WriteByte((Byte)(i + 16));
631*f6dc9357SAndroid Build Coastguard Worker }
632*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kEnd);
633*f6dc9357SAndroid Build Coastguard Worker }
634*f6dc9357SAndroid Build Coastguard Worker */
635*f6dc9357SAndroid Build Coastguard Worker
636*f6dc9357SAndroid Build Coastguard Worker if (db.Folders.Size() > 0)
637*f6dc9357SAndroid Build Coastguard Worker {
638*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kMainStreamsInfo);
639*f6dc9357SAndroid Build Coastguard Worker WritePackInfo(0, db.PackSizes, db.PackCRCs);
640*f6dc9357SAndroid Build Coastguard Worker WriteUnpackInfo(db.Folders, (const COutFolders &)db);
641*f6dc9357SAndroid Build Coastguard Worker
642*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt64> unpackSizes;
643*f6dc9357SAndroid Build Coastguard Worker CUInt32DefVector digests;
644*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, db.Files)
645*f6dc9357SAndroid Build Coastguard Worker {
646*f6dc9357SAndroid Build Coastguard Worker const CFileItem &file = db.Files[i];
647*f6dc9357SAndroid Build Coastguard Worker if (!file.HasStream)
648*f6dc9357SAndroid Build Coastguard Worker continue;
649*f6dc9357SAndroid Build Coastguard Worker unpackSizes.Add(file.Size);
650*f6dc9357SAndroid Build Coastguard Worker digests.Defs.Add(file.CrcDefined);
651*f6dc9357SAndroid Build Coastguard Worker digests.Vals.Add(file.Crc);
652*f6dc9357SAndroid Build Coastguard Worker }
653*f6dc9357SAndroid Build Coastguard Worker
654*f6dc9357SAndroid Build Coastguard Worker WriteSubStreamsInfo(db.Folders, (const COutFolders &)db, unpackSizes, digests);
655*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kEnd);
656*f6dc9357SAndroid Build Coastguard Worker }
657*f6dc9357SAndroid Build Coastguard Worker
658*f6dc9357SAndroid Build Coastguard Worker if (db.Files.IsEmpty())
659*f6dc9357SAndroid Build Coastguard Worker {
660*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kEnd);
661*f6dc9357SAndroid Build Coastguard Worker return;
662*f6dc9357SAndroid Build Coastguard Worker }
663*f6dc9357SAndroid Build Coastguard Worker
664*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kFilesInfo);
665*f6dc9357SAndroid Build Coastguard Worker WriteNumber(db.Files.Size());
666*f6dc9357SAndroid Build Coastguard Worker
667*f6dc9357SAndroid Build Coastguard Worker {
668*f6dc9357SAndroid Build Coastguard Worker /* ---------- Empty Streams ---------- */
669*f6dc9357SAndroid Build Coastguard Worker CBoolVector emptyStreamVector;
670*f6dc9357SAndroid Build Coastguard Worker emptyStreamVector.ClearAndSetSize(db.Files.Size());
671*f6dc9357SAndroid Build Coastguard Worker unsigned numEmptyStreams = 0;
672*f6dc9357SAndroid Build Coastguard Worker {
673*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, db.Files)
674*f6dc9357SAndroid Build Coastguard Worker if (db.Files[i].HasStream)
675*f6dc9357SAndroid Build Coastguard Worker emptyStreamVector[i] = false;
676*f6dc9357SAndroid Build Coastguard Worker else
677*f6dc9357SAndroid Build Coastguard Worker {
678*f6dc9357SAndroid Build Coastguard Worker emptyStreamVector[i] = true;
679*f6dc9357SAndroid Build Coastguard Worker numEmptyStreams++;
680*f6dc9357SAndroid Build Coastguard Worker }
681*f6dc9357SAndroid Build Coastguard Worker }
682*f6dc9357SAndroid Build Coastguard Worker
683*f6dc9357SAndroid Build Coastguard Worker if (numEmptyStreams != 0)
684*f6dc9357SAndroid Build Coastguard Worker {
685*f6dc9357SAndroid Build Coastguard Worker WritePropBoolVector(NID::kEmptyStream, emptyStreamVector);
686*f6dc9357SAndroid Build Coastguard Worker
687*f6dc9357SAndroid Build Coastguard Worker CBoolVector emptyFileVector, antiVector;
688*f6dc9357SAndroid Build Coastguard Worker emptyFileVector.ClearAndSetSize(numEmptyStreams);
689*f6dc9357SAndroid Build Coastguard Worker antiVector.ClearAndSetSize(numEmptyStreams);
690*f6dc9357SAndroid Build Coastguard Worker bool thereAreEmptyFiles = false, thereAreAntiItems = false;
691*f6dc9357SAndroid Build Coastguard Worker unsigned cur = 0;
692*f6dc9357SAndroid Build Coastguard Worker
693*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, db.Files)
694*f6dc9357SAndroid Build Coastguard Worker {
695*f6dc9357SAndroid Build Coastguard Worker const CFileItem &file = db.Files[i];
696*f6dc9357SAndroid Build Coastguard Worker if (file.HasStream)
697*f6dc9357SAndroid Build Coastguard Worker continue;
698*f6dc9357SAndroid Build Coastguard Worker emptyFileVector[cur] = !file.IsDir;
699*f6dc9357SAndroid Build Coastguard Worker if (!file.IsDir)
700*f6dc9357SAndroid Build Coastguard Worker thereAreEmptyFiles = true;
701*f6dc9357SAndroid Build Coastguard Worker bool isAnti = db.IsItemAnti(i);
702*f6dc9357SAndroid Build Coastguard Worker antiVector[cur] = isAnti;
703*f6dc9357SAndroid Build Coastguard Worker if (isAnti)
704*f6dc9357SAndroid Build Coastguard Worker thereAreAntiItems = true;
705*f6dc9357SAndroid Build Coastguard Worker cur++;
706*f6dc9357SAndroid Build Coastguard Worker }
707*f6dc9357SAndroid Build Coastguard Worker
708*f6dc9357SAndroid Build Coastguard Worker if (thereAreEmptyFiles)
709*f6dc9357SAndroid Build Coastguard Worker WritePropBoolVector(NID::kEmptyFile, emptyFileVector);
710*f6dc9357SAndroid Build Coastguard Worker if (thereAreAntiItems)
711*f6dc9357SAndroid Build Coastguard Worker WritePropBoolVector(NID::kAnti, antiVector);
712*f6dc9357SAndroid Build Coastguard Worker }
713*f6dc9357SAndroid Build Coastguard Worker }
714*f6dc9357SAndroid Build Coastguard Worker
715*f6dc9357SAndroid Build Coastguard Worker
716*f6dc9357SAndroid Build Coastguard Worker {
717*f6dc9357SAndroid Build Coastguard Worker /* ---------- Names ---------- */
718*f6dc9357SAndroid Build Coastguard Worker
719*f6dc9357SAndroid Build Coastguard Worker size_t namesDataSize = 0;
720*f6dc9357SAndroid Build Coastguard Worker {
721*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, db.Files)
722*f6dc9357SAndroid Build Coastguard Worker {
723*f6dc9357SAndroid Build Coastguard Worker const UString &name = db.Names[i];
724*f6dc9357SAndroid Build Coastguard Worker const size_t numUtfChars =
725*f6dc9357SAndroid Build Coastguard Worker /*
726*f6dc9357SAndroid Build Coastguard Worker #if WCHAR_MAX > 0xffff
727*f6dc9357SAndroid Build Coastguard Worker Get_Num_Utf16_chars_from_wchar_string(name.Ptr());
728*f6dc9357SAndroid Build Coastguard Worker #else
729*f6dc9357SAndroid Build Coastguard Worker */
730*f6dc9357SAndroid Build Coastguard Worker name.Len();
731*f6dc9357SAndroid Build Coastguard Worker // #endif
732*f6dc9357SAndroid Build Coastguard Worker namesDataSize += numUtfChars;
733*f6dc9357SAndroid Build Coastguard Worker }
734*f6dc9357SAndroid Build Coastguard Worker }
735*f6dc9357SAndroid Build Coastguard Worker if (namesDataSize)
736*f6dc9357SAndroid Build Coastguard Worker {
737*f6dc9357SAndroid Build Coastguard Worker namesDataSize += db.Files.Size(); // we will write tail zero wchar for each name
738*f6dc9357SAndroid Build Coastguard Worker namesDataSize *= 2; // 2 bytes per wchar for UTF16 encoding
739*f6dc9357SAndroid Build Coastguard Worker namesDataSize++; // for additional switch byte (zero value)
740*f6dc9357SAndroid Build Coastguard Worker SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4);
741*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kName);
742*f6dc9357SAndroid Build Coastguard Worker WriteNumber(namesDataSize);
743*f6dc9357SAndroid Build Coastguard Worker
744*f6dc9357SAndroid Build Coastguard Worker if (_countMode)
745*f6dc9357SAndroid Build Coastguard Worker _countSize += namesDataSize;
746*f6dc9357SAndroid Build Coastguard Worker else
747*f6dc9357SAndroid Build Coastguard Worker {
748*f6dc9357SAndroid Build Coastguard Worker WriteByte(0);
749*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, db.Files)
750*f6dc9357SAndroid Build Coastguard Worker {
751*f6dc9357SAndroid Build Coastguard Worker const UString &name = db.Names[i];
752*f6dc9357SAndroid Build Coastguard Worker const wchar_t *p = name.Ptr();
753*f6dc9357SAndroid Build Coastguard Worker const size_t len = (size_t)name.Len() + 1;
754*f6dc9357SAndroid Build Coastguard Worker const wchar_t * const lim = p + len;
755*f6dc9357SAndroid Build Coastguard Worker if (_writeToStream)
756*f6dc9357SAndroid Build Coastguard Worker {
757*f6dc9357SAndroid Build Coastguard Worker do
758*f6dc9357SAndroid Build Coastguard Worker {
759*f6dc9357SAndroid Build Coastguard Worker const wchar_t c = *p++;
760*f6dc9357SAndroid Build Coastguard Worker WriteByte_ToStream((Byte)c);
761*f6dc9357SAndroid Build Coastguard Worker WriteByte_ToStream((Byte)(c >> 8));
762*f6dc9357SAndroid Build Coastguard Worker }
763*f6dc9357SAndroid Build Coastguard Worker while (p != lim);
764*f6dc9357SAndroid Build Coastguard Worker }
765*f6dc9357SAndroid Build Coastguard Worker else
766*f6dc9357SAndroid Build Coastguard Worker {
767*f6dc9357SAndroid Build Coastguard Worker Byte *dest = _outByte2.GetDest_and_Update(len * 2);
768*f6dc9357SAndroid Build Coastguard Worker do
769*f6dc9357SAndroid Build Coastguard Worker {
770*f6dc9357SAndroid Build Coastguard Worker /*
771*f6dc9357SAndroid Build Coastguard Worker #if WCHAR_MAX > 0xffff
772*f6dc9357SAndroid Build Coastguard Worker if (c >= 0x10000)
773*f6dc9357SAndroid Build Coastguard Worker {
774*f6dc9357SAndroid Build Coastguard Worker c -= 0x10000;
775*f6dc9357SAndroid Build Coastguard Worker if (c < (1 << 20))
776*f6dc9357SAndroid Build Coastguard Worker {
777*f6dc9357SAndroid Build Coastguard Worker unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF);
778*f6dc9357SAndroid Build Coastguard Worker WriteByte((Byte)c0);
779*f6dc9357SAndroid Build Coastguard Worker WriteByte((Byte)(c0 >> 8));
780*f6dc9357SAndroid Build Coastguard Worker c = 0xdc00 + (c & 0x3FF);
781*f6dc9357SAndroid Build Coastguard Worker }
782*f6dc9357SAndroid Build Coastguard Worker else
783*f6dc9357SAndroid Build Coastguard Worker c = '_'; // we change character unsupported by UTF16
784*f6dc9357SAndroid Build Coastguard Worker }
785*f6dc9357SAndroid Build Coastguard Worker #endif
786*f6dc9357SAndroid Build Coastguard Worker */
787*f6dc9357SAndroid Build Coastguard Worker const wchar_t c = *p++;
788*f6dc9357SAndroid Build Coastguard Worker SetUi16(dest, (UInt16)c)
789*f6dc9357SAndroid Build Coastguard Worker dest += 2;
790*f6dc9357SAndroid Build Coastguard Worker }
791*f6dc9357SAndroid Build Coastguard Worker while (p != lim);
792*f6dc9357SAndroid Build Coastguard Worker }
793*f6dc9357SAndroid Build Coastguard Worker }
794*f6dc9357SAndroid Build Coastguard Worker }
795*f6dc9357SAndroid Build Coastguard Worker }
796*f6dc9357SAndroid Build Coastguard Worker }
797*f6dc9357SAndroid Build Coastguard Worker
798*f6dc9357SAndroid Build Coastguard Worker /* if (headerOptions.WriteCTime) */ Write_UInt64DefVector_type(db.CTime, NID::kCTime);
799*f6dc9357SAndroid Build Coastguard Worker /* if (headerOptions.WriteATime) */ Write_UInt64DefVector_type(db.ATime, NID::kATime);
800*f6dc9357SAndroid Build Coastguard Worker /* if (headerOptions.WriteMTime) */ Write_UInt64DefVector_type(db.MTime, NID::kMTime);
801*f6dc9357SAndroid Build Coastguard Worker Write_UInt64DefVector_type(db.StartPos, NID::kStartPos);
802*f6dc9357SAndroid Build Coastguard Worker
803*f6dc9357SAndroid Build Coastguard Worker {
804*f6dc9357SAndroid Build Coastguard Worker /* ---------- Write Attrib ---------- */
805*f6dc9357SAndroid Build Coastguard Worker const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs);
806*f6dc9357SAndroid Build Coastguard Worker if (numDefined != 0)
807*f6dc9357SAndroid Build Coastguard Worker {
808*f6dc9357SAndroid Build Coastguard Worker WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2);
809*f6dc9357SAndroid Build Coastguard Worker Write_UInt32DefVector_numDefined(db.Attrib, numDefined);
810*f6dc9357SAndroid Build Coastguard Worker }
811*f6dc9357SAndroid Build Coastguard Worker }
812*f6dc9357SAndroid Build Coastguard Worker
813*f6dc9357SAndroid Build Coastguard Worker /*
814*f6dc9357SAndroid Build Coastguard Worker {
815*f6dc9357SAndroid Build Coastguard Worker // ---------- Write IsAux ----------
816*f6dc9357SAndroid Build Coastguard Worker if (BoolVector_CountSum(db.IsAux) != 0)
817*f6dc9357SAndroid Build Coastguard Worker WritePropBoolVector(NID::kIsAux, db.IsAux);
818*f6dc9357SAndroid Build Coastguard Worker }
819*f6dc9357SAndroid Build Coastguard Worker
820*f6dc9357SAndroid Build Coastguard Worker {
821*f6dc9357SAndroid Build Coastguard Worker // ---------- Write Parent ----------
822*f6dc9357SAndroid Build Coastguard Worker CBoolVector boolVector;
823*f6dc9357SAndroid Build Coastguard Worker boolVector.Reserve(db.Files.Size());
824*f6dc9357SAndroid Build Coastguard Worker unsigned numIsDir = 0;
825*f6dc9357SAndroid Build Coastguard Worker unsigned numParentLinks = 0;
826*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < db.Files.Size(); i++)
827*f6dc9357SAndroid Build Coastguard Worker {
828*f6dc9357SAndroid Build Coastguard Worker const CFileItem &file = db.Files[i];
829*f6dc9357SAndroid Build Coastguard Worker bool defined = !file.IsAltStream;
830*f6dc9357SAndroid Build Coastguard Worker boolVector.Add(defined);
831*f6dc9357SAndroid Build Coastguard Worker if (defined)
832*f6dc9357SAndroid Build Coastguard Worker numIsDir++;
833*f6dc9357SAndroid Build Coastguard Worker if (file.Parent >= 0)
834*f6dc9357SAndroid Build Coastguard Worker numParentLinks++;
835*f6dc9357SAndroid Build Coastguard Worker }
836*f6dc9357SAndroid Build Coastguard Worker if (numParentLinks > 0)
837*f6dc9357SAndroid Build Coastguard Worker {
838*f6dc9357SAndroid Build Coastguard Worker // WriteAlignedBools(boolVector, numDefined, NID::kParent, 2);
839*f6dc9357SAndroid Build Coastguard Worker const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector);
840*f6dc9357SAndroid Build Coastguard Worker const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1;
841*f6dc9357SAndroid Build Coastguard Worker SkipToAligned(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 2);
842*f6dc9357SAndroid Build Coastguard Worker
843*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kParent);
844*f6dc9357SAndroid Build Coastguard Worker WriteNumber(dataSize);
845*f6dc9357SAndroid Build Coastguard Worker Write_BoolVector_numDefined(boolVector, numIsDir);
846*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < db.Files.Size(); i++)
847*f6dc9357SAndroid Build Coastguard Worker {
848*f6dc9357SAndroid Build Coastguard Worker const CFileItem &file = db.Files[i];
849*f6dc9357SAndroid Build Coastguard Worker // if (file.Parent >= 0)
850*f6dc9357SAndroid Build Coastguard Worker WriteUInt32(file.Parent);
851*f6dc9357SAndroid Build Coastguard Worker }
852*f6dc9357SAndroid Build Coastguard Worker }
853*f6dc9357SAndroid Build Coastguard Worker }
854*f6dc9357SAndroid Build Coastguard Worker
855*f6dc9357SAndroid Build Coastguard Worker if (thereIsSecure)
856*f6dc9357SAndroid Build Coastguard Worker {
857*f6dc9357SAndroid Build Coastguard Worker UInt64 secureDataSize = 1 + 4 +
858*f6dc9357SAndroid Build Coastguard Worker db.SecureBuf.Size() +
859*f6dc9357SAndroid Build Coastguard Worker db.SecureSizes.Size() * 4;
860*f6dc9357SAndroid Build Coastguard Worker // secureDataSize += db.SecureIDs.Size() * 4;
861*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < db.SecureIDs.Size(); i++)
862*f6dc9357SAndroid Build Coastguard Worker secureDataSize += GetBigNumberSize(db.SecureIDs[i]);
863*f6dc9357SAndroid Build Coastguard Worker SkipToAligned(2 + GetBigNumberSize(secureDataSize), 2);
864*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kNtSecure);
865*f6dc9357SAndroid Build Coastguard Worker WriteNumber(secureDataSize);
866*f6dc9357SAndroid Build Coastguard Worker WriteByte(0);
867*f6dc9357SAndroid Build Coastguard Worker WriteUInt32(db.SecureSizes.Size());
868*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < db.SecureSizes.Size(); i++)
869*f6dc9357SAndroid Build Coastguard Worker WriteUInt32(db.SecureSizes[i]);
870*f6dc9357SAndroid Build Coastguard Worker WriteBytes(db.SecureBuf, db.SecureBuf.Size());
871*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < db.SecureIDs.Size(); i++)
872*f6dc9357SAndroid Build Coastguard Worker {
873*f6dc9357SAndroid Build Coastguard Worker WriteNumber(db.SecureIDs[i]);
874*f6dc9357SAndroid Build Coastguard Worker // WriteUInt32(db.SecureIDs[i]);
875*f6dc9357SAndroid Build Coastguard Worker }
876*f6dc9357SAndroid Build Coastguard Worker }
877*f6dc9357SAndroid Build Coastguard Worker */
878*f6dc9357SAndroid Build Coastguard Worker
879*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kEnd); // for files
880*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kEnd); // for headers
881*f6dc9357SAndroid Build Coastguard Worker }
882*f6dc9357SAndroid Build Coastguard Worker
WriteDatabase(DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabaseOut & db,const CCompressionMethodMode * options,const CHeaderOptions & headerOptions)883*f6dc9357SAndroid Build Coastguard Worker HRESULT COutArchive::WriteDatabase(
884*f6dc9357SAndroid Build Coastguard Worker DECL_EXTERNAL_CODECS_LOC_VARS
885*f6dc9357SAndroid Build Coastguard Worker const CArchiveDatabaseOut &db,
886*f6dc9357SAndroid Build Coastguard Worker const CCompressionMethodMode *options,
887*f6dc9357SAndroid Build Coastguard Worker const CHeaderOptions &headerOptions)
888*f6dc9357SAndroid Build Coastguard Worker {
889*f6dc9357SAndroid Build Coastguard Worker if (!db.CheckNumFiles())
890*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
891*f6dc9357SAndroid Build Coastguard Worker
892*f6dc9357SAndroid Build Coastguard Worker CStartHeader sh;
893*f6dc9357SAndroid Build Coastguard Worker sh.NextHeaderOffset = 0;
894*f6dc9357SAndroid Build Coastguard Worker sh.NextHeaderSize = 0;
895*f6dc9357SAndroid Build Coastguard Worker sh.NextHeaderCRC = 0; // CrcCalc(NULL, 0);
896*f6dc9357SAndroid Build Coastguard Worker
897*f6dc9357SAndroid Build Coastguard Worker if (!db.IsEmpty())
898*f6dc9357SAndroid Build Coastguard Worker {
899*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> crcStream;
900*f6dc9357SAndroid Build Coastguard Worker crcStream->SetStream(SeqStream);
901*f6dc9357SAndroid Build Coastguard Worker crcStream->Init();
902*f6dc9357SAndroid Build Coastguard Worker
903*f6dc9357SAndroid Build Coastguard Worker bool encodeHeaders = false;
904*f6dc9357SAndroid Build Coastguard Worker if (options)
905*f6dc9357SAndroid Build Coastguard Worker if (options->IsEmpty())
906*f6dc9357SAndroid Build Coastguard Worker options = NULL;
907*f6dc9357SAndroid Build Coastguard Worker if (options)
908*f6dc9357SAndroid Build Coastguard Worker if (options->PasswordIsDefined || headerOptions.CompressMainHeader)
909*f6dc9357SAndroid Build Coastguard Worker encodeHeaders = true;
910*f6dc9357SAndroid Build Coastguard Worker
911*f6dc9357SAndroid Build Coastguard Worker if (!_outByte.Create(1 << 16))
912*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
913*f6dc9357SAndroid Build Coastguard Worker _outByte.SetStream(crcStream.Interface());
914*f6dc9357SAndroid Build Coastguard Worker _outByte.Init();
915*f6dc9357SAndroid Build Coastguard Worker // _crc = CRC_INIT_VAL;
916*f6dc9357SAndroid Build Coastguard Worker _countMode = encodeHeaders;
917*f6dc9357SAndroid Build Coastguard Worker _writeToStream = true;
918*f6dc9357SAndroid Build Coastguard Worker _countSize = 0;
919*f6dc9357SAndroid Build Coastguard Worker WriteHeader(db, /* headerOptions, */ sh.NextHeaderOffset);
920*f6dc9357SAndroid Build Coastguard Worker
921*f6dc9357SAndroid Build Coastguard Worker if (encodeHeaders)
922*f6dc9357SAndroid Build Coastguard Worker {
923*f6dc9357SAndroid Build Coastguard Worker CByteBuffer buf(_countSize);
924*f6dc9357SAndroid Build Coastguard Worker _outByte2.Init((Byte *)buf, _countSize);
925*f6dc9357SAndroid Build Coastguard Worker
926*f6dc9357SAndroid Build Coastguard Worker _countMode = false;
927*f6dc9357SAndroid Build Coastguard Worker _writeToStream = false;
928*f6dc9357SAndroid Build Coastguard Worker WriteHeader(db, /* headerOptions, */ sh.NextHeaderOffset);
929*f6dc9357SAndroid Build Coastguard Worker
930*f6dc9357SAndroid Build Coastguard Worker if (_countSize != _outByte2.GetPos())
931*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
932*f6dc9357SAndroid Build Coastguard Worker
933*f6dc9357SAndroid Build Coastguard Worker CCompressionMethodMode encryptOptions;
934*f6dc9357SAndroid Build Coastguard Worker encryptOptions.PasswordIsDefined = options->PasswordIsDefined;
935*f6dc9357SAndroid Build Coastguard Worker encryptOptions.Password = options->Password;
936*f6dc9357SAndroid Build Coastguard Worker CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions);
937*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt64> packSizes;
938*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CFolder> folders;
939*f6dc9357SAndroid Build Coastguard Worker COutFolders outFolders;
940*f6dc9357SAndroid Build Coastguard Worker
941*f6dc9357SAndroid Build Coastguard Worker RINOK(EncodeStream(
942*f6dc9357SAndroid Build Coastguard Worker EXTERNAL_CODECS_LOC_VARS
943*f6dc9357SAndroid Build Coastguard Worker encoder, buf,
944*f6dc9357SAndroid Build Coastguard Worker packSizes, folders, outFolders))
945*f6dc9357SAndroid Build Coastguard Worker
946*f6dc9357SAndroid Build Coastguard Worker _writeToStream = true;
947*f6dc9357SAndroid Build Coastguard Worker
948*f6dc9357SAndroid Build Coastguard Worker if (folders.Size() == 0)
949*f6dc9357SAndroid Build Coastguard Worker throw 1;
950*f6dc9357SAndroid Build Coastguard Worker
951*f6dc9357SAndroid Build Coastguard Worker WriteID(NID::kEncodedHeader);
952*f6dc9357SAndroid Build Coastguard Worker WritePackInfo(sh.NextHeaderOffset, packSizes, CUInt32DefVector());
953*f6dc9357SAndroid Build Coastguard Worker WriteUnpackInfo(folders, outFolders);
954*f6dc9357SAndroid Build Coastguard Worker WriteByte(NID::kEnd);
955*f6dc9357SAndroid Build Coastguard Worker
956*f6dc9357SAndroid Build Coastguard Worker sh.NextHeaderOffset += UInt64Vector_CountSum(packSizes);
957*f6dc9357SAndroid Build Coastguard Worker }
958*f6dc9357SAndroid Build Coastguard Worker RINOK(_outByte.Flush())
959*f6dc9357SAndroid Build Coastguard Worker sh.NextHeaderCRC = crcStream->GetCRC();
960*f6dc9357SAndroid Build Coastguard Worker // sh.NextHeaderCRC = CRC_GET_DIGEST(_crc);
961*f6dc9357SAndroid Build Coastguard Worker // if (CRC_GET_DIGEST(_crc) != sh.NextHeaderCRC) throw 1;
962*f6dc9357SAndroid Build Coastguard Worker sh.NextHeaderSize = _outByte.GetProcessedSize();
963*f6dc9357SAndroid Build Coastguard Worker }
964*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_7Z_VOL
965*f6dc9357SAndroid Build Coastguard Worker if (_endMarker)
966*f6dc9357SAndroid Build Coastguard Worker {
967*f6dc9357SAndroid Build Coastguard Worker CFinishHeader h;
968*f6dc9357SAndroid Build Coastguard Worker h.NextHeaderSize = headerSize;
969*f6dc9357SAndroid Build Coastguard Worker h.NextHeaderCRC = headerCRC;
970*f6dc9357SAndroid Build Coastguard Worker h.NextHeaderOffset =
971*f6dc9357SAndroid Build Coastguard Worker UInt64(0) - (headerSize +
972*f6dc9357SAndroid Build Coastguard Worker 4 + kFinishHeaderSize);
973*f6dc9357SAndroid Build Coastguard Worker h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset;
974*f6dc9357SAndroid Build Coastguard Worker h.AdditionalStartBlockSize = 0;
975*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteFinishHeader(h));
976*f6dc9357SAndroid Build Coastguard Worker return WriteFinishSignature();
977*f6dc9357SAndroid Build Coastguard Worker }
978*f6dc9357SAndroid Build Coastguard Worker else
979*f6dc9357SAndroid Build Coastguard Worker #endif
980*f6dc9357SAndroid Build Coastguard Worker if (Stream)
981*f6dc9357SAndroid Build Coastguard Worker {
982*f6dc9357SAndroid Build Coastguard Worker RINOK(Stream->Seek((Int64)_signatureHeaderPos, STREAM_SEEK_SET, NULL))
983*f6dc9357SAndroid Build Coastguard Worker return WriteStartHeader(sh);
984*f6dc9357SAndroid Build Coastguard Worker }
985*f6dc9357SAndroid Build Coastguard Worker return S_OK;
986*f6dc9357SAndroid Build Coastguard Worker }
987*f6dc9357SAndroid Build Coastguard Worker
SetItem(unsigned index,bool defined,UInt32 value)988*f6dc9357SAndroid Build Coastguard Worker void CUInt32DefVector::SetItem(unsigned index, bool defined, UInt32 value)
989*f6dc9357SAndroid Build Coastguard Worker {
990*f6dc9357SAndroid Build Coastguard Worker while (index >= Defs.Size())
991*f6dc9357SAndroid Build Coastguard Worker Defs.Add(false);
992*f6dc9357SAndroid Build Coastguard Worker Defs[index] = defined;
993*f6dc9357SAndroid Build Coastguard Worker if (!defined)
994*f6dc9357SAndroid Build Coastguard Worker return;
995*f6dc9357SAndroid Build Coastguard Worker while (index >= Vals.Size())
996*f6dc9357SAndroid Build Coastguard Worker Vals.Add(0);
997*f6dc9357SAndroid Build Coastguard Worker Vals[index] = value;
998*f6dc9357SAndroid Build Coastguard Worker }
999*f6dc9357SAndroid Build Coastguard Worker
SetItem(unsigned index,bool defined,UInt64 value)1000*f6dc9357SAndroid Build Coastguard Worker void CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value)
1001*f6dc9357SAndroid Build Coastguard Worker {
1002*f6dc9357SAndroid Build Coastguard Worker while (index >= Defs.Size())
1003*f6dc9357SAndroid Build Coastguard Worker Defs.Add(false);
1004*f6dc9357SAndroid Build Coastguard Worker Defs[index] = defined;
1005*f6dc9357SAndroid Build Coastguard Worker if (!defined)
1006*f6dc9357SAndroid Build Coastguard Worker return;
1007*f6dc9357SAndroid Build Coastguard Worker while (index >= Vals.Size())
1008*f6dc9357SAndroid Build Coastguard Worker Vals.Add(0);
1009*f6dc9357SAndroid Build Coastguard Worker Vals[index] = value;
1010*f6dc9357SAndroid Build Coastguard Worker }
1011*f6dc9357SAndroid Build Coastguard Worker
AddFile(const CFileItem & file,const CFileItem2 & file2,const UString & name)1012*f6dc9357SAndroid Build Coastguard Worker void CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name)
1013*f6dc9357SAndroid Build Coastguard Worker {
1014*f6dc9357SAndroid Build Coastguard Worker unsigned index = Files.Size();
1015*f6dc9357SAndroid Build Coastguard Worker CTime.SetItem(index, file2.CTimeDefined, file2.CTime);
1016*f6dc9357SAndroid Build Coastguard Worker ATime.SetItem(index, file2.ATimeDefined, file2.ATime);
1017*f6dc9357SAndroid Build Coastguard Worker MTime.SetItem(index, file2.MTimeDefined, file2.MTime);
1018*f6dc9357SAndroid Build Coastguard Worker StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos);
1019*f6dc9357SAndroid Build Coastguard Worker Attrib.SetItem(index, file2.AttribDefined, file2.Attrib);
1020*f6dc9357SAndroid Build Coastguard Worker SetItem_Anti(index, file2.IsAnti);
1021*f6dc9357SAndroid Build Coastguard Worker // SetItem_Aux(index, file2.IsAux);
1022*f6dc9357SAndroid Build Coastguard Worker Names.Add(name);
1023*f6dc9357SAndroid Build Coastguard Worker Files.Add(file);
1024*f6dc9357SAndroid Build Coastguard Worker }
1025*f6dc9357SAndroid Build Coastguard Worker
1026*f6dc9357SAndroid Build Coastguard Worker }}
1027