Upload 2.0.2
[physicsfs] / lzma / CPP / 7zip / Archive / Common / CoderMixer2MT.cpp
1 // CoderMixer2MT.cpp
2
3 #include "StdAfx.h"
4
5 #include "CoderMixer2MT.h"
6
7 namespace NCoderMixer {
8
9 CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): 
10     CCoderInfo2(numInStreams, numOutStreams)
11 {
12   InStreams.Reserve(NumInStreams);
13   InStreamPointers.Reserve(NumInStreams);
14   OutStreams.Reserve(NumOutStreams);
15   OutStreamPointers.Reserve(NumOutStreams);
16 }
17
18 void CCoder2::Execute() { Code(NULL); }
19
20 void CCoder2::Code(ICompressProgressInfo *progress)
21 {
22   InStreamPointers.Clear();
23   OutStreamPointers.Clear();
24   UInt32 i;
25   for (i = 0; i < NumInStreams; i++)
26   {
27     if (InSizePointers[i] != NULL)
28       InSizePointers[i] = &InSizes[i];
29     InStreamPointers.Add((ISequentialInStream *)InStreams[i]);
30   }
31   for (i = 0; i < NumOutStreams; i++)
32   {
33     if (OutSizePointers[i] != NULL)
34       OutSizePointers[i] = &OutSizes[i];
35     OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]);
36   }
37   if (Coder)
38     Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], 
39         InSizePointers[0], OutSizePointers[0], progress);
40   else
41     Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams,
42       &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress);
43   {
44     int i;
45     for (i = 0; i < InStreams.Size(); i++)
46       InStreams[i].Release();
47     for (i = 0; i < OutStreams.Size(); i++)
48       OutStreams[i].Release();
49   }
50 }
51
52 static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, 
53     CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
54 {
55   sizes.Clear();
56   sizePointers.Clear();
57   for(UInt32 i = 0; i < numItems; i++)
58   {
59     if (srcSizes == 0 || srcSizes[i] == NULL)
60     {
61       sizes.Add(0);
62       sizePointers.Add(NULL);
63     }
64     else
65     {
66       sizes.Add(*srcSizes[i]);
67       sizePointers.Add(&sizes.Back());
68     }
69   }
70 }
71
72
73 void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)
74 {
75   SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
76   SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
77 }
78
79 //////////////////////////////////////
80 // CCoderMixer2MT
81
82 HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)
83 {  
84   _bindInfo = bindInfo; 
85   _streamBinders.Clear();
86   for(int i = 0; i < _bindInfo.BindPairs.Size(); i++)
87   {
88     _streamBinders.Add(CStreamBinder());
89     RINOK(_streamBinders.Back().CreateEvents());
90   }
91   return S_OK;
92 }
93
94 void CCoderMixer2MT::AddCoderCommon()
95 {
96   const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()];
97   CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams);
98   _coders.Add(threadCoderInfo);
99 }
100
101 void CCoderMixer2MT::AddCoder(ICompressCoder *coder)
102 {
103   AddCoderCommon();
104   _coders.Back().Coder = coder;
105 }
106
107 void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
108 {
109   AddCoderCommon();
110   _coders.Back().Coder2 = coder;
111 }
112
113
114 void CCoderMixer2MT::ReInit()
115 {
116   for(int i = 0; i < _streamBinders.Size(); i++)
117     _streamBinders[i].ReInit();
118 }
119
120
121 HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams) 
122 {
123   /*
124   if (_coders.Size() != _bindInfo.Coders.Size())
125     throw 0;
126   */
127   int i;
128   for(i = 0; i < _coders.Size(); i++)
129   {
130     CCoder2 &coderInfo = _coders[i];
131     const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];
132     coderInfo.InStreams.Clear();
133     UInt32 j;
134     for(j = 0; j < coderStreamsInfo.NumInStreams; j++)
135       coderInfo.InStreams.Add(NULL);
136     coderInfo.OutStreams.Clear();
137     for(j = 0; j < coderStreamsInfo.NumOutStreams; j++)
138       coderInfo.OutStreams.Add(NULL);
139   }
140
141   for(i = 0; i < _bindInfo.BindPairs.Size(); i++)
142   {
143     const CBindPair &bindPair = _bindInfo.BindPairs[i];
144     UInt32 inCoderIndex, inCoderStreamIndex;
145     UInt32 outCoderIndex, outCoderStreamIndex;
146     _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex);
147     _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);
148
149     _streamBinders[i].CreateStreams(
150         &_coders[inCoderIndex].InStreams[inCoderStreamIndex],
151         &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
152   }
153
154   for(i = 0; i < _bindInfo.InStreams.Size(); i++)
155   {
156     UInt32 inCoderIndex, inCoderStreamIndex;
157     _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);
158     _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i];
159   }
160   
161   for(i = 0; i < _bindInfo.OutStreams.Size(); i++)
162   {
163     UInt32 outCoderIndex, outCoderStreamIndex;
164     _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex);
165     _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i];
166   }
167   return S_OK;
168 }
169
170 HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code)
171 {
172   for (int i = 0; i < _coders.Size(); i++)
173     if (_coders[i].Result == code)
174       return code;
175   return S_OK;
176 }
177
178 STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
179       const UInt64 ** /* inSizes */, 
180       UInt32 numInStreams,
181       ISequentialOutStream **outStreams, 
182       const UInt64 ** /* outSizes */,
183       UInt32 numOutStreams,
184       ICompressProgressInfo *progress)
185 {
186   if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
187       numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
188     return E_INVALIDARG;
189
190   Init(inStreams, outStreams);
191
192   int i;
193   for (i = 0; i < _coders.Size(); i++)
194     if (i != _progressCoderIndex)
195     {
196       RINOK(_coders[i].Create());
197     }
198
199   for (i = 0; i < _coders.Size(); i++)
200     if (i != _progressCoderIndex)
201       _coders[i].Start();
202
203   _coders[_progressCoderIndex].Code(progress);
204
205   for (i = 0; i < _coders.Size(); i++)
206     if (i != _progressCoderIndex)
207       _coders[i].WaitFinish();
208
209   RINOK(ReturnIfError(E_ABORT));
210   RINOK(ReturnIfError(E_OUTOFMEMORY));
211   RINOK(ReturnIfError(S_FALSE));
212
213   for (i = 0; i < _coders.Size(); i++)
214   {
215     HRESULT result = _coders[i].Result;
216     if (result != S_OK && result != E_FAIL)
217       return result;
218   }
219   for (i = 0; i < _coders.Size(); i++)
220   {
221     HRESULT result = _coders[i].Result;
222     if (result != S_OK)
223       return result;
224   }
225   return S_OK;
226 }
227
228 }