1 // CoderMixer2.h
2 
3 #ifndef __CODER_MIXER2_H
4 #define __CODER_MIXER2_H
5 
6 #include "../../../Common/MyCom.h"
7 #include "../../../Common/MyVector.h"
8 
9 #include "../../ICoder.h"
10 
11 #include "../../Common/CreateCoder.h"
12 
13 #ifdef _7ZIP_ST
14   #define USE_MIXER_ST
15 #else
16   #define USE_MIXER_MT
17   #ifndef _SFX
18     #define USE_MIXER_ST
19   #endif
20 #endif
21 
22 #ifdef USE_MIXER_MT
23 #include "../../Common/StreamBinder.h"
24 #include "../../Common/VirtThread.h"
25 #endif
26 
27 
28 
29 #ifdef USE_MIXER_ST
30 
31 class CSequentialInStreamCalcSize:
32   public ISequentialInStream,
33   public CMyUnknownImp
34 {
35 public:
36   MY_UNKNOWN_IMP1(ISequentialInStream)
37 
38   STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
39 private:
40   CMyComPtr<ISequentialInStream> _stream;
41   UInt64 _size;
42   bool _wasFinished;
43 public:
SetStream(ISequentialInStream * stream)44   void SetStream(ISequentialInStream *stream) { _stream = stream;  }
Init()45   void Init()
46   {
47     _size = 0;
48     _wasFinished = false;
49   }
ReleaseStream()50   void ReleaseStream() { _stream.Release(); }
GetSize()51   UInt64 GetSize() const { return _size; }
WasFinished()52   bool WasFinished() const { return _wasFinished; }
53 };
54 
55 
56 class COutStreamCalcSize:
57   public ISequentialOutStream,
58   public IOutStreamFinish,
59   public CMyUnknownImp
60 {
61   CMyComPtr<ISequentialOutStream> _stream;
62   UInt64 _size;
63 public:
64   MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFinish)
65 
66   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
67   STDMETHOD(OutStreamFinish)();
68 
SetStream(ISequentialOutStream * stream)69   void SetStream(ISequentialOutStream *stream) { _stream = stream; }
ReleaseStream()70   void ReleaseStream() { _stream.Release(); }
Init()71   void Init() { _size = 0; }
GetSize()72   UInt64 GetSize() const { return _size; }
73 };
74 
75 #endif
76 
77 
78 
79 namespace NCoderMixer2 {
80 
81 struct CBond
82 {
83   UInt32 PackIndex;
84   UInt32 UnpackIndex;
85 
Get_InIndexCBond86   UInt32 Get_InIndex(bool encodeMode) const { return encodeMode ? UnpackIndex : PackIndex; }
Get_OutIndexCBond87   UInt32 Get_OutIndex(bool encodeMode) const { return encodeMode ? PackIndex : UnpackIndex; }
88 };
89 
90 
91 struct CCoderStreamsInfo
92 {
93   UInt32 NumStreams;
94 };
95 
96 
97 struct CBindInfo
98 {
99   CRecordVector<CCoderStreamsInfo> Coders;
100   CRecordVector<CBond> Bonds;
101   CRecordVector<UInt32> PackStreams;
102   unsigned UnpackCoder;
103 
GetNum_Bonds_and_PackStreamsCBindInfo104   unsigned GetNum_Bonds_and_PackStreams() const { return Bonds.Size() + PackStreams.Size(); }
105 
FindBond_for_PackStreamCBindInfo106   int FindBond_for_PackStream(UInt32 packStream) const
107   {
108     FOR_VECTOR (i, Bonds)
109       if (Bonds[i].PackIndex == packStream)
110         return i;
111     return -1;
112   }
113 
FindBond_for_UnpackStreamCBindInfo114   int FindBond_for_UnpackStream(UInt32 unpackStream) const
115   {
116     FOR_VECTOR (i, Bonds)
117       if (Bonds[i].UnpackIndex == unpackStream)
118         return i;
119     return -1;
120   }
121 
SetUnpackCoderCBindInfo122   bool SetUnpackCoder()
123   {
124     bool isOk = false;
125     FOR_VECTOR(i, Coders)
126     {
127       if (FindBond_for_UnpackStream(i) < 0)
128       {
129         if (isOk)
130           return false;
131         UnpackCoder = i;
132         isOk = true;
133       }
134     }
135     return isOk;
136   }
137 
IsStream_in_PackStreamsCBindInfo138   bool IsStream_in_PackStreams(UInt32 streamIndex) const
139   {
140     return FindStream_in_PackStreams(streamIndex) >= 0;
141   }
142 
FindStream_in_PackStreamsCBindInfo143   int FindStream_in_PackStreams(UInt32 streamIndex) const
144   {
145     FOR_VECTOR(i, PackStreams)
146       if (PackStreams[i] == streamIndex)
147         return i;
148     return -1;
149   }
150 
151 
152   // that function is used before Maps is calculated
153 
GetStream_for_CoderCBindInfo154   UInt32 GetStream_for_Coder(UInt32 coderIndex) const
155   {
156     UInt32 streamIndex = 0;
157     for (UInt32 i = 0; i < coderIndex; i++)
158       streamIndex += Coders[i].NumStreams;
159     return streamIndex;
160   }
161 
162   // ---------- Maps Section ----------
163 
164   CRecordVector<UInt32> Coder_to_Stream;
165   CRecordVector<UInt32> Stream_to_Coder;
166 
167   void ClearMaps();
168   bool CalcMapsAndCheck();
169 
170   // ---------- End of Maps Section ----------
171 
ClearCBindInfo172   void Clear()
173   {
174     Coders.Clear();
175     Bonds.Clear();
176     PackStreams.Clear();
177 
178     ClearMaps();
179   }
180 
GetCoder_for_StreamCBindInfo181   void GetCoder_for_Stream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const
182   {
183     coderIndex = Stream_to_Coder[streamIndex];
184     coderStreamIndex = streamIndex - Coder_to_Stream[coderIndex];
185   }
186 };
187 
188 
189 
190 class CCoder
191 {
192   CLASS_NO_COPY(CCoder);
193 public:
194   CMyComPtr<ICompressCoder> Coder;
195   CMyComPtr<ICompressCoder2> Coder2;
196   UInt32 NumStreams;
197 
198   UInt64 UnpackSize;
199   const UInt64 *UnpackSizePointer;
200 
201   CRecordVector<UInt64> PackSizes;
202   CRecordVector<const UInt64 *> PackSizePointers;
203 
204   bool Finish;
205 
CCoder()206   CCoder(): Finish(false) {}
207 
208   void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish);
209 
210   HRESULT CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const;
211 
GetUnknown()212   IUnknown *GetUnknown() const
213   {
214     return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;
215   }
216 
QueryInterface(REFGUID iid,void ** pp)217   HRESULT QueryInterface(REFGUID iid, void** pp) const
218   {
219     return GetUnknown()->QueryInterface(iid, pp);
220   }
221 };
222 
223 
224 
225 class CMixer
226 {
227   bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex);
228 
229 protected:
230   CBindInfo _bi;
231 
FindBond_for_Stream(bool forInputStream,UInt32 streamIndex)232   int FindBond_for_Stream(bool forInputStream, UInt32 streamIndex) const
233   {
234     if (EncodeMode == forInputStream)
235       return _bi.FindBond_for_UnpackStream(streamIndex);
236     else
237       return _bi.FindBond_for_PackStream(streamIndex);
238   }
239 
240   CBoolVector IsFilter_Vector;
241   CBoolVector IsExternal_Vector;
242   bool EncodeMode;
243 public:
244   unsigned MainCoderIndex;
245 
246   // bool InternalPackSizeError;
247 
CMixer(bool encodeMode)248   CMixer(bool encodeMode):
249       EncodeMode(encodeMode),
250       MainCoderIndex(0)
251       // , InternalPackSizeError(false)
252       {}
253 
254   /*
255   Sequence of calling:
256 
257       SetBindInfo();
258       for each coder
259         AddCoder();
260       SelectMainCoder();
261 
262       for each file
263       {
264         ReInit()
265         for each coder
266           SetCoderInfo();
267         Code();
268       }
269   */
270 
SetBindInfo(const CBindInfo & bindInfo)271   virtual HRESULT SetBindInfo(const CBindInfo &bindInfo)
272   {
273     _bi = bindInfo;
274     IsFilter_Vector.Clear();
275     MainCoderIndex = 0;
276     return S_OK;
277   }
278 
279   virtual void AddCoder(const CCreatedCoder &cod) = 0;
280   virtual CCoder &GetCoder(unsigned index) = 0;
281   virtual void SelectMainCoder(bool useFirst) = 0;
282   virtual void ReInit() = 0;
283   virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) = 0;
284   virtual HRESULT Code(
285       ISequentialInStream * const *inStreams,
286       ISequentialOutStream * const *outStreams,
287       ICompressProgressInfo *progress,
288       bool &dataAfterEnd_Error) = 0;
289   virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0;
290 
291   bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex);
292   bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex);
293   bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex);
294 };
295 
296 
297 
298 
299 #ifdef USE_MIXER_ST
300 
301 struct CCoderST: public CCoder
302 {
303   bool CanRead;
304   bool CanWrite;
305 
CCoderSTCCoderST306   CCoderST(): CanRead(false), CanWrite(false) {}
307 };
308 
309 
310 struct CStBinderStream
311 {
312   CSequentialInStreamCalcSize *InStreamSpec;
313   COutStreamCalcSize *OutStreamSpec;
314   CMyComPtr<IUnknown> StreamRef;
315 
CStBinderStreamCStBinderStream316   CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {}
317 };
318 
319 
320 class CMixerST:
321   public IUnknown,
322   public CMixer,
323   public CMyUnknownImp
324 {
325   HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
326       UInt32 outStreamIndex, ISequentialInStream **inStreamRes);
327   HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
328       UInt32 inStreamIndex, ISequentialInStream **inStreamRes);
329   HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
330       UInt32 outStreamIndex, ISequentialOutStream **outStreamRes);
331 
332   HRESULT FinishStream(UInt32 streamIndex);
333   HRESULT FinishCoder(UInt32 coderIndex);
334 
335 public:
336   CObjectVector<CCoderST> _coders;
337 
338   CObjectVector<CStBinderStream> _binderStreams;
339 
340   MY_UNKNOWN_IMP
341 
342   CMixerST(bool encodeMode);
343   ~CMixerST();
344 
345   virtual void AddCoder(const CCreatedCoder &cod);
346   virtual CCoder &GetCoder(unsigned index);
347   virtual void SelectMainCoder(bool useFirst);
348   virtual void ReInit();
SetCoderInfo(unsigned coderIndex,const UInt64 * unpackSize,const UInt64 * const * packSizes,bool finish)349   virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
350     { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
351   virtual HRESULT Code(
352       ISequentialInStream * const *inStreams,
353       ISequentialOutStream * const *outStreams,
354       ICompressProgressInfo *progress,
355       bool &dataAfterEnd_Error);
356   virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
357 
358   HRESULT GetMainUnpackStream(
359       ISequentialInStream * const *inStreams,
360       ISequentialInStream **inStreamRes);
361 };
362 
363 #endif
364 
365 
366 
367 
368 #ifdef USE_MIXER_MT
369 
370 class CCoderMT: public CCoder, public CVirtThread
371 {
372   CLASS_NO_COPY(CCoderMT)
373   CRecordVector<ISequentialInStream*> InStreamPointers;
374   CRecordVector<ISequentialOutStream*> OutStreamPointers;
375 
376 private:
377   void Execute();
378 public:
379   bool EncodeMode;
380   HRESULT Result;
381   CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
382   CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
383 
Release()384   void Release()
385   {
386     InStreamPointers.Clear();
387     OutStreamPointers.Clear();
388     unsigned i;
389     for (i = 0; i < InStreams.Size(); i++)
390       InStreams[i].Release();
391     for (i = 0; i < OutStreams.Size(); i++)
392       OutStreams[i].Release();
393   }
394 
395   class CReleaser
396   {
397     CLASS_NO_COPY(CReleaser)
398     CCoderMT &_c;
399   public:
CReleaser(CCoderMT & c)400     CReleaser(CCoderMT &c): _c(c) {}
~CReleaser()401     ~CReleaser() { _c.Release(); }
402   };
403 
CCoderMT()404   CCoderMT(): EncodeMode(false) {}
~CCoderMT()405   ~CCoderMT() { CVirtThread::WaitThreadFinish(); }
406 
407   void Code(ICompressProgressInfo *progress);
408 };
409 
410 
411 class CMixerMT:
412   public IUnknown,
413   public CMixer,
414   public CMyUnknownImp
415 {
416   CObjectVector<CStreamBinder> _streamBinders;
417 
418   HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
419   HRESULT ReturnIfError(HRESULT code);
420 
421 public:
422   CObjectVector<CCoderMT> _coders;
423 
424   MY_UNKNOWN_IMP
425 
426   virtual HRESULT SetBindInfo(const CBindInfo &bindInfo);
427   virtual void AddCoder(const CCreatedCoder &cod);
428   virtual CCoder &GetCoder(unsigned index);
429   virtual void SelectMainCoder(bool useFirst);
430   virtual void ReInit();
SetCoderInfo(unsigned coderIndex,const UInt64 * unpackSize,const UInt64 * const * packSizes,bool finish)431   virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
432     { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
433   virtual HRESULT Code(
434       ISequentialInStream * const *inStreams,
435       ISequentialOutStream * const *outStreams,
436       ICompressProgressInfo *progress,
437       bool &dataAfterEnd_Error);
438   virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
439 
CMixerMT(bool encodeMode)440   CMixerMT(bool encodeMode): CMixer(encodeMode) {}
441 };
442 
443 #endif
444 
445 }
446 
447 #endif
448