• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 (int)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 (int)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 (int)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 
~CMixer()254   virtual ~CMixer() {};
255   /*
256   Sequence of calling:
257 
258       SetBindInfo();
259       for each coder
260         AddCoder();
261       SelectMainCoder();
262 
263       for each file
264       {
265         ReInit()
266         for each coder
267           SetCoderInfo();
268         Code();
269       }
270   */
271 
SetBindInfo(const CBindInfo & bindInfo)272   virtual HRESULT SetBindInfo(const CBindInfo &bindInfo)
273   {
274     _bi = bindInfo;
275     IsFilter_Vector.Clear();
276     MainCoderIndex = 0;
277     return S_OK;
278   }
279 
280   virtual void AddCoder(const CCreatedCoder &cod) = 0;
281   virtual CCoder &GetCoder(unsigned index) = 0;
282   virtual void SelectMainCoder(bool useFirst) = 0;
283   virtual HRESULT ReInit2() = 0;
284   virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) = 0;
285   virtual HRESULT Code(
286       ISequentialInStream * const *inStreams,
287       ISequentialOutStream * const *outStreams,
288       ICompressProgressInfo *progress,
289       bool &dataAfterEnd_Error) = 0;
290   virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0;
291 
292   bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex);
293   bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex);
294   bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex);
295 };
296 
297 
298 
299 
300 #ifdef USE_MIXER_ST
301 
302 struct CCoderST: public CCoder
303 {
304   bool CanRead;
305   bool CanWrite;
306 
CCoderSTCCoderST307   CCoderST(): CanRead(false), CanWrite(false) {}
308 };
309 
310 
311 struct CStBinderStream
312 {
313   CSequentialInStreamCalcSize *InStreamSpec;
314   COutStreamCalcSize *OutStreamSpec;
315   CMyComPtr<IUnknown> StreamRef;
316 
CStBinderStreamCStBinderStream317   CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {}
318 };
319 
320 
321 class CMixerST:
322   public IUnknown,
323   public CMixer,
324   public CMyUnknownImp
325 {
326   CLASS_NO_COPY(CMixerST)
327 
328   HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
329       UInt32 outStreamIndex, ISequentialInStream **inStreamRes);
330   HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
331       UInt32 inStreamIndex, ISequentialInStream **inStreamRes);
332   HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
333       UInt32 outStreamIndex, ISequentialOutStream **outStreamRes);
334 
335   HRESULT FinishStream(UInt32 streamIndex);
336   HRESULT FinishCoder(UInt32 coderIndex);
337 
338 public:
339   CObjectVector<CCoderST> _coders;
340 
341   CObjectVector<CStBinderStream> _binderStreams;
342 
343   MY_UNKNOWN_IMP
344 
345   CMixerST(bool encodeMode);
346   ~CMixerST();
347 
348   virtual void AddCoder(const CCreatedCoder &cod);
349   virtual CCoder &GetCoder(unsigned index);
350   virtual void SelectMainCoder(bool useFirst);
351   virtual HRESULT ReInit2();
SetCoderInfo(unsigned coderIndex,const UInt64 * unpackSize,const UInt64 * const * packSizes,bool finish)352   virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
353     { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
354   virtual HRESULT Code(
355       ISequentialInStream * const *inStreams,
356       ISequentialOutStream * const *outStreams,
357       ICompressProgressInfo *progress,
358       bool &dataAfterEnd_Error);
359   virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
360 
361   HRESULT GetMainUnpackStream(
362       ISequentialInStream * const *inStreams,
363       ISequentialInStream **inStreamRes);
364 };
365 
366 #endif
367 
368 
369 
370 
371 #ifdef USE_MIXER_MT
372 
373 class CCoderMT: public CCoder, public CVirtThread
374 {
375   CLASS_NO_COPY(CCoderMT)
376   CRecordVector<ISequentialInStream*> InStreamPointers;
377   CRecordVector<ISequentialOutStream*> OutStreamPointers;
378 
379 private:
380   void Execute();
381 public:
382   bool EncodeMode;
383   HRESULT Result;
384   CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
385   CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
386 
Release()387   void Release()
388   {
389     InStreamPointers.Clear();
390     OutStreamPointers.Clear();
391     unsigned i;
392     for (i = 0; i < InStreams.Size(); i++)
393       InStreams[i].Release();
394     for (i = 0; i < OutStreams.Size(); i++)
395       OutStreams[i].Release();
396   }
397 
398   class CReleaser
399   {
400     CLASS_NO_COPY(CReleaser)
401     CCoderMT &_c;
402   public:
CReleaser(CCoderMT & c)403     CReleaser(CCoderMT &c): _c(c) {}
~CReleaser()404     ~CReleaser() { _c.Release(); }
405   };
406 
CCoderMT()407   CCoderMT(): EncodeMode(false) {}
~CCoderMT()408   virtual ~CCoderMT() { CVirtThread::WaitThreadFinish(); }
409 
410   void Code(ICompressProgressInfo *progress);
411 };
412 
413 
414 class CMixerMT:
415   public IUnknown,
416   public CMixer,
417   public CMyUnknownImp
418 {
419   CLASS_NO_COPY(CMixerMT)
420 
421   CObjectVector<CStreamBinder> _streamBinders;
422 
423   HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);
424   HRESULT ReturnIfError(HRESULT code);
425 
426   // virtual ~CMixerMT() {};
427 public:
428   CObjectVector<CCoderMT> _coders;
429 
430   MY_UNKNOWN_IMP
431 
432   virtual HRESULT SetBindInfo(const CBindInfo &bindInfo);
433   virtual void AddCoder(const CCreatedCoder &cod);
434   virtual CCoder &GetCoder(unsigned index);
435   virtual void SelectMainCoder(bool useFirst);
436   virtual HRESULT ReInit2();
SetCoderInfo(unsigned coderIndex,const UInt64 * unpackSize,const UInt64 * const * packSizes,bool finish)437   virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
438     { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
439   virtual HRESULT Code(
440       ISequentialInStream * const *inStreams,
441       ISequentialOutStream * const *outStreams,
442       ICompressProgressInfo *progress,
443       bool &dataAfterEnd_Error);
444   virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
445 
CMixerMT(bool encodeMode)446   CMixerMT(bool encodeMode): CMixer(encodeMode) {}
447 };
448 
449 #endif
450 
451 }
452 
453 #endif
454