xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/7z/7zOut.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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