diff src/win32/7zip/7z/CPP/7zip/Archive/Split/SplitHandler.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Archive/Split/SplitHandler.cpp	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,357 @@
     1.4 +// SplitHandler.cpp
     1.5 +
     1.6 +#include "StdAfx.h"
     1.7 +
     1.8 +#include "Common/ComTry.h"
     1.9 +#include "Common/Defs.h"
    1.10 +#include "Common/NewHandler.h"
    1.11 +#include "Common/StringConvert.h"
    1.12 +
    1.13 +#include "Windows/PropVariant.h"
    1.14 +#include "Windows/Time.h"
    1.15 +
    1.16 +#include "../../Common/ProgressUtils.h"
    1.17 +
    1.18 +#include "../../Compress/CopyCoder.h"
    1.19 +
    1.20 +#include "../Common/ItemNameUtils.h"
    1.21 +#include "../Common/MultiStream.h"
    1.22 +
    1.23 +#include "SplitHandler.h"
    1.24 +
    1.25 +using namespace NWindows;
    1.26 +using namespace NTime;
    1.27 +
    1.28 +namespace NArchive {
    1.29 +namespace NSplit {
    1.30 +
    1.31 +STATPROPSTG kProps[] =
    1.32 +{
    1.33 +  { NULL, kpidPath, VT_BSTR},
    1.34 +  { NULL, kpidSize, VT_UI8},
    1.35 +  { NULL, kpidPackSize, VT_UI8},
    1.36 +};
    1.37 +
    1.38 +IMP_IInArchive_Props
    1.39 +IMP_IInArchive_ArcProps_NO
    1.40 +
    1.41 +class CSeqName
    1.42 +{
    1.43 +public:
    1.44 +  UString _unchangedPart;
    1.45 +  UString _changedPart;
    1.46 +  bool _splitStyle;
    1.47 +  UString GetNextName()
    1.48 +  {
    1.49 +    UString newName;
    1.50 +    if (_splitStyle)
    1.51 +    {
    1.52 +      int i;
    1.53 +      int numLetters = _changedPart.Length();
    1.54 +      for (i = numLetters - 1; i >= 0; i--)
    1.55 +      {
    1.56 +        wchar_t c = _changedPart[i];
    1.57 +        if (c == 'z')
    1.58 +        {
    1.59 +          c = 'a';
    1.60 +          newName = c + newName;
    1.61 +          continue;
    1.62 +        }
    1.63 +        else if (c == 'Z')
    1.64 +        {
    1.65 +          c = 'A';
    1.66 +          newName = c + newName;
    1.67 +          continue;
    1.68 +        }
    1.69 +        c++;
    1.70 +        if ((c == 'z' || c == 'Z') && i == 0)
    1.71 +        {
    1.72 +          _unchangedPart += c;
    1.73 +          wchar_t newChar = (c == 'z') ? L'a' : L'A';
    1.74 +          newName.Empty();
    1.75 +          numLetters++;
    1.76 +          for (int k = 0; k < numLetters; k++)
    1.77 +            newName += newChar;
    1.78 +          break;
    1.79 +        }
    1.80 +        newName = c + newName;
    1.81 +        i--;
    1.82 +        for (; i >= 0; i--)
    1.83 +          newName = _changedPart[i] + newName;
    1.84 +        break;
    1.85 +      }
    1.86 +    }
    1.87 +    else
    1.88 +    {
    1.89 +      int i;
    1.90 +      int numLetters = _changedPart.Length();
    1.91 +      for (i = numLetters - 1; i >= 0; i--)
    1.92 +      {
    1.93 +        wchar_t c = _changedPart[i];
    1.94 +        if (c == L'9')
    1.95 +        {
    1.96 +          c = L'0';
    1.97 +          newName = c + newName;
    1.98 +          if (i == 0)
    1.99 +            newName = UString(L'1') + newName;
   1.100 +          continue;
   1.101 +        }
   1.102 +        c++;
   1.103 +        newName = c + newName;
   1.104 +        i--;
   1.105 +        for (; i >= 0; i--)
   1.106 +          newName = _changedPart[i] + newName;
   1.107 +        break;
   1.108 +      }
   1.109 +    }
   1.110 +    _changedPart = newName;
   1.111 +    return _unchangedPart + _changedPart;
   1.112 +  }
   1.113 +};
   1.114 +
   1.115 +STDMETHODIMP CHandler::Open(IInStream *stream,
   1.116 +    const UInt64 * /* maxCheckStartPosition */,
   1.117 +    IArchiveOpenCallback *openArchiveCallback)
   1.118 +{
   1.119 +  COM_TRY_BEGIN
   1.120 +  Close();
   1.121 +  if (openArchiveCallback == 0)
   1.122 +    return S_FALSE;
   1.123 +  // try
   1.124 +  {
   1.125 +    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
   1.126 +    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback;
   1.127 +    if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback,
   1.128 +        &openVolumeCallback) != S_OK)
   1.129 +      return S_FALSE;
   1.130 +    
   1.131 +    {
   1.132 +      NCOM::CPropVariant prop;
   1.133 +      RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
   1.134 +      if (prop.vt != VT_BSTR)
   1.135 +        return S_FALSE;
   1.136 +      _name = prop.bstrVal;
   1.137 +    }
   1.138 +    
   1.139 +    int dotPos = _name.ReverseFind('.');
   1.140 +    UString prefix, ext;
   1.141 +    if (dotPos >= 0)
   1.142 +    {
   1.143 +      prefix = _name.Left(dotPos + 1);
   1.144 +      ext = _name.Mid(dotPos + 1);
   1.145 +    }
   1.146 +    else
   1.147 +      ext = _name;
   1.148 +    UString extBig = ext;
   1.149 +    extBig.MakeUpper();
   1.150 +
   1.151 +    CSeqName seqName;
   1.152 +
   1.153 +    int numLetters = 2;
   1.154 +    bool splitStyle = false;
   1.155 +    if (extBig.Right(2) == L"AA")
   1.156 +    {
   1.157 +      splitStyle = true;
   1.158 +      while (numLetters < extBig.Length())
   1.159 +      {
   1.160 +        if (extBig[extBig.Length() - numLetters - 1] != 'A')
   1.161 +          break;
   1.162 +        numLetters++;
   1.163 +      }
   1.164 +    }
   1.165 +    else if (ext.Right(2) == L"01")
   1.166 +    {
   1.167 +      while (numLetters < extBig.Length())
   1.168 +      {
   1.169 +        if (extBig[extBig.Length() - numLetters - 1] != '0')
   1.170 +          break;
   1.171 +        numLetters++;
   1.172 +      }
   1.173 +      if (numLetters != ext.Length())
   1.174 +        return S_FALSE;
   1.175 +    }
   1.176 +    else
   1.177 +      return S_FALSE;
   1.178 +
   1.179 +    _streams.Add(stream);
   1.180 +
   1.181 +    seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters);
   1.182 +    seqName._changedPart = ext.Right(numLetters);
   1.183 +    seqName._splitStyle = splitStyle;
   1.184 +
   1.185 +    if (prefix.Length() < 1)
   1.186 +      _subName = L"file";
   1.187 +    else
   1.188 +      _subName = prefix.Left(prefix.Length() - 1);
   1.189 +
   1.190 +    _totalSize = 0;
   1.191 +    UInt64 size;
   1.192 +    {
   1.193 +      NCOM::CPropVariant prop;
   1.194 +      RINOK(openVolumeCallback->GetProperty(kpidSize, &prop));
   1.195 +      if (prop.vt != VT_UI8)
   1.196 +        return E_INVALIDARG;
   1.197 +      size = prop.uhVal.QuadPart;
   1.198 +    }
   1.199 +    _totalSize += size;
   1.200 +    _sizes.Add(size);
   1.201 +    
   1.202 +    if (openArchiveCallback != NULL)
   1.203 +    {
   1.204 +      UInt64 numFiles = _streams.Size();
   1.205 +      RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
   1.206 +    }
   1.207 +
   1.208 +    for (;;)
   1.209 +    {
   1.210 +      UString fullName = seqName.GetNextName();
   1.211 +      CMyComPtr<IInStream> nextStream;
   1.212 +      HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);
   1.213 +      if (result == S_FALSE)
   1.214 +        break;
   1.215 +      if (result != S_OK)
   1.216 +        return result;
   1.217 +      if (!stream)
   1.218 +        break;
   1.219 +      {
   1.220 +        NCOM::CPropVariant prop;
   1.221 +        RINOK(openVolumeCallback->GetProperty(kpidSize, &prop));
   1.222 +        if (prop.vt != VT_UI8)
   1.223 +          return E_INVALIDARG;
   1.224 +        size = prop.uhVal.QuadPart;
   1.225 +      }
   1.226 +      _totalSize += size;
   1.227 +      _sizes.Add(size);
   1.228 +      _streams.Add(nextStream);
   1.229 +      if (openArchiveCallback != NULL)
   1.230 +      {
   1.231 +        UInt64 numFiles = _streams.Size();
   1.232 +        RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
   1.233 +      }
   1.234 +    }
   1.235 +  }
   1.236 +  /*
   1.237 +  catch(...)
   1.238 +  {
   1.239 +    return S_FALSE;
   1.240 +  }
   1.241 +  */
   1.242 +  return S_OK;
   1.243 +  COM_TRY_END
   1.244 +}
   1.245 +
   1.246 +STDMETHODIMP CHandler::Close()
   1.247 +{
   1.248 +  _sizes.Clear();
   1.249 +  _streams.Clear();
   1.250 +  return S_OK;
   1.251 +}
   1.252 +
   1.253 +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
   1.254 +{
   1.255 +  *numItems = _streams.IsEmpty() ? 0 : 1;
   1.256 +  return S_OK;
   1.257 +}
   1.258 +
   1.259 +STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
   1.260 +{
   1.261 +  NWindows::NCOM::CPropVariant prop;
   1.262 +  switch(propID)
   1.263 +  {
   1.264 +    case kpidPath:
   1.265 +      prop = _subName;
   1.266 +      break;
   1.267 +    case kpidSize:
   1.268 +    case kpidPackSize:
   1.269 +      prop = _totalSize;
   1.270 +      break;
   1.271 +  }
   1.272 +  prop.Detach(value);
   1.273 +  return S_OK;
   1.274 +}
   1.275 +
   1.276 +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
   1.277 +    Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback)
   1.278 +{
   1.279 +  COM_TRY_BEGIN
   1.280 +
   1.281 +  if (numItems != UInt32(-1))
   1.282 +  {
   1.283 +    if (numItems != 1)
   1.284 +      return E_INVALIDARG;
   1.285 +    if (indices[0] != 0)
   1.286 +      return E_INVALIDARG;
   1.287 +  }
   1.288 +  bool testMode = (_aTestMode != 0);
   1.289 +  CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback;
   1.290 +  extractCallback->SetTotal(_totalSize);
   1.291 +  
   1.292 +  /*
   1.293 +  CMyComPtr<IArchiveVolumeExtractCallback> volumeExtractCallback;
   1.294 +  if (extractCallback.QueryInterface(&volumeExtractCallback) != S_OK)
   1.295 +    return E_FAIL;
   1.296 +  */
   1.297 +
   1.298 +  UInt64 currentTotalSize = 0;
   1.299 +  UInt64 currentItemSize;
   1.300 +
   1.301 +  RINOK(extractCallback->SetCompleted(&currentTotalSize));
   1.302 +  CMyComPtr<ISequentialOutStream> realOutStream;
   1.303 +  Int32 askMode;
   1.304 +  askMode = testMode ? NArchive::NExtract::NAskMode::kTest :
   1.305 +  NArchive::NExtract::NAskMode::kExtract;
   1.306 +  Int32 index = 0;
   1.307 +  RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
   1.308 +  
   1.309 +  RINOK(extractCallback->PrepareOperation(askMode));
   1.310 +  if (testMode)
   1.311 +  {
   1.312 +    RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
   1.313 +    return S_OK;
   1.314 +  }
   1.315 +  
   1.316 +  if (!testMode && (!realOutStream))
   1.317 +    return S_OK;
   1.318 +
   1.319 +  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
   1.320 +  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
   1.321 +
   1.322 +  CLocalProgress *lps = new CLocalProgress;
   1.323 +  CMyComPtr<ICompressProgressInfo> progress = lps;
   1.324 +  lps->Init(extractCallback, false);
   1.325 +
   1.326 +  for (int i = 0; i < _streams.Size(); i++, currentTotalSize += currentItemSize)
   1.327 +  {
   1.328 +    lps->InSize = lps->OutSize = currentTotalSize;
   1.329 +    RINOK(lps->SetCur());
   1.330 +    IInStream *inStream = _streams[i];
   1.331 +    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
   1.332 +    RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
   1.333 +    currentItemSize = copyCoderSpec->TotalSize;
   1.334 +  }
   1.335 +  realOutStream.Release();
   1.336 +  return extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK);
   1.337 +  COM_TRY_END
   1.338 +}
   1.339 +
   1.340 +STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
   1.341 +{
   1.342 +  if (index != 0)
   1.343 +    return E_INVALIDARG;
   1.344 +  *stream = 0;
   1.345 +  CMultiStream *streamSpec = new CMultiStream;
   1.346 +  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
   1.347 +  for (int i = 0; i < _streams.Size(); i++)
   1.348 +  {
   1.349 +    CMultiStream::CSubStreamInfo subStreamInfo;
   1.350 +    subStreamInfo.Stream = _streams[i];
   1.351 +    subStreamInfo.Pos = 0;
   1.352 +    subStreamInfo.Size = _sizes[i];
   1.353 +    streamSpec->Streams.Add(subStreamInfo);
   1.354 +  }
   1.355 +  streamSpec->Init();
   1.356 +  *stream = streamTemp.Detach();
   1.357 +  return S_OK;
   1.358 +}
   1.359 +
   1.360 +}}