1370b324cSopenharmony_ci// 7zOut.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include "../../../../C/7zCrc.h"
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci#include "../../../Common/AutoPtr.h"
8370b324cSopenharmony_ci// #include "../../../Common/UTFConvert.h"
9370b324cSopenharmony_ci
10370b324cSopenharmony_ci#include "../../Common/StreamObjects.h"
11370b324cSopenharmony_ci
12370b324cSopenharmony_ci#include "7zOut.h"
13370b324cSopenharmony_ci
14370b324cSopenharmony_cinamespace NArchive {
15370b324cSopenharmony_cinamespace N7z {
16370b324cSopenharmony_ci
17370b324cSopenharmony_cistatic void FillSignature(Byte *buf)
18370b324cSopenharmony_ci{
19370b324cSopenharmony_ci  memcpy(buf, kSignature, kSignatureSize);
20370b324cSopenharmony_ci  buf[kSignatureSize] = kMajorVersion;
21370b324cSopenharmony_ci  buf[kSignatureSize + 1] = 4;
22370b324cSopenharmony_ci}
23370b324cSopenharmony_ci
24370b324cSopenharmony_ci#ifdef Z7_7Z_VOL
25370b324cSopenharmony_ciHRESULT COutArchive::WriteFinishSignature()
26370b324cSopenharmony_ci{
27370b324cSopenharmony_ci  RINOK(WriteDirect(kFinishSignature, kSignatureSize));
28370b324cSopenharmony_ci  CArchiveVersion av;
29370b324cSopenharmony_ci  av.Major = kMajorVersion;
30370b324cSopenharmony_ci  av.Minor = 2;
31370b324cSopenharmony_ci  RINOK(WriteDirectByte(av.Major));
32370b324cSopenharmony_ci  return WriteDirectByte(av.Minor);
33370b324cSopenharmony_ci}
34370b324cSopenharmony_ci#endif
35370b324cSopenharmony_ci
36370b324cSopenharmony_cistatic void SetUInt32(Byte *p, UInt32 d)
37370b324cSopenharmony_ci{
38370b324cSopenharmony_ci  for (int i = 0; i < 4; i++, d >>= 8)
39370b324cSopenharmony_ci    p[i] = (Byte)d;
40370b324cSopenharmony_ci}
41370b324cSopenharmony_ci
42370b324cSopenharmony_cistatic void SetUInt64(Byte *p, UInt64 d)
43370b324cSopenharmony_ci{
44370b324cSopenharmony_ci  for (int i = 0; i < 8; i++, d >>= 8)
45370b324cSopenharmony_ci    p[i] = (Byte)d;
46370b324cSopenharmony_ci}
47370b324cSopenharmony_ci
48370b324cSopenharmony_ciHRESULT COutArchive::WriteStartHeader(const CStartHeader &h)
49370b324cSopenharmony_ci{
50370b324cSopenharmony_ci  Byte buf[32];
51370b324cSopenharmony_ci  FillSignature(buf);
52370b324cSopenharmony_ci  SetUInt64(buf + 8 + 4, h.NextHeaderOffset);
53370b324cSopenharmony_ci  SetUInt64(buf + 8 + 12, h.NextHeaderSize);
54370b324cSopenharmony_ci  SetUInt32(buf + 8 + 20, h.NextHeaderCRC);
55370b324cSopenharmony_ci  SetUInt32(buf + 8, CrcCalc(buf + 8 + 4, 20));
56370b324cSopenharmony_ci  return WriteDirect(buf, sizeof(buf));
57370b324cSopenharmony_ci}
58370b324cSopenharmony_ci
59370b324cSopenharmony_ci#ifdef Z7_7Z_VOL
60370b324cSopenharmony_ciHRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h)
61370b324cSopenharmony_ci{
62370b324cSopenharmony_ci  CCRC crc;
63370b324cSopenharmony_ci  crc.UpdateUInt64(h.NextHeaderOffset);
64370b324cSopenharmony_ci  crc.UpdateUInt64(h.NextHeaderSize);
65370b324cSopenharmony_ci  crc.UpdateUInt32(h.NextHeaderCRC);
66370b324cSopenharmony_ci  crc.UpdateUInt64(h.ArchiveStartOffset);
67370b324cSopenharmony_ci  crc.UpdateUInt64(h.AdditionalStartBlockSize);
68370b324cSopenharmony_ci  RINOK(WriteDirectUInt32(crc.GetDigest()));
69370b324cSopenharmony_ci  RINOK(WriteDirectUInt64(h.NextHeaderOffset));
70370b324cSopenharmony_ci  RINOK(WriteDirectUInt64(h.NextHeaderSize));
71370b324cSopenharmony_ci  RINOK(WriteDirectUInt32(h.NextHeaderCRC));
72370b324cSopenharmony_ci  RINOK(WriteDirectUInt64(h.ArchiveStartOffset));
73370b324cSopenharmony_ci  return WriteDirectUInt64(h.AdditionalStartBlockSize);
74370b324cSopenharmony_ci}
75370b324cSopenharmony_ci#endif
76370b324cSopenharmony_ci
77370b324cSopenharmony_ciHRESULT COutArchive::Create_and_WriteStartPrefix(ISequentialOutStream *stream /* , bool endMarker */)
78370b324cSopenharmony_ci{
79370b324cSopenharmony_ci  Close();
80370b324cSopenharmony_ci  #ifdef Z7_7Z_VOL
81370b324cSopenharmony_ci  // endMarker = false;
82370b324cSopenharmony_ci  _endMarker = endMarker;
83370b324cSopenharmony_ci  #endif
84370b324cSopenharmony_ci  SeqStream = stream;
85370b324cSopenharmony_ci  // if (!endMarker)
86370b324cSopenharmony_ci  {
87370b324cSopenharmony_ci    SeqStream.QueryInterface(IID_IOutStream, &Stream);
88370b324cSopenharmony_ci    if (!Stream)
89370b324cSopenharmony_ci    {
90370b324cSopenharmony_ci      return E_NOTIMPL;
91370b324cSopenharmony_ci      // endMarker = true;
92370b324cSopenharmony_ci    }
93370b324cSopenharmony_ci    RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_signatureHeaderPos))
94370b324cSopenharmony_ci    Byte buf[32];
95370b324cSopenharmony_ci    FillSignature(buf);
96370b324cSopenharmony_ci    memset(&buf[8], 0, 32 - 8);
97370b324cSopenharmony_ci    return WriteDirect(buf, sizeof(buf));
98370b324cSopenharmony_ci  }
99370b324cSopenharmony_ci  #ifdef Z7_7Z_VOL
100370b324cSopenharmony_ci  if (endMarker)
101370b324cSopenharmony_ci  {
102370b324cSopenharmony_ci    /*
103370b324cSopenharmony_ci    CStartHeader sh;
104370b324cSopenharmony_ci    sh.NextHeaderOffset = (UInt32)(Int32)-1;
105370b324cSopenharmony_ci    sh.NextHeaderSize = (UInt32)(Int32)-1;
106370b324cSopenharmony_ci    sh.NextHeaderCRC = 0;
107370b324cSopenharmony_ci    WriteStartHeader(sh);
108370b324cSopenharmony_ci    return S_OK;
109370b324cSopenharmony_ci    */
110370b324cSopenharmony_ci  }
111370b324cSopenharmony_ci  #endif
112370b324cSopenharmony_ci}
113370b324cSopenharmony_ci
114370b324cSopenharmony_civoid COutArchive::Close()
115370b324cSopenharmony_ci{
116370b324cSopenharmony_ci  SeqStream.Release();
117370b324cSopenharmony_ci  Stream.Release();
118370b324cSopenharmony_ci}
119370b324cSopenharmony_ci
120370b324cSopenharmony_ciUInt64 COutArchive::GetPos() const
121370b324cSopenharmony_ci{
122370b324cSopenharmony_ci  if (_countMode)
123370b324cSopenharmony_ci    return _countSize;
124370b324cSopenharmony_ci  if (_writeToStream)
125370b324cSopenharmony_ci    return _outByte.GetProcessedSize();
126370b324cSopenharmony_ci  return _outByte2.GetPos();
127370b324cSopenharmony_ci}
128370b324cSopenharmony_ci
129370b324cSopenharmony_civoid COutArchive::WriteBytes(const void *data, size_t size)
130370b324cSopenharmony_ci{
131370b324cSopenharmony_ci  if (_countMode)
132370b324cSopenharmony_ci    _countSize += size;
133370b324cSopenharmony_ci  else if (_writeToStream)
134370b324cSopenharmony_ci  {
135370b324cSopenharmony_ci    _outByte.WriteBytes(data, size);
136370b324cSopenharmony_ci    _crc = CrcUpdate(_crc, data, size);
137370b324cSopenharmony_ci  }
138370b324cSopenharmony_ci  else
139370b324cSopenharmony_ci    _outByte2.WriteBytes(data, size);
140370b324cSopenharmony_ci}
141370b324cSopenharmony_ci
142370b324cSopenharmony_civoid COutArchive::WriteByte(Byte b)
143370b324cSopenharmony_ci{
144370b324cSopenharmony_ci  if (_countMode)
145370b324cSopenharmony_ci    _countSize++;
146370b324cSopenharmony_ci  else if (_writeToStream)
147370b324cSopenharmony_ci  {
148370b324cSopenharmony_ci    _outByte.WriteByte(b);
149370b324cSopenharmony_ci    _crc = CRC_UPDATE_BYTE(_crc, b);
150370b324cSopenharmony_ci  }
151370b324cSopenharmony_ci  else
152370b324cSopenharmony_ci    _outByte2.WriteByte(b);
153370b324cSopenharmony_ci}
154370b324cSopenharmony_ci
155370b324cSopenharmony_civoid COutArchive::WriteUInt32(UInt32 value)
156370b324cSopenharmony_ci{
157370b324cSopenharmony_ci  for (int i = 0; i < 4; i++)
158370b324cSopenharmony_ci  {
159370b324cSopenharmony_ci    WriteByte((Byte)value);
160370b324cSopenharmony_ci    value >>= 8;
161370b324cSopenharmony_ci  }
162370b324cSopenharmony_ci}
163370b324cSopenharmony_ci
164370b324cSopenharmony_civoid COutArchive::WriteUInt64(UInt64 value)
165370b324cSopenharmony_ci{
166370b324cSopenharmony_ci  for (int i = 0; i < 8; i++)
167370b324cSopenharmony_ci  {
168370b324cSopenharmony_ci    WriteByte((Byte)value);
169370b324cSopenharmony_ci    value >>= 8;
170370b324cSopenharmony_ci  }
171370b324cSopenharmony_ci}
172370b324cSopenharmony_ci
173370b324cSopenharmony_civoid COutArchive::WriteNumber(UInt64 value)
174370b324cSopenharmony_ci{
175370b324cSopenharmony_ci  Byte firstByte = 0;
176370b324cSopenharmony_ci  Byte mask = 0x80;
177370b324cSopenharmony_ci  int i;
178370b324cSopenharmony_ci  for (i = 0; i < 8; i++)
179370b324cSopenharmony_ci  {
180370b324cSopenharmony_ci    if (value < ((UInt64(1) << ( 7  * (i + 1)))))
181370b324cSopenharmony_ci    {
182370b324cSopenharmony_ci      firstByte |= Byte(value >> (8 * i));
183370b324cSopenharmony_ci      break;
184370b324cSopenharmony_ci    }
185370b324cSopenharmony_ci    firstByte |= mask;
186370b324cSopenharmony_ci    mask = (Byte)(mask >> 1);
187370b324cSopenharmony_ci  }
188370b324cSopenharmony_ci  WriteByte(firstByte);
189370b324cSopenharmony_ci  for (; i > 0; i--)
190370b324cSopenharmony_ci  {
191370b324cSopenharmony_ci    WriteByte((Byte)value);
192370b324cSopenharmony_ci    value >>= 8;
193370b324cSopenharmony_ci  }
194370b324cSopenharmony_ci}
195370b324cSopenharmony_ci
196370b324cSopenharmony_cistatic unsigned GetBigNumberSize(UInt64 value)
197370b324cSopenharmony_ci{
198370b324cSopenharmony_ci  unsigned i;
199370b324cSopenharmony_ci  for (i = 1; i < 9; i++)
200370b324cSopenharmony_ci    if (value < (((UInt64)1 << (i * 7))))
201370b324cSopenharmony_ci      break;
202370b324cSopenharmony_ci  return i;
203370b324cSopenharmony_ci}
204370b324cSopenharmony_ci
205370b324cSopenharmony_ci#ifdef Z7_7Z_VOL
206370b324cSopenharmony_ciUInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props)
207370b324cSopenharmony_ci{
208370b324cSopenharmony_ci  UInt32 result = GetBigNumberSize(dataSize) * 2 + 41;
209370b324cSopenharmony_ci  if (nameLength != 0)
210370b324cSopenharmony_ci  {
211370b324cSopenharmony_ci    nameLength = (nameLength + 1) * 2;
212370b324cSopenharmony_ci    result += nameLength + GetBigNumberSize(nameLength) + 2;
213370b324cSopenharmony_ci  }
214370b324cSopenharmony_ci  if (props)
215370b324cSopenharmony_ci  {
216370b324cSopenharmony_ci    result += 20;
217370b324cSopenharmony_ci  }
218370b324cSopenharmony_ci  if (result >= 128)
219370b324cSopenharmony_ci    result++;
220370b324cSopenharmony_ci  result += kSignatureSize + 2 + kFinishHeaderSize;
221370b324cSopenharmony_ci  return result;
222370b324cSopenharmony_ci}
223370b324cSopenharmony_ci
224370b324cSopenharmony_ciUInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props)
225370b324cSopenharmony_ci{
226370b324cSopenharmony_ci  UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props);
227370b324cSopenharmony_ci  int testSize;
228370b324cSopenharmony_ci  if (volSize > headersSizeBase)
229370b324cSopenharmony_ci    testSize = volSize - headersSizeBase;
230370b324cSopenharmony_ci  else
231370b324cSopenharmony_ci    testSize = 1;
232370b324cSopenharmony_ci  UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props);
233370b324cSopenharmony_ci  UInt64 pureSize = 1;
234370b324cSopenharmony_ci  if (volSize > headersSize)
235370b324cSopenharmony_ci    pureSize = volSize - headersSize;
236370b324cSopenharmony_ci  return pureSize;
237370b324cSopenharmony_ci}
238370b324cSopenharmony_ci#endif
239370b324cSopenharmony_ci
240370b324cSopenharmony_civoid COutArchive::WriteFolder(const CFolder &folder)
241370b324cSopenharmony_ci{
242370b324cSopenharmony_ci  WriteNumber(folder.Coders.Size());
243370b324cSopenharmony_ci  unsigned i;
244370b324cSopenharmony_ci
245370b324cSopenharmony_ci  for (i = 0; i < folder.Coders.Size(); i++)
246370b324cSopenharmony_ci  {
247370b324cSopenharmony_ci    const CCoderInfo &coder = folder.Coders[i];
248370b324cSopenharmony_ci    {
249370b324cSopenharmony_ci      UInt64 id = coder.MethodID;
250370b324cSopenharmony_ci      unsigned idSize;
251370b324cSopenharmony_ci      for (idSize = 1; idSize < sizeof(id); idSize++)
252370b324cSopenharmony_ci        if ((id >> (8 * idSize)) == 0)
253370b324cSopenharmony_ci          break;
254370b324cSopenharmony_ci      // idSize &= 0xF; // idSize is smaller than 16 already
255370b324cSopenharmony_ci      Byte temp[16];
256370b324cSopenharmony_ci      for (unsigned t = idSize; t != 0; t--, id >>= 8)
257370b324cSopenharmony_ci        temp[t] = (Byte)(id & 0xFF);
258370b324cSopenharmony_ci
259370b324cSopenharmony_ci      unsigned b = idSize;
260370b324cSopenharmony_ci      const bool isComplex = !coder.IsSimpleCoder();
261370b324cSopenharmony_ci      b |= (isComplex ? 0x10 : 0);
262370b324cSopenharmony_ci
263370b324cSopenharmony_ci      const size_t propsSize = coder.Props.Size();
264370b324cSopenharmony_ci      b |= ((propsSize != 0) ? 0x20 : 0);
265370b324cSopenharmony_ci      temp[0] = (Byte)b;
266370b324cSopenharmony_ci      WriteBytes(temp, idSize + 1);
267370b324cSopenharmony_ci      if (isComplex)
268370b324cSopenharmony_ci      {
269370b324cSopenharmony_ci        WriteNumber(coder.NumStreams);
270370b324cSopenharmony_ci        WriteNumber(1); // NumOutStreams;
271370b324cSopenharmony_ci      }
272370b324cSopenharmony_ci      if (propsSize == 0)
273370b324cSopenharmony_ci        continue;
274370b324cSopenharmony_ci      WriteNumber(propsSize);
275370b324cSopenharmony_ci      WriteBytes(coder.Props, propsSize);
276370b324cSopenharmony_ci    }
277370b324cSopenharmony_ci  }
278370b324cSopenharmony_ci
279370b324cSopenharmony_ci  for (i = 0; i < folder.Bonds.Size(); i++)
280370b324cSopenharmony_ci  {
281370b324cSopenharmony_ci    const CBond &bond = folder.Bonds[i];
282370b324cSopenharmony_ci    WriteNumber(bond.PackIndex);
283370b324cSopenharmony_ci    WriteNumber(bond.UnpackIndex);
284370b324cSopenharmony_ci  }
285370b324cSopenharmony_ci
286370b324cSopenharmony_ci  if (folder.PackStreams.Size() > 1)
287370b324cSopenharmony_ci    for (i = 0; i < folder.PackStreams.Size(); i++)
288370b324cSopenharmony_ci      WriteNumber(folder.PackStreams[i]);
289370b324cSopenharmony_ci}
290370b324cSopenharmony_ci
291370b324cSopenharmony_civoid COutArchive::WriteBoolVector(const CBoolVector &boolVector)
292370b324cSopenharmony_ci{
293370b324cSopenharmony_ci  Byte b = 0;
294370b324cSopenharmony_ci  Byte mask = 0x80;
295370b324cSopenharmony_ci  FOR_VECTOR (i, boolVector)
296370b324cSopenharmony_ci  {
297370b324cSopenharmony_ci    if (boolVector[i])
298370b324cSopenharmony_ci      b |= mask;
299370b324cSopenharmony_ci    mask = (Byte)(mask >> 1);
300370b324cSopenharmony_ci    if (mask == 0)
301370b324cSopenharmony_ci    {
302370b324cSopenharmony_ci      WriteByte(b);
303370b324cSopenharmony_ci      mask = 0x80;
304370b324cSopenharmony_ci      b = 0;
305370b324cSopenharmony_ci    }
306370b324cSopenharmony_ci  }
307370b324cSopenharmony_ci  if (mask != 0x80)
308370b324cSopenharmony_ci    WriteByte(b);
309370b324cSopenharmony_ci}
310370b324cSopenharmony_ci
311370b324cSopenharmony_cistatic inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; }
312370b324cSopenharmony_ci
313370b324cSopenharmony_civoid COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector)
314370b324cSopenharmony_ci{
315370b324cSopenharmony_ci  WriteByte(id);
316370b324cSopenharmony_ci  WriteNumber(Bv_GetSizeInBytes(boolVector));
317370b324cSopenharmony_ci  WriteBoolVector(boolVector);
318370b324cSopenharmony_ci}
319370b324cSopenharmony_ci
320370b324cSopenharmony_ciunsigned BoolVector_CountSum(const CBoolVector &v);
321370b324cSopenharmony_ci
322370b324cSopenharmony_civoid COutArchive::WriteHashDigests(const CUInt32DefVector &digests)
323370b324cSopenharmony_ci{
324370b324cSopenharmony_ci  const unsigned numDefined = BoolVector_CountSum(digests.Defs);
325370b324cSopenharmony_ci  if (numDefined == 0)
326370b324cSopenharmony_ci    return;
327370b324cSopenharmony_ci
328370b324cSopenharmony_ci  WriteByte(NID::kCRC);
329370b324cSopenharmony_ci  if (numDefined == digests.Defs.Size())
330370b324cSopenharmony_ci    WriteByte(1);
331370b324cSopenharmony_ci  else
332370b324cSopenharmony_ci  {
333370b324cSopenharmony_ci    WriteByte(0);
334370b324cSopenharmony_ci    WriteBoolVector(digests.Defs);
335370b324cSopenharmony_ci  }
336370b324cSopenharmony_ci
337370b324cSopenharmony_ci  for (unsigned i = 0; i < digests.Defs.Size(); i++)
338370b324cSopenharmony_ci    if (digests.Defs[i])
339370b324cSopenharmony_ci      WriteUInt32(digests.Vals[i]);
340370b324cSopenharmony_ci}
341370b324cSopenharmony_ci
342370b324cSopenharmony_civoid COutArchive::WritePackInfo(
343370b324cSopenharmony_ci    UInt64 dataOffset,
344370b324cSopenharmony_ci    const CRecordVector<UInt64> &packSizes,
345370b324cSopenharmony_ci    const CUInt32DefVector &packCRCs)
346370b324cSopenharmony_ci{
347370b324cSopenharmony_ci  if (packSizes.IsEmpty())
348370b324cSopenharmony_ci    return;
349370b324cSopenharmony_ci  WriteByte(NID::kPackInfo);
350370b324cSopenharmony_ci  WriteNumber(dataOffset);
351370b324cSopenharmony_ci  WriteNumber(packSizes.Size());
352370b324cSopenharmony_ci  WriteByte(NID::kSize);
353370b324cSopenharmony_ci  FOR_VECTOR (i, packSizes)
354370b324cSopenharmony_ci    WriteNumber(packSizes[i]);
355370b324cSopenharmony_ci
356370b324cSopenharmony_ci  WriteHashDigests(packCRCs);
357370b324cSopenharmony_ci
358370b324cSopenharmony_ci  WriteByte(NID::kEnd);
359370b324cSopenharmony_ci}
360370b324cSopenharmony_ci
361370b324cSopenharmony_civoid COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders, const COutFolders &outFolders)
362370b324cSopenharmony_ci{
363370b324cSopenharmony_ci  if (folders.IsEmpty())
364370b324cSopenharmony_ci    return;
365370b324cSopenharmony_ci
366370b324cSopenharmony_ci  WriteByte(NID::kUnpackInfo);
367370b324cSopenharmony_ci
368370b324cSopenharmony_ci  WriteByte(NID::kFolder);
369370b324cSopenharmony_ci  WriteNumber(folders.Size());
370370b324cSopenharmony_ci  {
371370b324cSopenharmony_ci    WriteByte(0);
372370b324cSopenharmony_ci    FOR_VECTOR (i, folders)
373370b324cSopenharmony_ci      WriteFolder(folders[i]);
374370b324cSopenharmony_ci  }
375370b324cSopenharmony_ci
376370b324cSopenharmony_ci  WriteByte(NID::kCodersUnpackSize);
377370b324cSopenharmony_ci  FOR_VECTOR (i, outFolders.CoderUnpackSizes)
378370b324cSopenharmony_ci    WriteNumber(outFolders.CoderUnpackSizes[i]);
379370b324cSopenharmony_ci
380370b324cSopenharmony_ci  WriteHashDigests(outFolders.FolderUnpackCRCs);
381370b324cSopenharmony_ci
382370b324cSopenharmony_ci  WriteByte(NID::kEnd);
383370b324cSopenharmony_ci}
384370b324cSopenharmony_ci
385370b324cSopenharmony_civoid COutArchive::WriteSubStreamsInfo(const CObjectVector<CFolder> &folders,
386370b324cSopenharmony_ci    const COutFolders &outFolders,
387370b324cSopenharmony_ci    const CRecordVector<UInt64> &unpackSizes,
388370b324cSopenharmony_ci    const CUInt32DefVector &digests)
389370b324cSopenharmony_ci{
390370b324cSopenharmony_ci  const CRecordVector<CNum> &numUnpackStreamsInFolders = outFolders.NumUnpackStreamsVector;
391370b324cSopenharmony_ci  WriteByte(NID::kSubStreamsInfo);
392370b324cSopenharmony_ci
393370b324cSopenharmony_ci  unsigned i;
394370b324cSopenharmony_ci  for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
395370b324cSopenharmony_ci    if (numUnpackStreamsInFolders[i] != 1)
396370b324cSopenharmony_ci    {
397370b324cSopenharmony_ci      WriteByte(NID::kNumUnpackStream);
398370b324cSopenharmony_ci      for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
399370b324cSopenharmony_ci        WriteNumber(numUnpackStreamsInFolders[i]);
400370b324cSopenharmony_ci      break;
401370b324cSopenharmony_ci    }
402370b324cSopenharmony_ci
403370b324cSopenharmony_ci  for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
404370b324cSopenharmony_ci    if (numUnpackStreamsInFolders[i] > 1)
405370b324cSopenharmony_ci    {
406370b324cSopenharmony_ci      WriteByte(NID::kSize);
407370b324cSopenharmony_ci      CNum index = 0;
408370b324cSopenharmony_ci      for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
409370b324cSopenharmony_ci      {
410370b324cSopenharmony_ci        CNum num = numUnpackStreamsInFolders[i];
411370b324cSopenharmony_ci        for (CNum j = 0; j < num; j++)
412370b324cSopenharmony_ci        {
413370b324cSopenharmony_ci          if (j + 1 != num)
414370b324cSopenharmony_ci            WriteNumber(unpackSizes[index]);
415370b324cSopenharmony_ci          index++;
416370b324cSopenharmony_ci        }
417370b324cSopenharmony_ci      }
418370b324cSopenharmony_ci      break;
419370b324cSopenharmony_ci    }
420370b324cSopenharmony_ci
421370b324cSopenharmony_ci  CUInt32DefVector digests2;
422370b324cSopenharmony_ci
423370b324cSopenharmony_ci  unsigned digestIndex = 0;
424370b324cSopenharmony_ci  for (i = 0; i < folders.Size(); i++)
425370b324cSopenharmony_ci  {
426370b324cSopenharmony_ci    unsigned numSubStreams = (unsigned)numUnpackStreamsInFolders[i];
427370b324cSopenharmony_ci    if (numSubStreams == 1 && outFolders.FolderUnpackCRCs.ValidAndDefined(i))
428370b324cSopenharmony_ci      digestIndex++;
429370b324cSopenharmony_ci    else
430370b324cSopenharmony_ci      for (unsigned j = 0; j < numSubStreams; j++, digestIndex++)
431370b324cSopenharmony_ci      {
432370b324cSopenharmony_ci        digests2.Defs.Add(digests.Defs[digestIndex]);
433370b324cSopenharmony_ci        digests2.Vals.Add(digests.Vals[digestIndex]);
434370b324cSopenharmony_ci      }
435370b324cSopenharmony_ci  }
436370b324cSopenharmony_ci  WriteHashDigests(digests2);
437370b324cSopenharmony_ci  WriteByte(NID::kEnd);
438370b324cSopenharmony_ci}
439370b324cSopenharmony_ci
440370b324cSopenharmony_ci// 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field.
441370b324cSopenharmony_ci
442370b324cSopenharmony_civoid COutArchive::SkipToAligned(unsigned pos, unsigned alignShifts)
443370b324cSopenharmony_ci{
444370b324cSopenharmony_ci  if (!_useAlign)
445370b324cSopenharmony_ci    return;
446370b324cSopenharmony_ci
447370b324cSopenharmony_ci  const unsigned alignSize = (unsigned)1 << alignShifts;
448370b324cSopenharmony_ci  pos += (unsigned)GetPos();
449370b324cSopenharmony_ci  pos &= (alignSize - 1);
450370b324cSopenharmony_ci  if (pos == 0)
451370b324cSopenharmony_ci    return;
452370b324cSopenharmony_ci  unsigned skip = alignSize - pos;
453370b324cSopenharmony_ci  if (skip < 2)
454370b324cSopenharmony_ci    skip += alignSize;
455370b324cSopenharmony_ci  skip -= 2;
456370b324cSopenharmony_ci  WriteByte(NID::kDummy);
457370b324cSopenharmony_ci  WriteByte((Byte)skip);
458370b324cSopenharmony_ci  for (unsigned i = 0; i < skip; i++)
459370b324cSopenharmony_ci    WriteByte(0);
460370b324cSopenharmony_ci}
461370b324cSopenharmony_ci
462370b324cSopenharmony_civoid COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts)
463370b324cSopenharmony_ci{
464370b324cSopenharmony_ci  const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v);
465370b324cSopenharmony_ci  const UInt64 dataSize = ((UInt64)numDefined << itemSizeShifts) + bvSize + 2;
466370b324cSopenharmony_ci  SkipToAligned(3 + bvSize + GetBigNumberSize(dataSize), itemSizeShifts);
467370b324cSopenharmony_ci
468370b324cSopenharmony_ci  WriteByte(type);
469370b324cSopenharmony_ci  WriteNumber(dataSize);
470370b324cSopenharmony_ci  if (numDefined == v.Size())
471370b324cSopenharmony_ci    WriteByte(1);
472370b324cSopenharmony_ci  else
473370b324cSopenharmony_ci  {
474370b324cSopenharmony_ci    WriteByte(0);
475370b324cSopenharmony_ci    WriteBoolVector(v);
476370b324cSopenharmony_ci  }
477370b324cSopenharmony_ci  WriteByte(0); // 0 means no switching to external stream
478370b324cSopenharmony_ci}
479370b324cSopenharmony_ci
480370b324cSopenharmony_civoid COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)
481370b324cSopenharmony_ci{
482370b324cSopenharmony_ci  const unsigned numDefined = BoolVector_CountSum(v.Defs);
483370b324cSopenharmony_ci  if (numDefined == 0)
484370b324cSopenharmony_ci    return;
485370b324cSopenharmony_ci
486370b324cSopenharmony_ci  WriteAlignedBools(v.Defs, numDefined, type, 3);
487370b324cSopenharmony_ci
488370b324cSopenharmony_ci  for (unsigned i = 0; i < v.Defs.Size(); i++)
489370b324cSopenharmony_ci    if (v.Defs[i])
490370b324cSopenharmony_ci      WriteUInt64(v.Vals[i]);
491370b324cSopenharmony_ci}
492370b324cSopenharmony_ci
493370b324cSopenharmony_ciHRESULT COutArchive::EncodeStream(
494370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
495370b324cSopenharmony_ci    CEncoder &encoder, const CByteBuffer &data,
496370b324cSopenharmony_ci    CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders)
497370b324cSopenharmony_ci{
498370b324cSopenharmony_ci  CBufInStream *streamSpec = new CBufInStream;
499370b324cSopenharmony_ci  CMyComPtr<ISequentialInStream> stream = streamSpec;
500370b324cSopenharmony_ci  streamSpec->Init(data, data.Size());
501370b324cSopenharmony_ci  outFolders.FolderUnpackCRCs.Defs.Add(true);
502370b324cSopenharmony_ci  outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size()));
503370b324cSopenharmony_ci  // outFolders.NumUnpackStreamsVector.Add(1);
504370b324cSopenharmony_ci  const UInt64 dataSize64 = data.Size();
505370b324cSopenharmony_ci  const UInt64 expectSize = data.Size();
506370b324cSopenharmony_ci  RINOK(encoder.Encode1(
507370b324cSopenharmony_ci      EXTERNAL_CODECS_LOC_VARS
508370b324cSopenharmony_ci      stream,
509370b324cSopenharmony_ci      // NULL,
510370b324cSopenharmony_ci      &dataSize64,  // inSizeForReduce
511370b324cSopenharmony_ci      expectSize,
512370b324cSopenharmony_ci      folders.AddNew(),
513370b324cSopenharmony_ci      // outFolders.CoderUnpackSizes, unpackSize,
514370b324cSopenharmony_ci      SeqStream, packSizes, NULL))
515370b324cSopenharmony_ci  if (!streamSpec->WasFinished())
516370b324cSopenharmony_ci    return E_FAIL;
517370b324cSopenharmony_ci  encoder.Encode_Post(dataSize64, outFolders.CoderUnpackSizes);
518370b324cSopenharmony_ci  return S_OK;
519370b324cSopenharmony_ci}
520370b324cSopenharmony_ci
521370b324cSopenharmony_civoid COutArchive::WriteHeader(
522370b324cSopenharmony_ci    const CArchiveDatabaseOut &db,
523370b324cSopenharmony_ci    // const CHeaderOptions &headerOptions,
524370b324cSopenharmony_ci    UInt64 &headerOffset)
525370b324cSopenharmony_ci{
526370b324cSopenharmony_ci  /*
527370b324cSopenharmony_ci  bool thereIsSecure = (db.SecureBuf.Size() != 0);
528370b324cSopenharmony_ci  */
529370b324cSopenharmony_ci  _useAlign = true;
530370b324cSopenharmony_ci
531370b324cSopenharmony_ci  {
532370b324cSopenharmony_ci    UInt64 packSize = 0;
533370b324cSopenharmony_ci    FOR_VECTOR (i, db.PackSizes)
534370b324cSopenharmony_ci      packSize += db.PackSizes[i];
535370b324cSopenharmony_ci    headerOffset = packSize;
536370b324cSopenharmony_ci  }
537370b324cSopenharmony_ci
538370b324cSopenharmony_ci
539370b324cSopenharmony_ci  WriteByte(NID::kHeader);
540370b324cSopenharmony_ci
541370b324cSopenharmony_ci  /*
542370b324cSopenharmony_ci  {
543370b324cSopenharmony_ci    // It's example for per archive properies writing
544370b324cSopenharmony_ci
545370b324cSopenharmony_ci    WriteByte(NID::kArchiveProperties);
546370b324cSopenharmony_ci
547370b324cSopenharmony_ci    // you must use random 40-bit number that will identify you
548370b324cSopenharmony_ci    // then you can use same kDeveloperID for any properties and methods
549370b324cSopenharmony_ci    const UInt64 kDeveloperID = 0x123456789A; // change that value to real random 40-bit number
550370b324cSopenharmony_ci
551370b324cSopenharmony_ci    #define GENERATE_7Z_ID(developerID, subID) (((UInt64)0x3F << 56) | ((UInt64)developerID << 16) | subID)
552370b324cSopenharmony_ci
553370b324cSopenharmony_ci    {
554370b324cSopenharmony_ci      const UInt64 kSubID = 0x1; // you can use small number for subID
555370b324cSopenharmony_ci      const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID);
556370b324cSopenharmony_ci      WriteNumber(kID);
557370b324cSopenharmony_ci      const unsigned kPropsSize = 3; // it's example size
558370b324cSopenharmony_ci      WriteNumber(kPropsSize);
559370b324cSopenharmony_ci      for (unsigned i = 0; i < kPropsSize; i++)
560370b324cSopenharmony_ci        WriteByte((Byte)(i & 0xFF));
561370b324cSopenharmony_ci    }
562370b324cSopenharmony_ci    {
563370b324cSopenharmony_ci      const UInt64 kSubID = 0x2; // you can use small number for subID
564370b324cSopenharmony_ci      const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID);
565370b324cSopenharmony_ci      WriteNumber(kID);
566370b324cSopenharmony_ci      const unsigned kPropsSize = 5; // it's example size
567370b324cSopenharmony_ci      WriteNumber(kPropsSize);
568370b324cSopenharmony_ci      for (unsigned i = 0; i < kPropsSize; i++)
569370b324cSopenharmony_ci        WriteByte((Byte)(i + 16));
570370b324cSopenharmony_ci    }
571370b324cSopenharmony_ci    WriteByte(NID::kEnd);
572370b324cSopenharmony_ci  }
573370b324cSopenharmony_ci  */
574370b324cSopenharmony_ci
575370b324cSopenharmony_ci  if (db.Folders.Size() > 0)
576370b324cSopenharmony_ci  {
577370b324cSopenharmony_ci    WriteByte(NID::kMainStreamsInfo);
578370b324cSopenharmony_ci    WritePackInfo(0, db.PackSizes, db.PackCRCs);
579370b324cSopenharmony_ci    WriteUnpackInfo(db.Folders, (const COutFolders &)db);
580370b324cSopenharmony_ci
581370b324cSopenharmony_ci    CRecordVector<UInt64> unpackSizes;
582370b324cSopenharmony_ci    CUInt32DefVector digests;
583370b324cSopenharmony_ci    FOR_VECTOR (i, db.Files)
584370b324cSopenharmony_ci    {
585370b324cSopenharmony_ci      const CFileItem &file = db.Files[i];
586370b324cSopenharmony_ci      if (!file.HasStream)
587370b324cSopenharmony_ci        continue;
588370b324cSopenharmony_ci      unpackSizes.Add(file.Size);
589370b324cSopenharmony_ci      digests.Defs.Add(file.CrcDefined);
590370b324cSopenharmony_ci      digests.Vals.Add(file.Crc);
591370b324cSopenharmony_ci    }
592370b324cSopenharmony_ci
593370b324cSopenharmony_ci    WriteSubStreamsInfo(db.Folders, (const COutFolders &)db, unpackSizes, digests);
594370b324cSopenharmony_ci    WriteByte(NID::kEnd);
595370b324cSopenharmony_ci  }
596370b324cSopenharmony_ci
597370b324cSopenharmony_ci  if (db.Files.IsEmpty())
598370b324cSopenharmony_ci  {
599370b324cSopenharmony_ci    WriteByte(NID::kEnd);
600370b324cSopenharmony_ci    return;
601370b324cSopenharmony_ci  }
602370b324cSopenharmony_ci
603370b324cSopenharmony_ci  WriteByte(NID::kFilesInfo);
604370b324cSopenharmony_ci  WriteNumber(db.Files.Size());
605370b324cSopenharmony_ci
606370b324cSopenharmony_ci  {
607370b324cSopenharmony_ci    /* ---------- Empty Streams ---------- */
608370b324cSopenharmony_ci    CBoolVector emptyStreamVector;
609370b324cSopenharmony_ci    emptyStreamVector.ClearAndSetSize(db.Files.Size());
610370b324cSopenharmony_ci    unsigned numEmptyStreams = 0;
611370b324cSopenharmony_ci    {
612370b324cSopenharmony_ci      FOR_VECTOR (i, db.Files)
613370b324cSopenharmony_ci        if (db.Files[i].HasStream)
614370b324cSopenharmony_ci          emptyStreamVector[i] = false;
615370b324cSopenharmony_ci        else
616370b324cSopenharmony_ci        {
617370b324cSopenharmony_ci          emptyStreamVector[i] = true;
618370b324cSopenharmony_ci          numEmptyStreams++;
619370b324cSopenharmony_ci        }
620370b324cSopenharmony_ci    }
621370b324cSopenharmony_ci
622370b324cSopenharmony_ci    if (numEmptyStreams != 0)
623370b324cSopenharmony_ci    {
624370b324cSopenharmony_ci      WritePropBoolVector(NID::kEmptyStream, emptyStreamVector);
625370b324cSopenharmony_ci
626370b324cSopenharmony_ci      CBoolVector emptyFileVector, antiVector;
627370b324cSopenharmony_ci      emptyFileVector.ClearAndSetSize(numEmptyStreams);
628370b324cSopenharmony_ci      antiVector.ClearAndSetSize(numEmptyStreams);
629370b324cSopenharmony_ci      bool thereAreEmptyFiles = false, thereAreAntiItems = false;
630370b324cSopenharmony_ci      unsigned cur = 0;
631370b324cSopenharmony_ci
632370b324cSopenharmony_ci      FOR_VECTOR (i, db.Files)
633370b324cSopenharmony_ci      {
634370b324cSopenharmony_ci        const CFileItem &file = db.Files[i];
635370b324cSopenharmony_ci        if (file.HasStream)
636370b324cSopenharmony_ci          continue;
637370b324cSopenharmony_ci        emptyFileVector[cur] = !file.IsDir;
638370b324cSopenharmony_ci        if (!file.IsDir)
639370b324cSopenharmony_ci          thereAreEmptyFiles = true;
640370b324cSopenharmony_ci        bool isAnti = db.IsItemAnti(i);
641370b324cSopenharmony_ci        antiVector[cur] = isAnti;
642370b324cSopenharmony_ci        if (isAnti)
643370b324cSopenharmony_ci          thereAreAntiItems = true;
644370b324cSopenharmony_ci        cur++;
645370b324cSopenharmony_ci      }
646370b324cSopenharmony_ci
647370b324cSopenharmony_ci      if (thereAreEmptyFiles)
648370b324cSopenharmony_ci        WritePropBoolVector(NID::kEmptyFile, emptyFileVector);
649370b324cSopenharmony_ci      if (thereAreAntiItems)
650370b324cSopenharmony_ci        WritePropBoolVector(NID::kAnti, antiVector);
651370b324cSopenharmony_ci    }
652370b324cSopenharmony_ci  }
653370b324cSopenharmony_ci
654370b324cSopenharmony_ci
655370b324cSopenharmony_ci  {
656370b324cSopenharmony_ci    /* ---------- Names ---------- */
657370b324cSopenharmony_ci
658370b324cSopenharmony_ci    unsigned numDefined = 0;
659370b324cSopenharmony_ci    size_t namesDataSize = 0;
660370b324cSopenharmony_ci    FOR_VECTOR (i, db.Files)
661370b324cSopenharmony_ci    {
662370b324cSopenharmony_ci      const UString &name = db.Names[i];
663370b324cSopenharmony_ci      if (!name.IsEmpty())
664370b324cSopenharmony_ci        numDefined++;
665370b324cSopenharmony_ci      const size_t numUtfChars =
666370b324cSopenharmony_ci      /*
667370b324cSopenharmony_ci      #if WCHAR_MAX > 0xffff
668370b324cSopenharmony_ci        Get_Num_Utf16_chars_from_wchar_string(name.Ptr());
669370b324cSopenharmony_ci      #else
670370b324cSopenharmony_ci      */
671370b324cSopenharmony_ci        name.Len();
672370b324cSopenharmony_ci      // #endif
673370b324cSopenharmony_ci      namesDataSize += (numUtfChars + 1) * 2;
674370b324cSopenharmony_ci    }
675370b324cSopenharmony_ci
676370b324cSopenharmony_ci    if (numDefined > 0)
677370b324cSopenharmony_ci    {
678370b324cSopenharmony_ci      namesDataSize++;
679370b324cSopenharmony_ci      SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4);
680370b324cSopenharmony_ci
681370b324cSopenharmony_ci      WriteByte(NID::kName);
682370b324cSopenharmony_ci      WriteNumber(namesDataSize);
683370b324cSopenharmony_ci      WriteByte(0);
684370b324cSopenharmony_ci      FOR_VECTOR (i, db.Files)
685370b324cSopenharmony_ci      {
686370b324cSopenharmony_ci        const UString &name = db.Names[i];
687370b324cSopenharmony_ci        for (unsigned t = 0; t <= name.Len(); t++)
688370b324cSopenharmony_ci        {
689370b324cSopenharmony_ci          wchar_t c = name[t];
690370b324cSopenharmony_ci
691370b324cSopenharmony_ci          /*
692370b324cSopenharmony_ci          #if WCHAR_MAX > 0xffff
693370b324cSopenharmony_ci          if (c >= 0x10000)
694370b324cSopenharmony_ci          {
695370b324cSopenharmony_ci            c -= 0x10000;
696370b324cSopenharmony_ci            if (c < (1 << 20))
697370b324cSopenharmony_ci            {
698370b324cSopenharmony_ci              unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF);
699370b324cSopenharmony_ci              WriteByte((Byte)c0);
700370b324cSopenharmony_ci              WriteByte((Byte)(c0 >> 8));
701370b324cSopenharmony_ci              c = 0xdc00 + (c & 0x3FF);
702370b324cSopenharmony_ci            }
703370b324cSopenharmony_ci            else
704370b324cSopenharmony_ci              c = '_'; // we change character unsupported by UTF16
705370b324cSopenharmony_ci          }
706370b324cSopenharmony_ci          #endif
707370b324cSopenharmony_ci          */
708370b324cSopenharmony_ci
709370b324cSopenharmony_ci          WriteByte((Byte)c);
710370b324cSopenharmony_ci          WriteByte((Byte)(c >> 8));
711370b324cSopenharmony_ci        }
712370b324cSopenharmony_ci      }
713370b324cSopenharmony_ci    }
714370b324cSopenharmony_ci  }
715370b324cSopenharmony_ci
716370b324cSopenharmony_ci  /* if (headerOptions.WriteCTime) */ WriteUInt64DefVector(db.CTime, NID::kCTime);
717370b324cSopenharmony_ci  /* if (headerOptions.WriteATime) */ WriteUInt64DefVector(db.ATime, NID::kATime);
718370b324cSopenharmony_ci  /* if (headerOptions.WriteMTime) */ WriteUInt64DefVector(db.MTime, NID::kMTime);
719370b324cSopenharmony_ci  WriteUInt64DefVector(db.StartPos, NID::kStartPos);
720370b324cSopenharmony_ci
721370b324cSopenharmony_ci  {
722370b324cSopenharmony_ci    /* ---------- Write Attrib ---------- */
723370b324cSopenharmony_ci    const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs);
724370b324cSopenharmony_ci
725370b324cSopenharmony_ci    if (numDefined != 0)
726370b324cSopenharmony_ci    {
727370b324cSopenharmony_ci      WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2);
728370b324cSopenharmony_ci      FOR_VECTOR (i, db.Attrib.Defs)
729370b324cSopenharmony_ci      {
730370b324cSopenharmony_ci        if (db.Attrib.Defs[i])
731370b324cSopenharmony_ci          WriteUInt32(db.Attrib.Vals[i]);
732370b324cSopenharmony_ci      }
733370b324cSopenharmony_ci    }
734370b324cSopenharmony_ci  }
735370b324cSopenharmony_ci
736370b324cSopenharmony_ci  /*
737370b324cSopenharmony_ci  {
738370b324cSopenharmony_ci    // ---------- Write IsAux ----------
739370b324cSopenharmony_ci    if (BoolVector_CountSum(db.IsAux) != 0)
740370b324cSopenharmony_ci      WritePropBoolVector(NID::kIsAux, db.IsAux);
741370b324cSopenharmony_ci  }
742370b324cSopenharmony_ci
743370b324cSopenharmony_ci  {
744370b324cSopenharmony_ci    // ---------- Write Parent ----------
745370b324cSopenharmony_ci    CBoolVector boolVector;
746370b324cSopenharmony_ci    boolVector.Reserve(db.Files.Size());
747370b324cSopenharmony_ci    unsigned numIsDir = 0;
748370b324cSopenharmony_ci    unsigned numParentLinks = 0;
749370b324cSopenharmony_ci    for (i = 0; i < db.Files.Size(); i++)
750370b324cSopenharmony_ci    {
751370b324cSopenharmony_ci      const CFileItem &file = db.Files[i];
752370b324cSopenharmony_ci      bool defined = !file.IsAltStream;
753370b324cSopenharmony_ci      boolVector.Add(defined);
754370b324cSopenharmony_ci      if (defined)
755370b324cSopenharmony_ci        numIsDir++;
756370b324cSopenharmony_ci      if (file.Parent >= 0)
757370b324cSopenharmony_ci        numParentLinks++;
758370b324cSopenharmony_ci    }
759370b324cSopenharmony_ci    if (numParentLinks > 0)
760370b324cSopenharmony_ci    {
761370b324cSopenharmony_ci      // WriteAlignedBools(boolVector, numDefined, NID::kParent, 2);
762370b324cSopenharmony_ci      const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector);
763370b324cSopenharmony_ci      const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1;
764370b324cSopenharmony_ci      SkipToAligned(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 2);
765370b324cSopenharmony_ci
766370b324cSopenharmony_ci      WriteByte(NID::kParent);
767370b324cSopenharmony_ci      WriteNumber(dataSize);
768370b324cSopenharmony_ci      if (numIsDir == boolVector.Size())
769370b324cSopenharmony_ci        WriteByte(1);
770370b324cSopenharmony_ci      else
771370b324cSopenharmony_ci      {
772370b324cSopenharmony_ci        WriteByte(0);
773370b324cSopenharmony_ci        WriteBoolVector(boolVector);
774370b324cSopenharmony_ci      }
775370b324cSopenharmony_ci      for (i = 0; i < db.Files.Size(); i++)
776370b324cSopenharmony_ci      {
777370b324cSopenharmony_ci        const CFileItem &file = db.Files[i];
778370b324cSopenharmony_ci        // if (file.Parent >= 0)
779370b324cSopenharmony_ci          WriteUInt32(file.Parent);
780370b324cSopenharmony_ci      }
781370b324cSopenharmony_ci    }
782370b324cSopenharmony_ci  }
783370b324cSopenharmony_ci
784370b324cSopenharmony_ci  if (thereIsSecure)
785370b324cSopenharmony_ci  {
786370b324cSopenharmony_ci    UInt64 secureDataSize = 1 + 4 +
787370b324cSopenharmony_ci       db.SecureBuf.Size() +
788370b324cSopenharmony_ci       db.SecureSizes.Size() * 4;
789370b324cSopenharmony_ci    // secureDataSize += db.SecureIDs.Size() * 4;
790370b324cSopenharmony_ci    for (i = 0; i < db.SecureIDs.Size(); i++)
791370b324cSopenharmony_ci      secureDataSize += GetBigNumberSize(db.SecureIDs[i]);
792370b324cSopenharmony_ci    SkipToAligned(2 + GetBigNumberSize(secureDataSize), 2);
793370b324cSopenharmony_ci    WriteByte(NID::kNtSecure);
794370b324cSopenharmony_ci    WriteNumber(secureDataSize);
795370b324cSopenharmony_ci    WriteByte(0);
796370b324cSopenharmony_ci    WriteUInt32(db.SecureSizes.Size());
797370b324cSopenharmony_ci    for (i = 0; i < db.SecureSizes.Size(); i++)
798370b324cSopenharmony_ci      WriteUInt32(db.SecureSizes[i]);
799370b324cSopenharmony_ci    WriteBytes(db.SecureBuf, db.SecureBuf.Size());
800370b324cSopenharmony_ci    for (i = 0; i < db.SecureIDs.Size(); i++)
801370b324cSopenharmony_ci    {
802370b324cSopenharmony_ci      WriteNumber(db.SecureIDs[i]);
803370b324cSopenharmony_ci      // WriteUInt32(db.SecureIDs[i]);
804370b324cSopenharmony_ci    }
805370b324cSopenharmony_ci  }
806370b324cSopenharmony_ci  */
807370b324cSopenharmony_ci
808370b324cSopenharmony_ci  WriteByte(NID::kEnd); // for files
809370b324cSopenharmony_ci  WriteByte(NID::kEnd); // for headers
810370b324cSopenharmony_ci}
811370b324cSopenharmony_ci
812370b324cSopenharmony_ciHRESULT COutArchive::WriteDatabase(
813370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
814370b324cSopenharmony_ci    const CArchiveDatabaseOut &db,
815370b324cSopenharmony_ci    const CCompressionMethodMode *options,
816370b324cSopenharmony_ci    const CHeaderOptions &headerOptions)
817370b324cSopenharmony_ci{
818370b324cSopenharmony_ci  if (!db.CheckNumFiles())
819370b324cSopenharmony_ci    return E_FAIL;
820370b324cSopenharmony_ci
821370b324cSopenharmony_ci  UInt64 headerOffset;
822370b324cSopenharmony_ci  UInt32 headerCRC;
823370b324cSopenharmony_ci  UInt64 headerSize;
824370b324cSopenharmony_ci  if (db.IsEmpty())
825370b324cSopenharmony_ci  {
826370b324cSopenharmony_ci    headerSize = 0;
827370b324cSopenharmony_ci    headerOffset = 0;
828370b324cSopenharmony_ci    headerCRC = CrcCalc(NULL, 0);
829370b324cSopenharmony_ci  }
830370b324cSopenharmony_ci  else
831370b324cSopenharmony_ci  {
832370b324cSopenharmony_ci    bool encodeHeaders = false;
833370b324cSopenharmony_ci    if (options)
834370b324cSopenharmony_ci      if (options->IsEmpty())
835370b324cSopenharmony_ci        options = NULL;
836370b324cSopenharmony_ci    if (options)
837370b324cSopenharmony_ci      if (options->PasswordIsDefined || headerOptions.CompressMainHeader)
838370b324cSopenharmony_ci        encodeHeaders = true;
839370b324cSopenharmony_ci
840370b324cSopenharmony_ci    _outByte.SetStream(SeqStream);
841370b324cSopenharmony_ci    _outByte.Init();
842370b324cSopenharmony_ci    _crc = CRC_INIT_VAL;
843370b324cSopenharmony_ci    _countMode = encodeHeaders;
844370b324cSopenharmony_ci    _writeToStream = true;
845370b324cSopenharmony_ci    _countSize = 0;
846370b324cSopenharmony_ci    WriteHeader(db, /* headerOptions, */ headerOffset);
847370b324cSopenharmony_ci
848370b324cSopenharmony_ci    if (encodeHeaders)
849370b324cSopenharmony_ci    {
850370b324cSopenharmony_ci      CByteBuffer buf(_countSize);
851370b324cSopenharmony_ci      _outByte2.Init((Byte *)buf, _countSize);
852370b324cSopenharmony_ci
853370b324cSopenharmony_ci      _countMode = false;
854370b324cSopenharmony_ci      _writeToStream = false;
855370b324cSopenharmony_ci      WriteHeader(db, /* headerOptions, */ headerOffset);
856370b324cSopenharmony_ci
857370b324cSopenharmony_ci      if (_countSize != _outByte2.GetPos())
858370b324cSopenharmony_ci        return E_FAIL;
859370b324cSopenharmony_ci
860370b324cSopenharmony_ci      CCompressionMethodMode encryptOptions;
861370b324cSopenharmony_ci      encryptOptions.PasswordIsDefined = options->PasswordIsDefined;
862370b324cSopenharmony_ci      encryptOptions.Password = options->Password;
863370b324cSopenharmony_ci      CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions);
864370b324cSopenharmony_ci      CRecordVector<UInt64> packSizes;
865370b324cSopenharmony_ci      CObjectVector<CFolder> folders;
866370b324cSopenharmony_ci      COutFolders outFolders;
867370b324cSopenharmony_ci
868370b324cSopenharmony_ci      RINOK(EncodeStream(
869370b324cSopenharmony_ci          EXTERNAL_CODECS_LOC_VARS
870370b324cSopenharmony_ci          encoder, buf,
871370b324cSopenharmony_ci          packSizes, folders, outFolders))
872370b324cSopenharmony_ci
873370b324cSopenharmony_ci      _writeToStream = true;
874370b324cSopenharmony_ci
875370b324cSopenharmony_ci      if (folders.Size() == 0)
876370b324cSopenharmony_ci        throw 1;
877370b324cSopenharmony_ci
878370b324cSopenharmony_ci      WriteID(NID::kEncodedHeader);
879370b324cSopenharmony_ci      WritePackInfo(headerOffset, packSizes, CUInt32DefVector());
880370b324cSopenharmony_ci      WriteUnpackInfo(folders, outFolders);
881370b324cSopenharmony_ci      WriteByte(NID::kEnd);
882370b324cSopenharmony_ci      FOR_VECTOR (i, packSizes)
883370b324cSopenharmony_ci        headerOffset += packSizes[i];
884370b324cSopenharmony_ci    }
885370b324cSopenharmony_ci    RINOK(_outByte.Flush())
886370b324cSopenharmony_ci    headerCRC = CRC_GET_DIGEST(_crc);
887370b324cSopenharmony_ci    headerSize = _outByte.GetProcessedSize();
888370b324cSopenharmony_ci  }
889370b324cSopenharmony_ci  #ifdef Z7_7Z_VOL
890370b324cSopenharmony_ci  if (_endMarker)
891370b324cSopenharmony_ci  {
892370b324cSopenharmony_ci    CFinishHeader h;
893370b324cSopenharmony_ci    h.NextHeaderSize = headerSize;
894370b324cSopenharmony_ci    h.NextHeaderCRC = headerCRC;
895370b324cSopenharmony_ci    h.NextHeaderOffset =
896370b324cSopenharmony_ci        UInt64(0) - (headerSize +
897370b324cSopenharmony_ci        4 + kFinishHeaderSize);
898370b324cSopenharmony_ci    h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset;
899370b324cSopenharmony_ci    h.AdditionalStartBlockSize = 0;
900370b324cSopenharmony_ci    RINOK(WriteFinishHeader(h));
901370b324cSopenharmony_ci    return WriteFinishSignature();
902370b324cSopenharmony_ci  }
903370b324cSopenharmony_ci  else
904370b324cSopenharmony_ci  #endif
905370b324cSopenharmony_ci  if (Stream)
906370b324cSopenharmony_ci  {
907370b324cSopenharmony_ci    CStartHeader h;
908370b324cSopenharmony_ci    h.NextHeaderSize = headerSize;
909370b324cSopenharmony_ci    h.NextHeaderCRC = headerCRC;
910370b324cSopenharmony_ci    h.NextHeaderOffset = headerOffset;
911370b324cSopenharmony_ci    RINOK(Stream->Seek((Int64)_signatureHeaderPos, STREAM_SEEK_SET, NULL))
912370b324cSopenharmony_ci    return WriteStartHeader(h);
913370b324cSopenharmony_ci  }
914370b324cSopenharmony_ci  return S_OK;
915370b324cSopenharmony_ci}
916370b324cSopenharmony_ci
917370b324cSopenharmony_civoid CUInt32DefVector::SetItem(unsigned index, bool defined, UInt32 value)
918370b324cSopenharmony_ci{
919370b324cSopenharmony_ci  while (index >= Defs.Size())
920370b324cSopenharmony_ci    Defs.Add(false);
921370b324cSopenharmony_ci  Defs[index] = defined;
922370b324cSopenharmony_ci  if (!defined)
923370b324cSopenharmony_ci    return;
924370b324cSopenharmony_ci  while (index >= Vals.Size())
925370b324cSopenharmony_ci    Vals.Add(0);
926370b324cSopenharmony_ci  Vals[index] = value;
927370b324cSopenharmony_ci}
928370b324cSopenharmony_ci
929370b324cSopenharmony_civoid CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value)
930370b324cSopenharmony_ci{
931370b324cSopenharmony_ci  while (index >= Defs.Size())
932370b324cSopenharmony_ci    Defs.Add(false);
933370b324cSopenharmony_ci  Defs[index] = defined;
934370b324cSopenharmony_ci  if (!defined)
935370b324cSopenharmony_ci    return;
936370b324cSopenharmony_ci  while (index >= Vals.Size())
937370b324cSopenharmony_ci    Vals.Add(0);
938370b324cSopenharmony_ci  Vals[index] = value;
939370b324cSopenharmony_ci}
940370b324cSopenharmony_ci
941370b324cSopenharmony_civoid CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name)
942370b324cSopenharmony_ci{
943370b324cSopenharmony_ci  unsigned index = Files.Size();
944370b324cSopenharmony_ci  CTime.SetItem(index, file2.CTimeDefined, file2.CTime);
945370b324cSopenharmony_ci  ATime.SetItem(index, file2.ATimeDefined, file2.ATime);
946370b324cSopenharmony_ci  MTime.SetItem(index, file2.MTimeDefined, file2.MTime);
947370b324cSopenharmony_ci  StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos);
948370b324cSopenharmony_ci  Attrib.SetItem(index, file2.AttribDefined, file2.Attrib);
949370b324cSopenharmony_ci  SetItem_Anti(index, file2.IsAnti);
950370b324cSopenharmony_ci  // SetItem_Aux(index, file2.IsAux);
951370b324cSopenharmony_ci  Names.Add(name);
952370b324cSopenharmony_ci  Files.Add(file);
953370b324cSopenharmony_ci}
954370b324cSopenharmony_ci
955370b324cSopenharmony_ci}}
956