Upload 2.0.2
[physicsfs] / lzma / CPP / 7zip / Archive / Common / CoderMixer2MT.cpp
diff --git a/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
new file mode 100644 (file)
index 0000000..2ef1fa9
--- /dev/null
@@ -0,0 +1,228 @@
+// CoderMixer2MT.cpp
+
+#include "StdAfx.h"
+
+#include "CoderMixer2MT.h"
+
+namespace NCoderMixer {
+
+CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): 
+    CCoderInfo2(numInStreams, numOutStreams)
+{
+  InStreams.Reserve(NumInStreams);
+  InStreamPointers.Reserve(NumInStreams);
+  OutStreams.Reserve(NumOutStreams);
+  OutStreamPointers.Reserve(NumOutStreams);
+}
+
+void CCoder2::Execute() { Code(NULL); }
+
+void CCoder2::Code(ICompressProgressInfo *progress)
+{
+  InStreamPointers.Clear();
+  OutStreamPointers.Clear();
+  UInt32 i;
+  for (i = 0; i < NumInStreams; i++)
+  {
+    if (InSizePointers[i] != NULL)
+      InSizePointers[i] = &InSizes[i];
+    InStreamPointers.Add((ISequentialInStream *)InStreams[i]);
+  }
+  for (i = 0; i < NumOutStreams; i++)
+  {
+    if (OutSizePointers[i] != NULL)
+      OutSizePointers[i] = &OutSizes[i];
+    OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]);
+  }
+  if (Coder)
+    Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], 
+        InSizePointers[0], OutSizePointers[0], progress);
+  else
+    Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams,
+      &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress);
+  {
+    int i;
+    for (i = 0; i < InStreams.Size(); i++)
+      InStreams[i].Release();
+    for (i = 0; i < OutStreams.Size(); i++)
+      OutStreams[i].Release();
+  }
+}
+
+static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, 
+    CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
+{
+  sizes.Clear();
+  sizePointers.Clear();
+  for(UInt32 i = 0; i < numItems; i++)
+  {
+    if (srcSizes == 0 || srcSizes[i] == NULL)
+    {
+      sizes.Add(0);
+      sizePointers.Add(NULL);
+    }
+    else
+    {
+      sizes.Add(*srcSizes[i]);
+      sizePointers.Add(&sizes.Back());
+    }
+  }
+}
+
+
+void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)
+{
+  SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
+  SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
+}
+
+//////////////////////////////////////
+// CCoderMixer2MT
+
+HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)
+{  
+  _bindInfo = bindInfo; 
+  _streamBinders.Clear();
+  for(int i = 0; i < _bindInfo.BindPairs.Size(); i++)
+  {
+    _streamBinders.Add(CStreamBinder());
+    RINOK(_streamBinders.Back().CreateEvents());
+  }
+  return S_OK;
+}
+
+void CCoderMixer2MT::AddCoderCommon()
+{
+  const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()];
+  CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams);
+  _coders.Add(threadCoderInfo);
+}
+
+void CCoderMixer2MT::AddCoder(ICompressCoder *coder)
+{
+  AddCoderCommon();
+  _coders.Back().Coder = coder;
+}
+
+void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
+{
+  AddCoderCommon();
+  _coders.Back().Coder2 = coder;
+}
+
+
+void CCoderMixer2MT::ReInit()
+{
+  for(int i = 0; i < _streamBinders.Size(); i++)
+    _streamBinders[i].ReInit();
+}
+
+
+HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams) 
+{
+  /*
+  if (_coders.Size() != _bindInfo.Coders.Size())
+    throw 0;
+  */
+  int i;
+  for(i = 0; i < _coders.Size(); i++)
+  {
+    CCoder2 &coderInfo = _coders[i];
+    const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];
+    coderInfo.InStreams.Clear();
+    UInt32 j;
+    for(j = 0; j < coderStreamsInfo.NumInStreams; j++)
+      coderInfo.InStreams.Add(NULL);
+    coderInfo.OutStreams.Clear();
+    for(j = 0; j < coderStreamsInfo.NumOutStreams; j++)
+      coderInfo.OutStreams.Add(NULL);
+  }
+
+  for(i = 0; i < _bindInfo.BindPairs.Size(); i++)
+  {
+    const CBindPair &bindPair = _bindInfo.BindPairs[i];
+    UInt32 inCoderIndex, inCoderStreamIndex;
+    UInt32 outCoderIndex, outCoderStreamIndex;
+    _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex);
+    _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);
+
+    _streamBinders[i].CreateStreams(
+        &_coders[inCoderIndex].InStreams[inCoderStreamIndex],
+        &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
+  }
+
+  for(i = 0; i < _bindInfo.InStreams.Size(); i++)
+  {
+    UInt32 inCoderIndex, inCoderStreamIndex;
+    _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);
+    _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i];
+  }
+  
+  for(i = 0; i < _bindInfo.OutStreams.Size(); i++)
+  {
+    UInt32 outCoderIndex, outCoderStreamIndex;
+    _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex);
+    _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i];
+  }
+  return S_OK;
+}
+
+HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code)
+{
+  for (int i = 0; i < _coders.Size(); i++)
+    if (_coders[i].Result == code)
+      return code;
+  return S_OK;
+}
+
+STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
+      const UInt64 ** /* inSizes */, 
+      UInt32 numInStreams,
+      ISequentialOutStream **outStreams, 
+      const UInt64 ** /* outSizes */,
+      UInt32 numOutStreams,
+      ICompressProgressInfo *progress)
+{
+  if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
+      numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
+    return E_INVALIDARG;
+
+  Init(inStreams, outStreams);
+
+  int i;
+  for (i = 0; i < _coders.Size(); i++)
+    if (i != _progressCoderIndex)
+    {
+      RINOK(_coders[i].Create());
+    }
+
+  for (i = 0; i < _coders.Size(); i++)
+    if (i != _progressCoderIndex)
+      _coders[i].Start();
+
+  _coders[_progressCoderIndex].Code(progress);
+
+  for (i = 0; i < _coders.Size(); i++)
+    if (i != _progressCoderIndex)
+      _coders[i].WaitFinish();
+
+  RINOK(ReturnIfError(E_ABORT));
+  RINOK(ReturnIfError(E_OUTOFMEMORY));
+  RINOK(ReturnIfError(S_FALSE));
+
+  for (i = 0; i < _coders.Size(); i++)
+  {
+    HRESULT result = _coders[i].Result;
+    if (result != S_OK && result != E_FAIL)
+      return result;
+  }
+  for (i = 0; i < _coders.Size(); i++)
+  {
+    HRESULT result = _coders[i].Result;
+    if (result != S_OK)
+      return result;
+  }
+  return S_OK;
+}
+
+}