[llvm-commits] [test-suite] r170306 [2/7] - in /test-suite/trunk: ./ MultiSource/Benchmarks/ MultiSource/Benchmarks/7zip/ MultiSource/Benchmarks/7zip/C/ MultiSource/Benchmarks/7zip/C/LzmaUtil/ MultiSource/Benchmarks/7zip/CPP/ MultiSource/Benchmarks/7zip/CPP/7zip/ MultiSource/Benchmarks/7zip/CPP/7zip/Archive/ MultiSource/Benchmarks/7zip/CPP/7zip/Archive/7z/ MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Cab/ MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Chm/ MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Com/ MultiSource/Ben...

Michael Gottesman mgottesman at apple.com
Sun Dec 16 21:23:34 PST 2012


Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/OutStreamWithCRC.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/OutStreamWithCRC.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/OutStreamWithCRC.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/OutStreamWithCRC.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,36 @@
+// OutStreamWithCRC.h
+
+#ifndef __OUT_STREAM_WITH_CRC_H
+#define __OUT_STREAM_WITH_CRC_H
+
+#include "../../../../C/7zCrc.h"
+
+#include "../../../Common/MyCom.h"
+
+#include "../../IStream.h"
+
+class COutStreamWithCRC:
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+  CMyComPtr<ISequentialOutStream> _stream;
+  UInt64 _size;
+  UInt32 _crc;
+  bool _calculate;
+public:
+  MY_UNKNOWN_IMP
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+  void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+  void ReleaseStream() { _stream.Release(); }
+  void Init(bool calculate = true)
+  {
+    _size = 0;
+    _calculate = calculate;
+    _crc = CRC_INIT_VAL;
+  }
+  void InitCRC() { _crc = CRC_INIT_VAL; }
+  UInt64 GetSize() const { return _size; }
+  UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
+};
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,18 @@
+// OutStreamWithSha1.cpp
+
+#include "StdAfx.h"
+
+#include "OutStreamWithSha1.h"
+
+STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  HRESULT result = S_OK;
+  if (_stream)
+    result = _stream->Write(data, size, &size);
+  if (_calculate)
+    _sha.Update((const Byte *)data, size);
+  _size += size;
+  if (processedSize != NULL)
+    *processedSize = size;
+  return result;
+}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/OutStreamWithSha1.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/OutStreamWithSha1.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/OutStreamWithSha1.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/OutStreamWithSha1.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,36 @@
+// OutStreamWithSha1.h
+
+#ifndef __OUT_STREAM_WITH_SHA1_H
+#define __OUT_STREAM_WITH_SHA1_H
+
+#include "../../Crypto/Sha1.h"
+
+#include "../../../Common/MyCom.h"
+
+#include "../../IStream.h"
+
+class COutStreamWithSha1:
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+  CMyComPtr<ISequentialOutStream> _stream;
+  UInt64 _size;
+  NCrypto::NSha1::CContext _sha;
+  bool _calculate;
+public:
+  MY_UNKNOWN_IMP
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+  void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+  void ReleaseStream() { _stream.Release(); }
+  void Init(bool calculate = true)
+  {
+    _size = 0;
+    _calculate = calculate;
+    _sha.Init();
+  }
+  void InitSha1() { _sha.Init(); }
+  UInt64 GetSize() const { return _size; }
+  void Final(Byte *digest) { _sha.Final(digest); }
+};
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/ParseProperties.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/ParseProperties.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/ParseProperties.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/ParseProperties.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,177 @@
+// ParseProperties.cpp
+
+#include "StdAfx.h"
+
+#include "ParseProperties.h"
+
+#include "Common/StringToInt.h"
+#include "Common/MyCom.h"
+
+HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
+{
+  if (prop.vt == VT_UI4)
+  {
+    if (!name.IsEmpty())
+      return E_INVALIDARG;
+    resValue = prop.ulVal;
+  }
+  else if (prop.vt == VT_EMPTY)
+  {
+    if(!name.IsEmpty())
+    {
+      const wchar_t *start = name;
+      const wchar_t *end;
+      UInt64 v = ConvertStringToUInt64(start, &end);
+      if (end - start != name.Length())
+        return E_INVALIDARG;
+      resValue = (UInt32)v;
+    }
+  }
+  else
+    return E_INVALIDARG;
+  return S_OK;
+}
+
+static const int kLogarithmicSizeLimit = 32;
+static const wchar_t kByteSymbol = L'B';
+static const wchar_t kKiloByteSymbol = L'K';
+static const wchar_t kMegaByteSymbol = L'M';
+
+HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize)
+{
+  UString srcString = srcStringSpec;
+  srcString.MakeUpper();
+
+  const wchar_t *start = srcString;
+  const wchar_t *end;
+  UInt64 number = ConvertStringToUInt64(start, &end);
+  int numDigits = (int)(end - start);
+  if (numDigits == 0 || srcString.Length() > numDigits + 1)
+    return E_INVALIDARG;
+  if (srcString.Length() == numDigits)
+  {
+    if (number >= kLogarithmicSizeLimit)
+      return E_INVALIDARG;
+    dicSize = (UInt32)1 << (int)number;
+    return S_OK;
+  }
+  switch (srcString[numDigits])
+  {
+    case kByteSymbol:
+      if (number >= ((UInt64)1 << kLogarithmicSizeLimit))
+        return E_INVALIDARG;
+      dicSize = (UInt32)number;
+      break;
+    case kKiloByteSymbol:
+      if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10)))
+        return E_INVALIDARG;
+      dicSize = (UInt32)(number << 10);
+      break;
+    case kMegaByteSymbol:
+      if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20)))
+        return E_INVALIDARG;
+      dicSize = (UInt32)(number << 20);
+      break;
+    default:
+      return E_INVALIDARG;
+  }
+  return S_OK;
+}
+
+HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
+{
+  if (name.IsEmpty())
+  {
+    if (prop.vt == VT_UI4)
+    {
+      UInt32 logDicSize = prop.ulVal;
+      if (logDicSize >= 32)
+        return E_INVALIDARG;
+      resValue = (UInt32)1 << logDicSize;
+      return S_OK;
+    }
+    if (prop.vt == VT_BSTR)
+      return ParsePropDictionaryValue(prop.bstrVal, resValue);
+    return E_INVALIDARG;
+  }
+  return ParsePropDictionaryValue(name, resValue);
+}
+
+bool StringToBool(const UString &s, bool &res)
+{
+  if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0)
+  {
+    res = true;
+    return true;
+  }
+  if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0)
+  {
+    res = false;
+    return true;
+  }
+  return false;
+}
+
+HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value)
+{
+  switch(value.vt)
+  {
+    case VT_EMPTY:
+      dest = true;
+      return S_OK;
+    case VT_BOOL:
+      dest = (value.boolVal != VARIANT_FALSE);
+      return S_OK;
+    /*
+    case VT_UI4:
+      dest = (value.ulVal != 0);
+      break;
+    */
+    case VT_BSTR:
+      return StringToBool(value.bstrVal, dest) ?  S_OK : E_INVALIDARG;
+  }
+  return E_INVALIDARG;
+}
+
+int ParseStringToUInt32(const UString &srcString, UInt32 &number)
+{
+  const wchar_t *start = srcString;
+  const wchar_t *end;
+  UInt64 number64 = ConvertStringToUInt64(start, &end);
+  if (number64 > 0xFFFFFFFF)
+  {
+    number = 0;
+    return 0;
+  }
+  number = (UInt32)number64;
+  return (int)(end - start);
+}
+
+HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads)
+{
+  if (name.IsEmpty())
+  {
+    switch(prop.vt)
+    {
+      case VT_UI4:
+        numThreads = prop.ulVal;
+        break;
+      default:
+      {
+        bool val;
+        RINOK(SetBoolProperty(val, prop));
+        numThreads = (val ? defaultNumThreads : 1);
+        break;
+      }
+    }
+  }
+  else
+  {
+    UInt32 number;
+    int index = ParseStringToUInt32(name, number);
+    if (index != name.Length())
+      return E_INVALIDARG;
+    numThreads = number;
+  }
+  return S_OK;
+}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/ParseProperties.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/ParseProperties.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/ParseProperties.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Common/ParseProperties.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,18 @@
+// ParseProperties.h
+
+#ifndef __PARSEPROPERTIES_H
+#define __PARSEPROPERTIES_H
+
+#include "Common/MyString.h"
+#include "Common/Types.h"
+
+HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
+HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize);
+HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
+
+bool StringToBool(const UString &s, bool &res);
+HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value);
+int ParseStringToUInt32(const UString &srcString, UInt32 &number);
+HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads);
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/CpioHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/CpioHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/CpioHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/CpioHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,624 @@
+// CpioHandler.cpp
+
+#include "StdAfx.h"
+
+#include "Common/ComTry.h"
+#include "Common/StringConvert.h"
+#include "Common/StringToInt.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../Common/LimitedStreams.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+
+#include "Common/ItemNameUtils.h"
+
+namespace NArchive {
+namespace NCpio {
+
+namespace NFileHeader
+{
+  namespace NMagic
+  {
+    const char *kMagic1 = "070701";
+    const char *kMagic2 = "070702";
+    const char *kMagic3 = "070707";
+    const char *kEndName = "TRAILER!!!";
+
+    const Byte kMagicForRecord2[2] = { 0xC7, 0x71 };
+  }
+
+  const UInt32 kRecord2Size = 26;
+  /*
+  struct CRecord2
+  {
+    unsigned short c_magic;
+    short c_dev;
+    unsigned short c_ino;
+    unsigned short c_mode;
+    unsigned short c_uid;
+    unsigned short c_gid;
+    unsigned short c_nlink;
+    short c_rdev;
+    unsigned short c_mtimes[2];
+    unsigned short c_namesize;
+    unsigned short c_filesizes[2];
+  };
+  */
+ 
+  const UInt32 kRecordSize = 110;
+  /*
+  struct CRecord
+  {
+    char Magic[6];  // "070701" for "new" portable format, "070702" for CRC format
+    char inode[8];
+    char Mode[8];
+    char UID[8];
+    char GID[8];
+    char nlink[8];
+    char mtime[8];
+    char Size[8]; // must be 0 for FIFOs and directories
+    char DevMajor[8];
+    char DevMinor[8];
+    char RDevMajor[8];  //only valid for chr and blk special files
+    char RDevMinor[8];  //only valid for chr and blk special files
+    char NameSize[8]; // count includes terminating NUL in pathname
+    char ChkSum[8];  // 0 for "new" portable format; for CRC format the sum of all the bytes in the file
+    bool CheckMagic() const
+    { return memcmp(Magic, NMagic::kMagic1, 6) == 0 ||
+             memcmp(Magic, NMagic::kMagic2, 6) == 0; };
+  };
+  */
+
+  const UInt32 kOctRecordSize = 76;
+ 
+}
+
+struct CItem
+{
+  AString Name;
+  UInt32 inode;
+  UInt32 Mode;
+  UInt32 UID;
+  UInt32 GID;
+  UInt32 Size;
+  UInt32 MTime;
+
+  // char LinkFlag;
+  // AString LinkName; ?????
+  char Magic[8];
+  UInt32 NumLinks;
+  UInt32 DevMajor;
+  UInt32 DevMinor;
+  UInt32 RDevMajor;
+  UInt32 RDevMinor;
+  UInt32 ChkSum;
+
+  UInt32 Align;
+
+  bool IsDir() const { return (Mode & 0170000) == 0040000; }
+};
+
+class CItemEx: public CItem
+{
+public:
+  UInt64 HeaderPosition;
+  UInt32 HeaderSize;
+  UInt64 GetDataPosition() const { return HeaderPosition + HeaderSize; };
+};
+
+const UInt32 kMaxBlockSize = NFileHeader::kRecordSize;
+
+class CInArchive
+{
+  CMyComPtr<IInStream> m_Stream;
+  UInt64 m_Position;
+
+  UInt16 _blockSize;
+  Byte _block[kMaxBlockSize];
+  UInt32 _blockPos;
+  Byte ReadByte();
+  UInt16 ReadUInt16();
+  UInt32 ReadUInt32();
+  
+  bool ReadNumber(UInt32 &resultValue);
+  bool ReadOctNumber(int size, UInt32 &resultValue);
+
+  HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize);
+public:
+  HRESULT Open(IInStream *inStream);
+  HRESULT GetNextItem(bool &filled, CItemEx &itemInfo);
+  HRESULT Skip(UInt64 numBytes);
+  HRESULT SkipDataRecords(UInt64 dataSize, UInt32 align);
+};
+
+HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
+{
+  size_t realProcessedSize = size;
+  RINOK(ReadStream(m_Stream, data, &realProcessedSize));
+  processedSize = (UInt32)realProcessedSize;
+  m_Position += processedSize;
+  return S_OK;
+}
+
+Byte CInArchive::ReadByte()
+{
+  if (_blockPos >= _blockSize)
+    throw "Incorrect cpio archive";
+  return _block[_blockPos++];
+}
+
+UInt16 CInArchive::ReadUInt16()
+{
+  UInt16 value = 0;
+  for (int i = 0; i < 2; i++)
+  {
+    Byte b = ReadByte();
+    value |= (UInt16(b) << (8 * i));
+  }
+  return value;
+}
+
+UInt32 CInArchive::ReadUInt32()
+{
+  UInt32 value = 0;
+  for (int i = 0; i < 4; i++)
+  {
+    Byte b = ReadByte();
+    value |= (UInt32(b) << (8 * i));
+  }
+  return value;
+}
+
+HRESULT CInArchive::Open(IInStream *inStream)
+{
+  RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));
+  m_Stream = inStream;
+  return S_OK;
+}
+
+bool CInArchive::ReadNumber(UInt32 &resultValue)
+{
+  resultValue = 0;
+  for (int i = 0; i < 8; i++)
+  {
+    char c = char(ReadByte());
+    int d;
+    if (c >= '0' && c <= '9')
+      d = c - '0';
+    else if (c >= 'A' && c <= 'F')
+      d = 10 + c - 'A';
+    else if (c >= 'a' && c <= 'f')
+      d = 10 + c - 'a';
+    else
+      return false;
+    resultValue *= 0x10;
+    resultValue += d;
+  }
+  return true;
+}
+
+static bool OctalToNumber(const char *s, UInt64 &res)
+{
+  const char *end;
+  res = ConvertOctStringToUInt64(s, &end);
+  return (*end == ' ' || *end == 0);
+}
+
+static bool OctalToNumber32(const char *s, UInt32 &res)
+{
+  UInt64 res64;
+  if (!OctalToNumber(s, res64))
+    return false;
+  res = (UInt32)res64;
+  return (res64 <= 0xFFFFFFFF);
+}
+
+bool CInArchive::ReadOctNumber(int size, UInt32 &resultValue)
+{
+  char sz[32 + 4];
+  int i;
+  for (i = 0; i < size && i < 32; i++)
+    sz[i] = (char)ReadByte();
+  sz[i] = 0;
+  return OctalToNumber32(sz, resultValue);
+}
+
+#define GetFromHex(y) { if (!ReadNumber(y)) return S_FALSE; }
+#define GetFromOct6(y) { if (!ReadOctNumber(6, y)) return S_FALSE; }
+#define GetFromOct11(y) { if (!ReadOctNumber(11, y)) return S_FALSE; }
+
+static unsigned short ConvertValue(unsigned short value, bool convert)
+{
+  if (!convert)
+    return value;
+  return (unsigned short)((((unsigned short)(value & 0xFF)) << 8) | (value >> 8));
+}
+
+static UInt32 GetAlignedSize(UInt32 size, UInt32 align)
+{
+  while ((size & (align - 1)) != 0)
+    size++;
+  return size;
+}
+
+
+HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
+{
+  filled = false;
+
+  UInt32 processedSize;
+  item.HeaderPosition = m_Position;
+
+  _blockSize = kMaxBlockSize;
+  RINOK(ReadBytes(_block, 2, processedSize));
+  if (processedSize != 2)
+    return S_FALSE;
+  _blockPos = 0;
+
+  UInt32 nameSize;
+
+  bool oldBE =
+    _block[0] == NFileHeader::NMagic::kMagicForRecord2[1] &&
+    _block[1] == NFileHeader::NMagic::kMagicForRecord2[0];
+
+  bool binMode = (_block[0] == NFileHeader::NMagic::kMagicForRecord2[0] &&
+    _block[1] == NFileHeader::NMagic::kMagicForRecord2[1]) ||
+    oldBE;
+
+  if (binMode)
+  {
+    RINOK(ReadBytes(_block + 2, NFileHeader::kRecord2Size - 2, processedSize));
+    if (processedSize != NFileHeader::kRecord2Size - 2)
+      return S_FALSE;
+    item.Align = 2;
+    _blockPos = 2;
+    item.DevMajor = 0;
+    item.DevMinor = ConvertValue(ReadUInt16(), oldBE);
+    item.inode = ConvertValue(ReadUInt16(), oldBE);
+    item.Mode = ConvertValue(ReadUInt16(), oldBE);
+    item.UID = ConvertValue(ReadUInt16(), oldBE);
+    item.GID = ConvertValue(ReadUInt16(), oldBE);
+    item.NumLinks = ConvertValue(ReadUInt16(), oldBE);
+    item.RDevMajor =0;
+    item.RDevMinor = ConvertValue(ReadUInt16(), oldBE);
+    UInt16 timeHigh = ConvertValue(ReadUInt16(), oldBE);
+    UInt16 timeLow = ConvertValue(ReadUInt16(), oldBE);
+    item.MTime = (UInt32(timeHigh) << 16) + timeLow;
+    nameSize = ConvertValue(ReadUInt16(), oldBE);
+    UInt16 sizeHigh = ConvertValue(ReadUInt16(), oldBE);
+    UInt16 sizeLow = ConvertValue(ReadUInt16(), oldBE);
+    item.Size = (UInt32(sizeHigh) << 16) + sizeLow;
+
+    item.ChkSum = 0;
+    item.HeaderSize = GetAlignedSize(
+        nameSize + NFileHeader::kRecord2Size, item.Align);
+    nameSize = item.HeaderSize - NFileHeader::kRecord2Size;
+  }
+  else
+  {
+    RINOK(ReadBytes(_block + 2, 4, processedSize));
+    if (processedSize != 4)
+      return S_FALSE;
+
+    bool magicOK =
+        memcmp(_block, NFileHeader::NMagic::kMagic1, 6) == 0 ||
+        memcmp(_block, NFileHeader::NMagic::kMagic2, 6) == 0;
+    _blockPos = 6;
+    if (magicOK)
+    {
+      RINOK(ReadBytes(_block + 6, NFileHeader::kRecordSize - 6, processedSize));
+      if (processedSize != NFileHeader::kRecordSize - 6)
+        return S_FALSE;
+      item.Align = 4;
+
+      GetFromHex(item.inode);
+      GetFromHex(item.Mode);
+      GetFromHex(item.UID);
+      GetFromHex(item.GID);
+      GetFromHex(item.NumLinks);
+      UInt32 mTime;
+      GetFromHex(mTime);
+      item.MTime = mTime;
+      GetFromHex(item.Size);
+      GetFromHex(item.DevMajor);
+      GetFromHex(item.DevMinor);
+      GetFromHex(item.RDevMajor);
+      GetFromHex(item.RDevMinor);
+      GetFromHex(nameSize);
+      GetFromHex(item.ChkSum);
+      item.HeaderSize = GetAlignedSize(
+          nameSize + NFileHeader::kRecordSize, item.Align);
+      nameSize = item.HeaderSize - NFileHeader::kRecordSize;
+    }
+    else
+    {
+      if (!memcmp(_block, NFileHeader::NMagic::kMagic3, 6) == 0)
+        return S_FALSE;
+      RINOK(ReadBytes(_block + 6, NFileHeader::kOctRecordSize - 6, processedSize));
+      if (processedSize != NFileHeader::kOctRecordSize - 6)
+        return S_FALSE;
+      item.Align = 1;
+      item.DevMajor = 0;
+      GetFromOct6(item.DevMinor);
+      GetFromOct6(item.inode);
+      GetFromOct6(item.Mode);
+      GetFromOct6(item.UID);
+      GetFromOct6(item.GID);
+      GetFromOct6(item.NumLinks);
+      item.RDevMajor = 0;
+      GetFromOct6(item.RDevMinor);
+      UInt32 mTime;
+      GetFromOct11(mTime);
+      item.MTime = mTime;
+      GetFromOct6(nameSize);
+      GetFromOct11(item.Size);  // ?????
+      item.HeaderSize = GetAlignedSize(
+          nameSize + NFileHeader::kOctRecordSize, item.Align);
+      nameSize = item.HeaderSize - NFileHeader::kOctRecordSize;
+    }
+  }
+  if (nameSize == 0 || nameSize >= (1 << 27))
+    return E_FAIL;
+  RINOK(ReadBytes(item.Name.GetBuffer(nameSize), nameSize, processedSize));
+  if (processedSize != nameSize)
+    return E_FAIL;
+  item.Name.ReleaseBuffer();
+  if (strcmp(item.Name, NFileHeader::NMagic::kEndName) == 0)
+    return S_OK;
+  filled = true;
+  return S_OK;
+}
+
+HRESULT CInArchive::Skip(UInt64 numBytes)
+{
+  UInt64 newPostion;
+  RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion));
+  m_Position += numBytes;
+  if (m_Position != newPostion)
+    return E_FAIL;
+  return S_OK;
+}
+
+HRESULT CInArchive::SkipDataRecords(UInt64 dataSize, UInt32 align)
+{
+  while ((dataSize & (align - 1)) != 0)
+    dataSize++;
+  return Skip(dataSize);
+}
+
+
+class CHandler:
+  public IInArchive,
+  public IInArchiveGetStream,
+  public CMyUnknownImp
+{
+  CObjectVector<CItemEx> _items;
+  CMyComPtr<IInStream> _stream;
+public:
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+  INTERFACE_IInArchive(;)
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+};
+
+/*
+enum
+{
+  kpidinode = kpidUserDefined,
+  kpidiChkSum
+};
+*/
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidIsDir, VT_BOOL},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMTime, VT_FILETIME},
+  { NULL, kpidPosixAttrib, VT_UI4},
+  // { L"inode", kpidinode, VT_UI4}
+  // { L"CheckSum", kpidiChkSum, VT_UI4}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_NO
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)
+{
+  COM_TRY_BEGIN
+  // try
+  {
+    CInArchive archive;
+
+    UInt64 endPos = 0;
+    bool needSetTotal = true;
+
+    if (callback != NULL)
+    {
+      RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));
+      RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
+    }
+
+    RINOK(archive.Open(stream));
+
+    _items.Clear();
+
+    for (;;)
+    {
+      CItemEx item;
+      bool filled;
+      HRESULT result = archive.GetNextItem(filled, item);
+      if (result == S_FALSE)
+        return S_FALSE;
+      if (result != S_OK)
+        return S_FALSE;
+      if (!filled)
+        break;
+      _items.Add(item);
+      archive.SkipDataRecords(item.Size, item.Align);
+      if (callback != NULL)
+      {
+        if (needSetTotal)
+        {
+          RINOK(callback->SetTotal(NULL, &endPos));
+          needSetTotal = false;
+        }
+        if (_items.Size() % 100 == 0)
+        {
+          UInt64 numFiles = _items.Size();
+          UInt64 numBytes = item.HeaderPosition;
+          RINOK(callback->SetCompleted(&numFiles, &numBytes));
+        }
+      }
+    }
+    if (_items.Size() == 0)
+      return S_FALSE;
+
+    _stream = stream;
+  }
+  /*
+  catch(...)
+  {
+    return S_FALSE;
+  }
+  */
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _items.Clear();
+  _stream.Release();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _items.Size();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  const CItemEx &item = _items[index];
+
+  switch(propID)
+  {
+    case kpidPath: prop = NItemName::GetOSName(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break;
+    case kpidIsDir: prop = item.IsDir(); break;
+    case kpidSize:
+    case kpidPackSize:
+      prop = (UInt64)item.Size;
+      break;
+    case kpidMTime:
+    {
+      if (item.MTime != 0)
+      {
+        FILETIME utc;
+        NWindows::NTime::UnixTimeToFileTime(item.MTime, utc);
+        prop = utc;
+      }
+      break;
+    }
+    case kpidPosixAttrib: prop = item.Mode; break;
+    /*
+    case kpidinode:  prop = item.inode; break;
+    case kpidiChkSum:  prop = item.ChkSum; break;
+    */
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _items.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt64 totalSize = 0;
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+    totalSize += _items[allFilesMode ? i : indices[i]].Size;
+  extractCallback->SetTotal(totalSize);
+
+  UInt64 currentTotalSize = 0;
+  
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);
+  streamSpec->SetStream(_stream);
+
+  for (i = 0; i < numItems; i++)
+  {
+    lps->InSize = lps->OutSize = currentTotalSize;
+    RINOK(lps->SetCur());
+    CMyComPtr<ISequentialOutStream> outStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    Int32 index = allFilesMode ? i : indices[i];
+    const CItemEx &item = _items[index];
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));
+    currentTotalSize += item.Size;
+    if (item.IsDir())
+    {
+      RINOK(extractCallback->PrepareOperation(askMode));
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+      continue;
+    }
+    if (!testMode && !outStream)
+      continue;
+    RINOK(extractCallback->PrepareOperation(askMode));
+    if (testMode)
+    {
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+      continue;
+    }
+    RINOK(_stream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));
+    streamSpec->Init(item.Size);
+    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
+    outStream.Release();
+    RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?
+        NExtract::NOperationResult::kOK:
+        NExtract::NOperationResult::kDataError));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+  COM_TRY_BEGIN
+  const CItemEx &item = _items[index];
+  return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream);
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new NArchive::NCpio::CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"Cpio", L"cpio", 0, 0xED, { 0 }, 0, false, CreateArc, 0 };
+
+REGISTER_ARC(Cpio)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/CramfsHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/CramfsHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/CramfsHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/CramfsHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,644 @@
+// CramfsHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/7zCrc.h"
+#include "../../../C/CpuArch.h"
+#include "../../../C/Alloc.h"
+
+#include "Common/ComTry.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/PropVariantUtils.h"
+
+#include "../Common/LimitedStreams.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamObjects.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+#include "../Compress/ZlibDecoder.h"
+
+namespace NArchive {
+namespace NCramfs {
+
+#define SIGNATURE { 'C','o','m','p','r','e','s','s','e','d',' ','R','O','M','F','S' }
+
+static const UInt32 kSignatureSize = 16;
+static const char kSignature[kSignatureSize] = SIGNATURE;
+
+static const UInt32 kArcSizeMax = (256 + 16) << 20;
+static const UInt32 kNumFilesMax = (1 << 19);
+static const unsigned kNumDirLevelsMax = (1 << 8);
+
+static const UInt32 kHeaderSize = 0x40;
+static const unsigned kHeaderNameSize = 16;
+static const UInt32 kNodeSize = 12;
+
+static const UInt32 kFlag_FsVer2 = (1 << 0);
+
+static const CUInt32PCharPair k_Flags[] =
+{
+  { 0, "Ver2" },
+  { 1, "SortedDirs" },
+  { 8, "Holes" },
+  { 9, "WrongSignature" },
+  { 10, "ShiftedRootOffset" }
+};
+
+static const unsigned kBlockSizeLog = 12;
+static const UInt32 kBlockSize = 1 << kBlockSizeLog;
+
+/*
+struct CNode
+{
+  UInt16 Mode;
+  UInt16 Uid;
+  UInt32 Size;
+  Byte Gid;
+  UInt32 NameLen;
+  UInt32 Offset;
+
+  void Parse(const Byte *p)
+  {
+    Mode = GetUi16(p);
+    Uid = GetUi16(p + 2);
+    Size = Get32(p + 4) & 0xFFFFFF;
+    Gid = p[7];
+    NameLen = p[8] & 0x3F;
+    Offset = Get32(p + 8) >> 6;
+  }
+};
+*/
+
+#define Get32(p) (be ? GetBe32(p) : GetUi32(p))
+
+static UInt32 GetMode(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); }
+static bool IsDir(const Byte *p, bool be) { return (GetMode(p, be) & 0xF000) == 0x4000; }
+
+static UInt32 GetSize(const Byte *p, bool be)
+{
+  if (be)
+    return GetBe32(p + 4) >> 8;
+  else
+    return GetUi32(p + 4) & 0xFFFFFF;
+}
+
+static UInt32 GetNameLen(const Byte *p, bool be)
+{
+  if (be)
+    return (p[8] & 0xFC);
+  else
+    return (p[8] & 0x3F) << 2;
+}
+
+static UInt32 GetOffset(const Byte *p, bool be)
+{
+  if (be)
+    return (GetBe32(p + 8) & 0x03FFFFFF) << 2;
+  else
+    return GetUi32(p + 8) >> 6 << 2;
+}
+
+struct CItem
+{
+  UInt32 Offset;
+  int Parent;
+};
+
+struct CHeader
+{
+  bool be;
+  UInt32 Size;
+  UInt32 Flags;
+  // UInt32 Future;
+  UInt32 Crc;
+  // UInt32 Edition;
+  UInt32 NumBlocks;
+  UInt32 NumFiles;
+  char Name[kHeaderNameSize];
+
+  bool Parse(const Byte *p)
+  {
+    if (memcmp(p + 16, kSignature, kSignatureSize) != 0)
+      return false;
+    switch(GetUi32(p))
+    {
+      case 0x28CD3D45: be = false; break;
+      case 0x453DCD28: be = true; break;
+      default: return false;
+    }
+    Size = Get32(p + 4);
+    Flags = Get32(p + 8);
+    // Future = Get32(p + 0xC);
+    Crc = Get32(p + 0x20);
+    // Edition = Get32(p + 0x24);
+    NumBlocks = Get32(p + 0x28);
+    NumFiles = Get32(p + 0x2C);
+    memcpy(Name, p + 0x30, kHeaderNameSize);
+    return true;
+  }
+
+  bool IsVer2() const { return (Flags & kFlag_FsVer2) != 0; }
+};
+
+class CHandler:
+  public IInArchive,
+  public IInArchiveGetStream,
+  public CMyUnknownImp
+{
+  CRecordVector<CItem> _items;
+  CMyComPtr<IInStream> _stream;
+  Byte *_data;
+  UInt32 _size;
+  UInt32 _headersSize;
+  AString _errorMessage;
+  CHeader _h;
+
+  // Current file
+
+  NCompress::NZlib::CDecoder *_zlibDecoderSpec;
+  CMyComPtr<ICompressCoder> _zlibDecoder;
+  
+  CBufInStream *_inStreamSpec;
+  CMyComPtr<ISequentialInStream> _inStream;
+
+  CBufPtrSeqOutStream *_outStreamSpec;
+  CMyComPtr<ISequentialOutStream> _outStream;
+
+  UInt32 _curBlocksOffset;
+  UInt32 _curNumBlocks;
+
+  HRESULT OpenDir(int parent, UInt32 baseOffsetBase, unsigned level);
+  HRESULT Open2(IInStream *inStream);
+  AString GetPath(int index) const;
+  bool GetPackSize(int index, UInt32 &res) const;
+  void Free();
+public:
+  CHandler(): _data(0) {}
+  ~CHandler() { Free(); }
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+  INTERFACE_IInArchive(;)
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+  HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);
+};
+
+static const STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidIsDir, VT_BOOL},
+  { NULL, kpidSize, VT_UI4},
+  { NULL, kpidPackSize, VT_UI4},
+  { NULL, kpidPosixAttrib, VT_UI4}
+  // { NULL, kpidOffset, VT_UI4}
+};
+
+static const STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidName, VT_BSTR},
+  { NULL, kpidBigEndian, VT_BOOL},
+  { NULL, kpidCharacts, VT_BSTR},
+  { NULL, kpidPhySize, VT_UI4},
+  { NULL, kpidHeadersSize, VT_UI4},
+  { NULL, kpidNumSubFiles, VT_UI4},
+  { NULL, kpidNumBlocks, VT_UI4}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+HRESULT CHandler::OpenDir(int parent, UInt32 baseOffset, unsigned level)
+{
+  const Byte *p = _data + baseOffset;
+  bool be = _h.be;
+  if (!IsDir(p, be))
+    return S_OK;
+  UInt32 offset = GetOffset(p, be);
+  UInt32 size = GetSize(p, be);
+  if (offset == 0 && size == 0)
+    return S_OK;
+  UInt32 end = offset + size;
+  if (offset < kHeaderSize || end > _size || level > kNumDirLevelsMax)
+    return S_FALSE;
+  if (end > _headersSize)
+    _headersSize = end;
+
+  int startIndex = _items.Size();
+  
+  while (size != 0)
+  {
+    if (size < kNodeSize || (UInt32)_items.Size() >= kNumFilesMax)
+      return S_FALSE;
+    CItem item;
+    item.Parent = parent;
+    item.Offset = offset;
+    _items.Add(item);
+    UInt32 nodeLen = kNodeSize + GetNameLen(_data + offset, be);
+    if (size < nodeLen)
+      return S_FALSE;
+    offset += nodeLen;
+    size -= nodeLen;
+  }
+
+  int endIndex = _items.Size();
+  for (int i = startIndex; i < endIndex; i++)
+  {
+    RINOK(OpenDir(i, _items[i].Offset, level + 1));
+  }
+  return S_OK;
+}
+
+HRESULT CHandler::Open2(IInStream *inStream)
+{
+  Byte buf[kHeaderSize];
+  RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize));
+  if (!_h.Parse(buf))
+    return S_FALSE;
+  if (_h.IsVer2())
+  {
+    if (_h.Size < kHeaderSize || _h.Size > kArcSizeMax || _h.NumFiles > kNumFilesMax)
+      return S_FALSE;
+  }
+  else
+  {
+    UInt64 size;
+    RINOK(inStream->Seek(0, STREAM_SEEK_END, &size));
+    if (size > kArcSizeMax)
+      return S_FALSE;
+    _h.Size = (UInt32)size;
+    RINOK(inStream->Seek(kHeaderSize, STREAM_SEEK_SET, NULL));
+  }
+  _data = (Byte *)MidAlloc(_h.Size);
+  if (_data == 0)
+    return E_OUTOFMEMORY;
+  memcpy(_data, buf, kHeaderSize);
+  size_t processed = _h.Size - kHeaderSize;
+  RINOK(ReadStream(inStream, _data + kHeaderSize, &processed));
+  if (processed < kNodeSize)
+    return S_FALSE;
+  _size = kHeaderSize + (UInt32)processed;
+  if (_size != _h.Size)
+    _errorMessage = "Unexpected end of archive";
+  else
+  {
+    SetUi32(_data + 0x20, 0);
+    if (_h.IsVer2())
+      if (CrcCalc(_data, _h.Size) != _h.Crc)
+        _errorMessage = "CRC error";
+  }
+  if (_h.IsVer2())
+    _items.Reserve(_h.NumFiles - 1);
+  return OpenDir(-1, kHeaderSize, 0);
+}
+
+AString CHandler::GetPath(int index) const
+{
+  unsigned len = 0;
+  int indexMem = index;
+  do
+  {
+    const CItem &item = _items[index];
+    index = item.Parent;
+    const Byte *p = _data + item.Offset;
+    unsigned size = GetNameLen(p, _h.be);
+    p += kNodeSize;
+    unsigned i;
+    for (i = 0; i < size && p[i]; i++);
+    len += i + 1;
+  }
+  while (index >= 0);
+  len--;
+
+  AString path;
+  char *dest = path.GetBuffer(len) + len;
+  index = indexMem;
+  for (;;)
+  {
+    const CItem &item = _items[index];
+    index = item.Parent;
+    const Byte *p = _data + item.Offset;
+    unsigned size = GetNameLen(p, _h.be);
+    p += kNodeSize;
+    unsigned i;
+    for (i = 0; i < size && p[i]; i++);
+    dest -= i;
+    memcpy(dest, p, i);
+    if (index < 0)
+      break;
+    *(--dest) = CHAR_PATH_SEPARATOR;
+  }
+  path.ReleaseBuffer(len);
+  return path;
+}
+
+bool CHandler::GetPackSize(int index, UInt32 &res) const
+{
+  const CItem &item = _items[index];
+  const Byte *p = _data + item.Offset;
+  bool be = _h.be;
+  UInt32 offset = GetOffset(p, be);
+  if (offset < kHeaderSize)
+    return false;
+  UInt32 numBlocks = (GetSize(p, be) + kBlockSize - 1) >> kBlockSizeLog;
+  UInt32 start = offset + numBlocks * 4;
+  if (start > _size)
+    return false;
+  UInt32 end = Get32(_data + start - 4);
+  if (end < start)
+    return false;
+  res = end - start;
+  return true;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */)
+{
+  COM_TRY_BEGIN
+  {
+    Close();
+    RINOK(Open2(stream));
+    _stream = stream;
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+void CHandler::Free()
+{
+  MidFree(_data);
+  _data = 0;
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _headersSize = 0;
+  _items.Clear();
+  _stream.Release();
+  _errorMessage.Empty();
+  Free();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _items.Size();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidName:
+    {
+      char dest[kHeaderNameSize + 4];
+      memcpy(dest, _h.Name, kHeaderNameSize);
+      dest[kHeaderNameSize] = 0;
+      prop = dest;
+      break;
+    }
+    case kpidBigEndian: prop = _h.be; break;
+    case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break;
+    case kpidNumBlocks: if (_h.IsVer2()) prop = _h.NumBlocks; break;
+    case kpidNumSubFiles: if (_h.IsVer2()) prop = _h.NumFiles; break;
+    case kpidPhySize: if (_h.IsVer2()) prop = _h.Size; break;
+    case kpidHeadersSize: prop = _headersSize; break;
+    case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  const CItem &item = _items[index];
+  const Byte *p = _data + item.Offset;
+  bool be = _h.be;
+  bool isDir = IsDir(p, be);
+  switch(propID)
+  {
+    case kpidPath: prop = MultiByteToUnicodeString(GetPath(index), CP_OEMCP); break;
+    case kpidIsDir: prop = isDir; break;
+    // case kpidOffset: prop = (UInt32)GetOffset(p, be); break;
+    case kpidSize: if (!isDir) prop = GetSize(p, be); break;
+    case kpidPackSize:
+      if (!isDir)
+      {
+        UInt32 size;
+        if (GetPackSize(index, size))
+          prop = size;
+      }
+      break;
+    case kpidPosixAttrib: prop = (UInt32)GetMode(p, be); break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+class CCramfsInStream: public CCachedInStream
+{
+  HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);
+public:
+  CHandler *Handler;
+};
+
+HRESULT CCramfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
+{
+  return Handler->ReadBlock(blockIndex, dest, blockSize);
+}
+
+HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
+{
+  if (!_zlibDecoder)
+  {
+    _zlibDecoderSpec = new NCompress::NZlib::CDecoder();
+    _zlibDecoder = _zlibDecoderSpec;
+  }
+  if (!_inStream)
+  {
+    _inStreamSpec = new CBufInStream();
+    _inStream = _inStreamSpec;
+  }
+  if (!_outStream)
+  {
+    _outStreamSpec = new CBufPtrSeqOutStream();
+    _outStream = _outStreamSpec;
+  }
+  bool be = _h.be;
+  const Byte *p = _data + (_curBlocksOffset + (UInt32)blockIndex * 4);
+  UInt32 start = (blockIndex == 0 ? _curBlocksOffset + _curNumBlocks * 4: Get32(p - 4));
+  UInt32 end = Get32(p);
+  if (end < start || end > _size)
+    return S_FALSE;
+  UInt32 inSize = end - start;
+  _inStreamSpec->Init(_data + start, inSize);
+  _outStreamSpec->Init(dest, blockSize);
+  RINOK(_zlibDecoder->Code(_inStream, _outStream, NULL, NULL, NULL));
+  return (_zlibDecoderSpec->GetInputProcessedSize() == inSize &&
+      _outStreamSpec->GetPos() == blockSize) ? S_OK : S_FALSE;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _items.Size();
+  if (numItems == 0)
+    return S_OK;
+  bool be = _h.be;
+  UInt64 totalSize = 0;
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+  {
+    const Byte *p = _data + _items[allFilesMode ? i : indices[i]].Offset;
+    if (!IsDir(p, be))
+      totalSize += GetSize(p, be);
+  }
+  extractCallback->SetTotal(totalSize);
+
+  UInt64 totalPackSize;
+  totalSize = totalPackSize = 0;
+  
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);
+  streamSpec->SetStream(_stream);
+
+  for (i = 0; i < numItems; i++)
+  {
+    lps->InSize = totalPackSize;
+    lps->OutSize = totalSize;
+    RINOK(lps->SetCur());
+    CMyComPtr<ISequentialOutStream> outStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    UInt32 index = allFilesMode ? i : indices[i];
+    const CItem &item = _items[index];
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));
+    const Byte *p = _data + item.Offset;
+
+    if (IsDir(p, be))
+    {
+      RINOK(extractCallback->PrepareOperation(askMode));
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+      continue;
+    }
+    UInt32 curSize = GetSize(p, be);
+    totalSize += curSize;
+    UInt32 packSize;
+    if (GetPackSize(index, packSize))
+      totalPackSize += packSize;
+
+    if (!testMode && !outStream)
+      continue;
+    RINOK(extractCallback->PrepareOperation(askMode));
+
+    UInt32 offset = GetOffset(p, be);
+    if (offset < kHeaderSize)
+      curSize = 0;
+
+    int res = NExtract::NOperationResult::kDataError;
+    {
+      CMyComPtr<ISequentialInStream> inSeqStream;
+      CMyComPtr<IInStream> inStream;
+      HRESULT hres = GetStream(index, &inSeqStream);
+      if (inSeqStream)
+        inSeqStream.QueryInterface(IID_IInStream, &inStream);
+      if (hres == E_OUTOFMEMORY)
+        return E_OUTOFMEMORY;
+      if (hres == S_FALSE || !inStream)
+        res = NExtract::NOperationResult::kUnSupportedMethod;
+      else
+      {
+        RINOK(hres);
+        if (inStream)
+        {
+          HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
+          if (hres != S_OK && hres != S_FALSE)
+          {
+            RINOK(hres);
+          }
+          if (copyCoderSpec->TotalSize == curSize && hres == S_OK)
+            res = NExtract::NOperationResult::kOK;
+        }
+      }
+    }
+    RINOK(extractCallback->SetOperationResult(res));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+  COM_TRY_BEGIN
+
+  const CItem &item = _items[index];
+  const Byte *p = _data + item.Offset;
+
+  bool be = _h.be;
+  if (IsDir(p, be))
+    return E_FAIL;
+
+  UInt32 size = GetSize(p, be);
+  UInt32 numBlocks = (size + kBlockSize - 1) >> kBlockSizeLog;
+  UInt32 offset = GetOffset(p, be);
+  if (offset < kHeaderSize)
+  {
+    if (offset != 0)
+      return S_FALSE;
+    CBufInStream *streamSpec = new CBufInStream;
+    CMyComPtr<IInStream> streamTemp = streamSpec;
+    streamSpec->Init(NULL, 0);
+    *stream = streamTemp.Detach();
+    return S_OK;
+  }
+
+  if (offset + numBlocks * 4 > _size)
+    return S_FALSE;
+  UInt32 prev = offset;
+  for (UInt32 i = 0; i < numBlocks; i++)
+  {
+    UInt32 next = Get32(_data + offset + i * 4);
+    if (next < prev || next > _size)
+      return S_FALSE;
+    prev = next;
+  }
+
+  CCramfsInStream *streamSpec = new CCramfsInStream;
+  CMyComPtr<IInStream> streamTemp = streamSpec;
+  _curNumBlocks = numBlocks;
+  _curBlocksOffset = offset;
+  streamSpec->Handler = this;
+  if (!streamSpec->Alloc(kBlockSizeLog, 21 - kBlockSizeLog))
+    return E_OUTOFMEMORY;
+  streamSpec->Init(size);
+  *stream = streamTemp.Detach();
+
+  return S_OK;
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new NArchive::NCramfs::CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"CramFS", L"cramfs", 0, 0xD3, SIGNATURE, kSignatureSize, false, CreateArc, 0 };
+
+REGISTER_ARC(Cramfs)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DebHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DebHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DebHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DebHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,413 @@
+// DebHandler.cpp
+
+#include "StdAfx.h"
+
+#include "Common/ComTry.h"
+#include "Common/StringConvert.h"
+#include "Common/StringToInt.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../Common/LimitedStreams.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+
+#include "Common/ItemNameUtils.h"
+
+using namespace NWindows;
+using namespace NTime;
+
+namespace NArchive {
+namespace NDeb {
+
+namespace NHeader
+{
+  const int kSignatureLen = 8;
+  
+  const char *kSignature = "!<arch>\n";
+
+  const int kNameSize = 16;
+  const int kTimeSize = 12;
+  const int kModeSize = 8;
+  const int kSizeSize = 10;
+
+  /*
+  struct CHeader
+  {
+    char Name[kNameSize];
+    char MTime[kTimeSize];
+    char Number0[6];
+    char Number1[6];
+    char Mode[kModeSize];
+    char Size[kSizeSize];
+    char Quote;
+    char NewLine;
+  };
+  */
+  const int kHeaderSize = kNameSize + kTimeSize + 6 + 6 + kModeSize + kSizeSize + 1 + 1;
+}
+
+struct CItem
+{
+  AString Name;
+  UInt64 Size;
+  UInt32 MTime;
+  UInt32 Mode;
+
+  UInt64 HeaderPos;
+  UInt64 GetDataPos() const { return HeaderPos + NHeader::kHeaderSize; };
+  // UInt64 GetFullSize() const { return NFileHeader::kRecordSize + Size; };
+};
+
+class CInArchive
+{
+  CMyComPtr<IInStream> m_Stream;
+  
+  HRESULT GetNextItemReal(bool &filled, CItem &itemInfo);
+public:
+  UInt64 m_Position;
+  HRESULT Open(IInStream *inStream);
+  HRESULT GetNextItem(bool &filled, CItem &itemInfo);
+  HRESULT SkipData(UInt64 dataSize);
+};
+
+HRESULT CInArchive::Open(IInStream *inStream)
+{
+  RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));
+  char signature[NHeader::kSignatureLen];
+  RINOK(ReadStream_FALSE(inStream, signature, NHeader::kSignatureLen));
+  m_Position += NHeader::kSignatureLen;
+  if (memcmp(signature, NHeader::kSignature, NHeader::kSignatureLen) != 0)
+    return S_FALSE;
+  m_Stream = inStream;
+  return S_OK;
+}
+
+static void MyStrNCpy(char *dest, const char *src, int size)
+{
+  for (int i = 0; i < size; i++)
+  {
+    char c = src[i];
+    dest[i] = c;
+    if (c == 0)
+      break;
+  }
+}
+
+static bool OctalToNumber(const char *s, int size, UInt64 &res)
+{
+  char sz[32];
+  MyStrNCpy(sz, s, size);
+  sz[size] = 0;
+  const char *end;
+  int i;
+  for (i = 0; sz[i] == ' '; i++);
+  res = ConvertOctStringToUInt64(sz + i, &end);
+  return (*end == ' ' || *end == 0);
+}
+
+static bool OctalToNumber32(const char *s, int size, UInt32 &res)
+{
+  UInt64 res64;
+  if (!OctalToNumber(s, size, res64))
+    return false;
+  res = (UInt32)res64;
+  return (res64 <= 0xFFFFFFFF);
+}
+
+static bool DecimalToNumber(const char *s, int size, UInt64 &res)
+{
+  char sz[32];
+  MyStrNCpy(sz, s, size);
+  sz[size] = 0;
+  const char *end;
+  int i;
+  for (i = 0; sz[i] == ' '; i++);
+  res = ConvertStringToUInt64(sz + i, &end);
+  return (*end == ' ' || *end == 0);
+}
+
+static bool DecimalToNumber32(const char *s, int size, UInt32 &res)
+{
+  UInt64 res64;
+  if (!DecimalToNumber(s, size, res64))
+    return false;
+  res = (UInt32)res64;
+  return (res64 <= 0xFFFFFFFF);
+}
+
+#define RIF(x) { if (!(x)) return S_FALSE; }
+
+
+HRESULT CInArchive::GetNextItemReal(bool &filled, CItem &item)
+{
+  filled = false;
+
+  char header[NHeader::kHeaderSize];
+  const char *cur = header;
+
+  size_t processedSize = sizeof(header);
+  item.HeaderPos = m_Position;
+  RINOK(ReadStream(m_Stream, header, &processedSize));
+  if (processedSize != sizeof(header))
+    return S_OK;
+  m_Position += processedSize;
+  
+  char tempString[NHeader::kNameSize + 1];
+  MyStrNCpy(tempString, cur, NHeader::kNameSize);
+  cur += NHeader::kNameSize;
+  tempString[NHeader::kNameSize] = '\0';
+  item.Name = tempString;
+  item.Name.Trim();
+
+  for (int i = 0; i < item.Name.Length(); i++)
+    if (((Byte)item.Name[i]) < 0x20)
+      return S_FALSE;
+
+  RIF(DecimalToNumber32(cur, NHeader::kTimeSize, item.MTime));
+  cur += NHeader::kTimeSize;
+
+  cur += 6 + 6;
+  
+  RIF(OctalToNumber32(cur, NHeader::kModeSize, item.Mode));
+  cur += NHeader::kModeSize;
+
+  RIF(DecimalToNumber(cur, NHeader::kSizeSize, item.Size));
+  cur += NHeader::kSizeSize;
+
+  filled = true;
+  return S_OK;
+}
+
+HRESULT CInArchive::GetNextItem(bool &filled, CItem &item)
+{
+  for (;;)
+  {
+    RINOK(GetNextItemReal(filled, item));
+    if (!filled)
+      return S_OK;
+    if (item.Name.Compare("debian-binary") != 0)
+      return S_OK;
+    if (item.Size != 4)
+      return S_OK;
+    SkipData(item.Size);
+  }
+}
+
+HRESULT CInArchive::SkipData(UInt64 dataSize)
+{
+  return m_Stream->Seek((dataSize + 1) & (~((UInt64)0x1)), STREAM_SEEK_CUR, &m_Position);
+}
+
+class CHandler:
+  public IInArchive,
+  public IInArchiveGetStream,
+  public CMyUnknownImp
+{
+  CObjectVector<CItem> _items;
+  CMyComPtr<IInStream> _stream;
+  Int32 _mainSubfile;
+  UInt64 _phySize;
+public:
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+  INTERFACE_IInArchive(;)
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+};
+
+static STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidPhySize, VT_UI8}
+};
+
+static STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidMTime, VT_FILETIME}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+    const UInt64 * /* maxCheckStartPosition */,
+    IArchiveOpenCallback *openArchiveCallback)
+{
+  COM_TRY_BEGIN
+  {
+    _mainSubfile = -1;
+    CInArchive archive;
+    if (archive.Open(stream) != S_OK)
+      return S_FALSE;
+    _items.Clear();
+
+    if (openArchiveCallback != NULL)
+    {
+      RINOK(openArchiveCallback->SetTotal(NULL, NULL));
+      UInt64 numFiles = _items.Size();
+      RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
+    }
+
+    for (;;)
+    {
+      CItem item;
+      bool filled;
+      HRESULT result = archive.GetNextItem(filled, item);
+      if (result == S_FALSE)
+        return S_FALSE;
+      if (result != S_OK)
+        return S_FALSE;
+      if (!filled)
+        break;
+      if (item.Name.Left(5) == "data.")
+        _mainSubfile = _items.Size();
+      _items.Add(item);
+      archive.SkipData(item.Size);
+      if (openArchiveCallback != NULL)
+      {
+        UInt64 numFiles = _items.Size();
+        RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
+      }
+    }
+    _stream = stream;
+    _phySize = archive.m_Position;
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _stream.Release();
+  _items.Clear();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _items.Size();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidPhySize: prop = _phySize; break;
+    case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  const CItem &item = _items[index];
+
+  switch(propID)
+  {
+    case kpidPath: prop = (const wchar_t *)NItemName::GetOSName2(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break;
+    case kpidSize:
+    case kpidPackSize:
+      prop = item.Size;
+      break;
+    case kpidMTime:
+    {
+      if (item.MTime != 0)
+      {
+        FILETIME fileTime;
+        NTime::UnixTimeToFileTime(item.MTime, fileTime);
+        prop = fileTime;
+      }
+      break;
+    }
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _items.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt64 totalSize = 0;
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+    totalSize += _items[allFilesMode ? i : indices[i]].Size;
+  extractCallback->SetTotal(totalSize);
+
+  UInt64 currentTotalSize = 0;
+  
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);
+  streamSpec->SetStream(_stream);
+
+  for (i = 0; i < numItems; i++)
+  {
+    lps->InSize = lps->OutSize = currentTotalSize;
+    RINOK(lps->SetCur());
+    CMyComPtr<ISequentialOutStream> realOutStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    Int32 index = allFilesMode ? i : indices[i];
+    const CItem &item = _items[index];
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+    currentTotalSize += item.Size;
+    
+    if (!testMode && !realOutStream)
+      continue;
+    RINOK(extractCallback->PrepareOperation(askMode));
+    if (testMode)
+    {
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+      continue;
+    }
+    RINOK(_stream->Seek(item.GetDataPos(), STREAM_SEEK_SET, NULL));
+    streamSpec->Init(item.Size);
+    RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
+    realOutStream.Release();
+    RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?
+        NExtract::NOperationResult::kOK:
+        NExtract::NOperationResult::kDataError));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+  COM_TRY_BEGIN
+  const CItem &item = _items[index];
+  return CreateLimitedInStream(_stream, item.GetDataPos(), item.Size, stream);
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new NArchive::NDeb::CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"Deb", L"deb", 0, 0xEC, { '!', '<', 'a', 'r', 'c', 'h', '>', '\n' }, 8, false, CreateArc, 0 };
+
+REGISTER_ARC(Deb)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DeflateProps.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DeflateProps.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DeflateProps.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DeflateProps.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,118 @@
+// DeflateProps.cpp
+
+#include "StdAfx.h"
+
+#include "Windows/PropVariant.h"
+
+#include "Common/ParseProperties.h"
+
+#include "DeflateProps.h"
+
+namespace NArchive {
+
+static const UInt32 kAlgo1 = 0;
+static const UInt32 kAlgo5 = 1;
+
+static const UInt32 kPasses1 = 1;
+static const UInt32 kPasses7 = 3;
+static const UInt32 kPasses9 = 10;
+
+static const UInt32 kFb1 = 32;
+static const UInt32 kFb7 = 64;
+static const UInt32 kFb9 = 128;
+
+void CDeflateProps::Normalize()
+{
+  UInt32 level = Level;
+  if (level == 0xFFFFFFFF)
+    level = 5;
+  
+  if (Algo == 0xFFFFFFFF)
+    Algo = (level >= 5 ?
+      kAlgo5 :
+      kAlgo1);
+
+  if (NumPasses == 0xFFFFFFFF)
+    NumPasses =
+      (level >= 9 ? kPasses9 :
+      (level >= 7 ? kPasses7 :
+                    kPasses1));
+  if (Fb == 0xFFFFFFFF)
+    Fb =
+      (level >= 9 ? kFb9 :
+      (level >= 7 ? kFb7 :
+                    kFb1));
+}
+
+HRESULT CDeflateProps::SetCoderProperties(ICompressSetCoderProperties *setCoderProperties)
+{
+  Normalize();
+
+  NWindows::NCOM::CPropVariant props[] =
+  {
+    Algo,
+    NumPasses,
+    Fb,
+    Mc
+  };
+  PROPID propIDs[] =
+  {
+    NCoderPropID::kAlgorithm,
+    NCoderPropID::kNumPasses,
+    NCoderPropID::kNumFastBytes,
+    NCoderPropID::kMatchFinderCycles
+  };
+  int numProps = sizeof(propIDs) / sizeof(propIDs[0]);
+  if (!McDefined)
+    numProps--;
+  return setCoderProperties->SetCoderProperties(propIDs, props, numProps);
+}
+
+HRESULT CDeflateProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
+{
+  Init();
+  for (int i = 0; i < numProps; i++)
+  {
+    UString name = names[i];
+    name.MakeUpper();
+    if (name.IsEmpty())
+      return E_INVALIDARG;
+    const PROPVARIANT &prop = values[i];
+    if (name[0] == L'X')
+    {
+      UInt32 a = 9;
+      RINOK(ParsePropValue(name.Mid(1), prop, a));
+      Level = a;
+    }
+    else if (name.Left(1) == L"A")
+    {
+      UInt32 a = kAlgo5;
+      RINOK(ParsePropValue(name.Mid(1), prop, a));
+      Algo = a;
+    }
+    else if (name.Left(4) == L"PASS")
+    {
+      UInt32 a = kPasses9;
+      RINOK(ParsePropValue(name.Mid(4), prop, a));
+      NumPasses = a;
+    }
+    else if (name.Left(2) == L"FB")
+    {
+      UInt32 a = kFb9;
+      RINOK(ParsePropValue(name.Mid(2), prop, a));
+      Fb = a;
+    }
+    else if (name.Left(2) == L"MC")
+    {
+      UInt32 a = 0xFFFFFFFF;
+      RINOK(ParsePropValue(name.Mid(2), prop, a));
+      Mc = a;
+      McDefined = true;
+    }
+    else
+      return E_INVALIDARG;
+  }
+  return S_OK;
+}
+
+}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DeflateProps.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DeflateProps.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DeflateProps.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DeflateProps.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,35 @@
+// DeflateProps.h
+
+#ifndef __DEFLATE_PROPS_H
+#define __DEFLATE_PROPS_H
+
+#include "../ICoder.h"
+
+namespace NArchive {
+
+class CDeflateProps
+{
+  UInt32 Level;
+  UInt32 NumPasses;
+  UInt32 Fb;
+  UInt32 Algo;
+  UInt32 Mc;
+  bool McDefined;
+
+  void Init()
+  {
+    Level = NumPasses = Fb = Algo = Mc = 0xFFFFFFFF;
+    McDefined = false;
+  }
+  void Normalize();
+public:
+  CDeflateProps() { Init(); }
+  bool IsMaximum() const { return Algo > 0; }
+
+  HRESULT SetCoderProperties(ICompressSetCoderProperties *setCoderProperties);
+  HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);
+};
+
+}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DllExports2.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DllExports2.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DllExports2.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DllExports2.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,76 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/MyInitGuid.h"
+
+#if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)
+#include "../../../C/Alloc.h"
+#endif
+
+#include "../../Common/ComTry.h"
+
+#include "../../Windows/NtCheck.h"
+#include "../../Windows/PropVariant.h"
+
+#include "../ICoder.h"
+#include "../IPassword.h"
+
+#include "IArchive.h"
+
+HINSTANCE g_hInstance;
+
+#define NT_CHECK_FAIL_ACTION return FALSE;
+
+#ifdef _WIN32
+extern "C"
+BOOL WINAPI DllMain(
+  #ifdef UNDER_CE
+  HANDLE
+  #else
+  HINSTANCE
+  #endif
+  hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
+{
+  if (dwReason == DLL_PROCESS_ATTACH)
+  {
+    g_hInstance = (HINSTANCE)hInstance;
+    NT_CHECK;
+  }
+  return TRUE;
+}
+#endif
+
+DEFINE_GUID(CLSID_CArchiveHandler,
+0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
+
+static const UInt16 kDecodeId = 0x2790;
+
+DEFINE_GUID(CLSID_CCodec,
+0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+
+STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);
+STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject);
+
+STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
+{
+  // COM_TRY_BEGIN
+  *outObject = 0;
+  if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter)
+  {
+    return CreateCoder(clsid, iid, outObject);
+  }
+  else
+  {
+    return CreateArchiver(clsid, iid, outObject);
+  }
+  // COM_TRY_END
+}
+
+STDAPI SetLargePageMode()
+{
+  #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)
+  SetLargePageSize();
+  #endif
+  return S_OK;
+}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DmgHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DmgHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DmgHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/DmgHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,918 @@
+// DmgHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/Buffer.h"
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+#include "Common/MyXml.h"
+#include "Common/UTFConvert.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../Common/LimitedStreams.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/BZip2Decoder.h"
+#include "../Compress/CopyCoder.h"
+#include "../Compress/ZlibDecoder.h"
+
+// #define DMG_SHOW_RAW
+
+// #include <stdio.h>
+#define PRF(x) // x
+
+#define Get32(p) GetBe32(p)
+#define Get64(p) GetBe64(p)
+
+static int Base64ToByte(char c)
+{
+  if (c >= 'A' && c <= 'Z') return c - 'A';
+  if (c >= 'a' && c <= 'z') return c - 'a' + 26;
+  if (c >= '0' && c <= '9') return c - '0' + 52;
+  if (c == '+') return 62;
+  if (c == '/') return 63;
+  if (c == '=') return 0;
+  return -1;
+}
+
+static int Base64ToBin(Byte *dest, const char *src, int srcLen)
+{
+  int srcPos = 0;
+  int destPos = 0;
+  while (srcPos < srcLen)
+  {
+    Byte buf[4];
+    int filled = 0;
+    while (srcPos < srcLen)
+    {
+      int n = Base64ToByte(src[srcPos++]);
+      if (n >= 0)
+      {
+        buf[filled++] = (Byte)n;
+        if (filled == 4)
+          break;
+      }
+    }
+    if (filled >= 2) { if (dest) dest[destPos] = (buf[0] << 2) | (buf[1] >> 4); destPos++; }
+    if (filled >= 3) { if (dest) dest[destPos] = (buf[1] << 4) | (buf[2] >> 2); destPos++; }
+    if (filled >= 4) { if (dest) dest[destPos] = (buf[2] << 6) | (buf[3]     ); destPos++; }
+  }
+  return destPos;
+}
+
+static UString GetSizeString(UInt64 value)
+{
+  wchar_t s[32];
+  wchar_t c;
+  if (value < (UInt64)20000) c = 0;
+  else if (value < ((UInt64)20000 << 10)) { value >>= 10; c = L'K'; }
+  else if (value < ((UInt64)20000 << 20)) { value >>= 20; c = L'M'; }
+  else                                    { value >>= 30; c = L'G'; }
+  ConvertUInt64ToString(value, s);
+  int p = MyStringLen(s);
+  s[p++] = c;
+  s[p++] = L'\0';
+  return s;
+}
+
+namespace NArchive {
+namespace NDmg {
+
+struct CBlock
+{
+  UInt32 Type;
+  UInt64 UnpPos;
+  UInt64 UnpSize;
+  UInt64 PackPos;
+  UInt64 PackSize;
+  
+  UInt64 GetNextPackOffset() const { return PackPos + PackSize; }
+};
+
+struct CFile
+{
+  CByteBuffer Raw;
+  UInt64 StartPos;
+  CRecordVector<CBlock> Blocks;
+  UInt64 GetUnpackSize() const
+  {
+    UInt64 size = 0;
+    for (int i = 0; i < Blocks.Size(); i++)
+      size += Blocks[i].UnpSize;
+    return size;
+  };
+  UInt64 GetPackSize() const
+  {
+    UInt64 size = 0;
+    for (int i = 0; i < Blocks.Size(); i++)
+      size += Blocks[i].PackSize;
+    return size;
+  };
+
+  AString Name;
+};
+
+class CHandler:
+  public IInArchive,
+  public CMyUnknownImp
+{
+  CMyComPtr<IInStream> _inStream;
+
+  AString _xml;
+  CObjectVector<CFile> _files;
+  CRecordVector<int> _fileIndices;
+
+  HRESULT Open2(IInStream *stream);
+  HRESULT Extract(IInStream *stream);
+public:
+  MY_UNKNOWN_IMP1(IInArchive)
+  INTERFACE_IInArchive(;)
+};
+
+const UInt32 kXmlSizeMax = ((UInt32)1 << 31) - (1 << 14);
+
+enum
+{
+  METHOD_ZERO_0 = 0,
+  METHOD_COPY   = 1,
+  METHOD_ZERO_2 = 2,
+  METHOD_ADC    = 0x80000004,
+  METHOD_ZLIB   = 0x80000005,
+  METHOD_BZIP2  = 0x80000006,
+  METHOD_DUMMY  = 0x7FFFFFFE,
+  METHOD_END    = 0xFFFFFFFF
+};
+
+struct CMethodStat
+{
+  UInt32 NumBlocks;
+  UInt64 PackSize;
+  UInt64 UnpSize;
+  CMethodStat(): NumBlocks(0), PackSize(0), UnpSize(0) {}
+};
+
+struct CMethods
+{
+  CRecordVector<CMethodStat> Stats;
+  CRecordVector<UInt32> Types;
+  void Update(const CFile &file);
+  UString GetString() const;
+};
+
+void CMethods::Update(const CFile &file)
+{
+  for (int i = 0; i < file.Blocks.Size(); i++)
+  {
+    const CBlock &b = file.Blocks[i];
+    int index = Types.FindInSorted(b.Type);
+    if (index < 0)
+    {
+      index = Types.AddToUniqueSorted(b.Type);
+      Stats.Insert(index, CMethodStat());
+    }
+    CMethodStat &m = Stats[index];
+    m.PackSize += b.PackSize;
+    m.UnpSize += b.UnpSize;
+    m.NumBlocks++;
+  }
+}
+
+UString CMethods::GetString() const
+{
+  UString res;
+  for (int i = 0; i < Types.Size(); i++)
+  {
+    if (i != 0)
+      res += L' ';
+    wchar_t buf[32];
+    const wchar_t *s;
+    const CMethodStat &m = Stats[i];
+    bool showPack = true;
+    UInt32 type = Types[i];
+    switch(type)
+    {
+      case METHOD_ZERO_0: s = L"zero0"; showPack = (m.PackSize != 0); break;
+      case METHOD_ZERO_2: s = L"zero2"; showPack = (m.PackSize != 0); break;
+      case METHOD_COPY:   s = L"copy"; showPack = (m.UnpSize != m.PackSize); break;
+      case METHOD_ADC:    s = L"adc"; break;
+      case METHOD_ZLIB:   s = L"zlib"; break;
+      case METHOD_BZIP2:  s = L"bzip2"; break;
+      default: ConvertUInt64ToString(type, buf); s = buf;
+    }
+    res += s;
+    if (m.NumBlocks != 1)
+    {
+      res += L'[';
+      ConvertUInt64ToString(m.NumBlocks, buf);
+      res += buf;
+      res += L']';
+    }
+    res += L'-';
+    res += GetSizeString(m.UnpSize);
+    if (showPack)
+    {
+      res += L'-';
+      res += GetSizeString(m.PackSize);
+    }
+  }
+  return res;
+}
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidComment, VT_BSTR},
+  { NULL, kpidMethod, VT_BSTR}
+};
+
+IMP_IInArchive_Props
+
+STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidMethod, VT_BSTR},
+  { NULL, kpidNumBlocks, VT_UI4}
+};
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidMethod:
+    {
+      CMethods m;
+      for (int i = 0; i < _files.Size(); i++)
+        m.Update(_files[i]);
+      prop = m.GetString();
+      break;
+    }
+    case kpidNumBlocks:
+    {
+      UInt64 numBlocks = 0;
+      for (int i = 0; i < _files.Size(); i++)
+        numBlocks += _files[i].Blocks.Size();
+      prop = numBlocks;
+      break;
+    }
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+IMP_IInArchive_ArcProps
+
+static int FindKeyPair(const CXmlItem &item, const AString &key, const AString &nextTag)
+{
+  for (int i = 0; i + 1 < item.SubItems.Size(); i++)
+  {
+    const CXmlItem &si = item.SubItems[i];
+    if (si.IsTagged("key") && si.GetSubString() == key && item.SubItems[i + 1].IsTagged(nextTag))
+      return i + 1;
+  }
+  return -1;
+}
+
+static AString GetStringFromKeyPair(const CXmlItem &item, const AString &key, const AString &nextTag)
+{
+  int index = FindKeyPair(item, key, nextTag);
+  if (index >= 0)
+    return item.SubItems[index].GetSubString();
+  return AString();
+}
+
+HRESULT CHandler::Open2(IInStream *stream)
+{
+  const int HEADER_SIZE = 0x1E0;
+
+  UInt64 headerPos;
+  RINOK(stream->Seek(-HEADER_SIZE, STREAM_SEEK_END, &headerPos));
+  Byte buf[HEADER_SIZE];
+  RINOK(ReadStream_FALSE(stream, buf, HEADER_SIZE));
+  UInt64 address1 = Get64(buf + 0);
+  UInt64 address2 = Get64(buf + 0xB8);
+  UInt64 size64 = Get64(buf + 0xC0);
+  if (address1 != address2 || size64 >= kXmlSizeMax || size64 == 0 ||
+      address1 >= headerPos || address1 + size64 > headerPos)
+    return S_FALSE;
+  RINOK(stream->Seek(address1, STREAM_SEEK_SET, NULL));
+  size_t size = (size_t)size64;
+
+  char *ss = _xml.GetBuffer((int)size + 1);
+  RINOK(ReadStream_FALSE(stream, ss, size));
+  ss[size] = 0;
+  _xml.ReleaseBuffer();
+
+  CXml xml;
+  if (!xml.Parse(_xml))
+    return S_FALSE;
+  if (xml.Root.Name != "plist")
+    return S_FALSE;
+  
+  int dictIndex = xml.Root.FindSubTag("dict");
+  if (dictIndex < 0)
+    return S_FALSE;
+  
+  const CXmlItem &dictItem = xml.Root.SubItems[dictIndex];
+  int rfDictIndex = FindKeyPair(dictItem, "resource-fork", "dict");
+  if (rfDictIndex < 0)
+    return S_FALSE;
+  
+  const CXmlItem &rfDictItem = dictItem.SubItems[rfDictIndex];
+  int arrIndex = FindKeyPair(rfDictItem, "blkx", "array");
+  if (arrIndex < 0)
+    return S_FALSE;
+
+  const CXmlItem &arrItem = rfDictItem.SubItems[arrIndex];
+
+  int i;
+  for (i = 0; i < arrItem.SubItems.Size(); i++)
+  {
+    const CXmlItem &item = arrItem.SubItems[i];
+    if (!item.IsTagged("dict"))
+      continue;
+
+    CFile file;
+    file.StartPos = 0;
+
+    int destLen;
+    {
+      AString dataString;
+      AString name = GetStringFromKeyPair(item, "Name", "string");
+      if (name.IsEmpty())
+        name = GetStringFromKeyPair(item, "CFName", "string");
+      file.Name = name;
+      dataString = GetStringFromKeyPair(item, "Data", "data");
+     
+      destLen = Base64ToBin(NULL, dataString, dataString.Length());
+      file.Raw.SetCapacity(destLen);
+      Base64ToBin(file.Raw, dataString, dataString.Length());
+    }
+
+    if (destLen > 0xCC && Get32(file.Raw) == 0x6D697368)
+    {
+      PRF(printf("\n\n index = %d", _files.Size()));
+      const int kRecordSize = 40;
+      for (int offset = 0xCC; offset + kRecordSize <= destLen; offset += kRecordSize)
+      {
+        const Byte *p = (const Byte *)file.Raw + offset;
+        CBlock b;
+        b.Type = Get32(p);
+        if (b.Type == METHOD_END)
+          break;
+        if (b.Type == METHOD_DUMMY)
+          continue;
+
+        b.UnpPos   = Get64(p + 0x08) << 9;
+        b.UnpSize  = Get64(p + 0x10) << 9;
+        b.PackPos  = Get64(p + 0x18);
+        b.PackSize = Get64(p + 0x20);
+
+        file.Blocks.Add(b);
+
+        PRF(printf("\nType=%8x  m[1]=%8x  uPos=%8x  uSize=%7x  pPos=%8x  pSize=%7x",
+            b.Type, Get32(p + 4), (UInt32)b.UnpPos, (UInt32)b.UnpSize, (UInt32)b.PackPos, (UInt32)b.PackSize));
+      }
+    }
+    int itemIndex = _files.Add(file);
+    if (file.Blocks.Size() > 0)
+    {
+      // if (file.Name.Find("HFS") >= 0)
+        _fileIndices.Add(itemIndex);
+    }
+  }
+  
+  // PackPos for each new file is 0 in some DMG files. So we use additional StartPos
+
+  bool allStartAreZeros = true;
+  for (i = 0; i < _files.Size(); i++)
+  {
+    const CFile &file = _files[i];
+    if (!file.Blocks.IsEmpty() && file.Blocks[0].PackPos != 0)
+      allStartAreZeros = false;
+  }
+  UInt64 startPos = 0;
+  if (allStartAreZeros)
+  {
+    for (i = 0; i < _files.Size(); i++)
+    {
+      CFile &file = _files[i];
+      file.StartPos = startPos;
+      if (!file.Blocks.IsEmpty())
+        startPos += file.Blocks.Back().GetNextPackOffset();
+    }
+  }
+
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+    const UInt64 * /* maxCheckStartPosition */,
+    IArchiveOpenCallback * /* openArchiveCallback */)
+{
+  COM_TRY_BEGIN
+  {
+    Close();
+    if (Open2(stream) != S_OK)
+      return S_FALSE;
+    _inStream = stream;
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _inStream.Release();
+  _fileIndices.Clear();
+  _files.Clear();
+  _xml.Empty();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _fileIndices.Size()
+    #ifdef DMG_SHOW_RAW
+    + _files.Size() + 1;
+    #endif
+  ;
+  return S_OK;
+}
+
+#define RAW_PREFIX L"raw" WSTRING_PATH_SEPARATOR
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  
+  #ifdef DMG_SHOW_RAW
+  if ((int)index == _fileIndices.Size())
+  {
+    switch(propID)
+    {
+      case kpidPath:
+        prop = RAW_PREFIX L"a.xml";
+        break;
+      case kpidSize:
+      case kpidPackSize:
+        prop = (UInt64)_xml.Length();
+        break;
+    }
+  }
+  else if ((int)index > _fileIndices.Size())
+  {
+    int rawIndex = (int)index - (_fileIndices.Size() + 1);
+    switch(propID)
+    {
+      case kpidPath:
+      {
+        wchar_t s[32] = RAW_PREFIX;
+        ConvertUInt64ToString(rawIndex, s + MyStringLen(s));
+        prop = s;
+        break;
+      }
+      case kpidSize:
+      case kpidPackSize:
+        prop = (UInt64)_files[rawIndex].Raw.GetCapacity();
+        break;
+    }
+  }
+  else
+  #endif
+  {
+    int itemIndex = _fileIndices[index];
+    const CFile &item = _files[itemIndex];
+    switch(propID)
+    {
+      case kpidMethod:
+      {
+        CMethods m;
+        m.Update(item);
+        UString resString = m.GetString();
+        if (!resString.IsEmpty())
+          prop = resString;
+        break;
+      }
+      
+      // case kpidExtension: prop = L"hfs"; break;
+
+      case kpidPath:
+      {
+        // break;
+        UString name;
+        wchar_t s[32];
+        ConvertUInt64ToString(index, s);
+        name = s;
+        int num = 10;
+        int numDigits;
+        for (numDigits = 1; num < _fileIndices.Size(); numDigits++)
+          num *= 10;
+        while (name.Length() < numDigits)
+          name = L'0' + name;
+
+        AString subName;
+        int pos1 = item.Name.Find('(');
+        if (pos1 >= 0)
+        {
+          pos1++;
+          int pos2 = item.Name.Find(')', pos1);
+          if (pos2 >= 0)
+          {
+            subName = item.Name.Mid(pos1, pos2 - pos1);
+            pos1 = subName.Find(':');
+            if (pos1 >= 0)
+              subName = subName.Left(pos1);
+          }
+        }
+        subName.Trim();
+        if (!subName.IsEmpty())
+        {
+          if (subName == "Apple_HFS")
+            subName = "hfs";
+          else if (subName == "Apple_HFSX")
+            subName = "hfsx";
+          else if (subName == "Apple_Free")
+            subName = "free";
+          else if (subName == "DDM")
+            subName = "ddm";
+          UString name2;
+          ConvertUTF8ToUnicode(subName, name2);
+          name += L'.';
+          name += name2;
+        }
+        else
+        {
+          UString name2;
+          ConvertUTF8ToUnicode(item.Name, name2);
+          if (!name2.IsEmpty())
+            name += L" - ";
+          name += name2;
+        }
+        prop = name;
+        break;
+      }
+      case kpidComment:
+      {
+        UString name;
+        ConvertUTF8ToUnicode(item.Name, name);
+        prop = name;
+        break;
+      }
+
+      case kpidSize:  prop = item.GetUnpackSize(); break;
+      case kpidPackSize:  prop = item.GetPackSize(); break;
+    }
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+class CAdcDecoder:
+  public ICompressCoder,
+  public CMyUnknownImp
+{
+  CLzOutWindow m_OutWindowStream;
+  CInBuffer m_InStream;
+
+  void ReleaseStreams()
+  {
+    m_OutWindowStream.ReleaseStream();
+    m_InStream.ReleaseStream();
+  }
+
+  class CCoderReleaser
+  {
+    CAdcDecoder *m_Coder;
+  public:
+    bool NeedFlush;
+    CCoderReleaser(CAdcDecoder *coder): m_Coder(coder), NeedFlush(true) {}
+    ~CCoderReleaser()
+    {
+      if (NeedFlush)
+        m_Coder->m_OutWindowStream.Flush();
+      m_Coder->ReleaseStreams();
+    }
+  };
+  friend class CCoderReleaser;
+
+public:
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(CodeReal)(ISequentialInStream *inStream,
+      ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
+      ICompressProgressInfo *progress);
+
+  STDMETHOD(Code)(ISequentialInStream *inStream,
+      ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
+      ICompressProgressInfo *progress);
+};
+
+STDMETHODIMP CAdcDecoder::CodeReal(ISequentialInStream *inStream,
+    ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
+    ICompressProgressInfo *progress)
+{
+  if (!m_OutWindowStream.Create(1 << 18))
+    return E_OUTOFMEMORY;
+  if (!m_InStream.Create(1 << 18))
+    return E_OUTOFMEMORY;
+
+  m_OutWindowStream.SetStream(outStream);
+  m_OutWindowStream.Init(false);
+  m_InStream.SetStream(inStream);
+  m_InStream.Init();
+  
+  CCoderReleaser coderReleaser(this);
+
+  const UInt32 kStep = (1 << 20);
+  UInt64 nextLimit = kStep;
+
+  UInt64 pos = 0;
+  while (pos < *outSize)
+  {
+    if (pos > nextLimit && progress)
+    {
+      UInt64 packSize = m_InStream.GetProcessedSize();
+      RINOK(progress->SetRatioInfo(&packSize, &pos));
+      nextLimit += kStep;
+    }
+    Byte b;
+    if (!m_InStream.ReadByte(b))
+      return S_FALSE;
+    UInt64 rem = *outSize - pos;
+    if (b & 0x80)
+    {
+      unsigned num = (b & 0x7F) + 1;
+      if (num > rem)
+        return S_FALSE;
+      for (unsigned i = 0; i < num; i++)
+      {
+        if (!m_InStream.ReadByte(b))
+          return S_FALSE;
+        m_OutWindowStream.PutByte(b);
+      }
+      pos += num;
+      continue;
+    }
+    Byte b1;
+    if (!m_InStream.ReadByte(b1))
+      return S_FALSE;
+
+    UInt32 len, distance;
+
+    if (b & 0x40)
+    {
+      len = ((UInt32)b & 0x3F) + 4;
+      Byte b2;
+      if (!m_InStream.ReadByte(b2))
+        return S_FALSE;
+      distance = ((UInt32)b1 << 8) + b2;
+    }
+    else
+    {
+      b &= 0x3F;
+      len = ((UInt32)b >> 2) + 3;
+      distance = (((UInt32)b & 3) << 8) + b1;
+    }
+
+    if (distance >= pos || len > rem)
+      return S_FALSE;
+    m_OutWindowStream.CopyBlock(distance, len);
+    pos += len;
+  }
+  if (*inSize != m_InStream.GetProcessedSize())
+    return S_FALSE;
+  coderReleaser.NeedFlush = false;
+  return m_OutWindowStream.Flush();
+}
+
+STDMETHODIMP CAdcDecoder::Code(ISequentialInStream *inStream,
+    ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
+    ICompressProgressInfo *progress)
+{
+  try { return CodeReal(inStream, outStream, inSize, outSize, progress);}
+  catch(const CInBufferException &e) { return e.ErrorCode; }
+  catch(const CLzOutWindowException &e) { return e.ErrorCode; }
+  catch(...) { return S_FALSE; }
+}
+
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _files.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt64 totalSize = 0;
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+  {
+    int index = (int)(allFilesMode ? i : indices[i]);
+    #ifdef DMG_SHOW_RAW
+    if (index == _fileIndices.Size())
+      totalSize += _xml.Length();
+    else if (index > _fileIndices.Size())
+      totalSize += _files[index - (_fileIndices.Size() + 1)].Raw.GetCapacity();
+    else
+    #endif
+      totalSize += _files[_fileIndices[index]].GetUnpackSize();
+  }
+  extractCallback->SetTotal(totalSize);
+
+  UInt64 currentPackTotal = 0;
+  UInt64 currentUnpTotal = 0;
+  UInt64 currentPackSize = 0;
+  UInt64 currentUnpSize = 0;
+
+  const UInt32 kZeroBufSize = (1 << 14);
+  CByteBuffer zeroBuf;
+  zeroBuf.SetCapacity(kZeroBufSize);
+  memset(zeroBuf, 0, kZeroBufSize);
+  
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  NCompress::NBZip2::CDecoder *bzip2CoderSpec = new NCompress::NBZip2::CDecoder();
+  CMyComPtr<ICompressCoder> bzip2Coder = bzip2CoderSpec;
+
+  NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder();
+  CMyComPtr<ICompressCoder> zlibCoder = zlibCoderSpec;
+
+  CAdcDecoder *adcCoderSpec = new CAdcDecoder();
+  CMyComPtr<ICompressCoder> adcCoder = adcCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);
+  streamSpec->SetStream(_inStream);
+
+  for (i = 0; i < numItems; i++, currentPackTotal += currentPackSize, currentUnpTotal += currentUnpSize)
+  {
+    lps->InSize = currentPackTotal;
+    lps->OutSize = currentUnpTotal;
+    currentPackSize = 0;
+    currentUnpSize = 0;
+    RINOK(lps->SetCur());
+    CMyComPtr<ISequentialOutStream> realOutStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    Int32 index = allFilesMode ? i : indices[i];
+    // const CItemEx &item = _files[index];
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+    
+    
+    if (!testMode && !realOutStream)
+      continue;
+    RINOK(extractCallback->PrepareOperation(askMode));
+
+    CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;
+    CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+    outStreamSpec->SetStream(realOutStream);
+    
+    realOutStream.Release();
+
+    Int32 opRes = NExtract::NOperationResult::kOK;
+    #ifdef DMG_SHOW_RAW
+    if (index > _fileIndices.Size())
+    {
+      const CByteBuffer &buf = _files[index - (_fileIndices.Size() + 1)].Raw;
+      outStreamSpec->Init(buf.GetCapacity());
+      RINOK(WriteStream(outStream, buf, buf.GetCapacity()));
+      currentPackSize = currentUnpSize = buf.GetCapacity();
+    }
+    else if (index == _fileIndices.Size())
+    {
+      outStreamSpec->Init(_xml.Length());
+      RINOK(WriteStream(outStream, (const char *)_xml, _xml.Length()));
+      currentPackSize = currentUnpSize = _xml.Length();
+    }
+    else
+    #endif
+    {
+      const CFile &item = _files[_fileIndices[index]];
+      currentPackSize = item.GetPackSize();
+      currentUnpSize = item.GetUnpackSize();
+
+      UInt64 unpPos = 0;
+      UInt64 packPos = 0;
+      {
+        for (int j = 0; j < item.Blocks.Size(); j++)
+        {
+          lps->InSize = currentPackTotal + packPos;
+          lps->OutSize = currentUnpTotal + unpPos;
+          RINOK(lps->SetCur());
+
+          const CBlock &block = item.Blocks[j];
+
+          packPos += block.PackSize;
+          if (block.UnpPos != unpPos)
+          {
+            opRes = NExtract::NOperationResult::kDataError;
+            break;
+          }
+
+          RINOK(_inStream->Seek(item.StartPos + block.PackPos, STREAM_SEEK_SET, NULL));
+          streamSpec->Init(block.PackSize);
+          // UInt64 startSize = outStreamSpec->GetSize();
+          bool realMethod = true;
+          outStreamSpec->Init(block.UnpSize);
+          HRESULT res = S_OK;
+
+          switch(block.Type)
+          {
+            case METHOD_ZERO_0:
+            case METHOD_ZERO_2:
+              realMethod = false;
+              if (block.PackSize != 0)
+                opRes = NExtract::NOperationResult::kUnSupportedMethod;
+              break;
+
+            case METHOD_COPY:
+              if (block.UnpSize != block.PackSize)
+              {
+                opRes = NExtract::NOperationResult::kUnSupportedMethod;
+                break;
+              }
+              res = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
+              break;
+            
+            case METHOD_ADC:
+            {
+              res = adcCoder->Code(inStream, outStream, &block.PackSize, &block.UnpSize, progress);
+              break;
+            }
+            
+            case METHOD_ZLIB:
+            {
+              res = zlibCoder->Code(inStream, outStream, NULL, NULL, progress);
+              break;
+            }
+
+            case METHOD_BZIP2:
+            {
+              res = bzip2Coder->Code(inStream, outStream, NULL, NULL, progress);
+              if (res == S_OK)
+                if (streamSpec->GetSize() != block.PackSize)
+                  opRes = NExtract::NOperationResult::kDataError;
+              break;
+            }
+            
+            default:
+              opRes = NExtract::NOperationResult::kUnSupportedMethod;
+              break;
+          }
+          if (res != S_OK)
+          {
+            if (res != S_FALSE)
+              return res;
+            if (opRes == NExtract::NOperationResult::kOK)
+              opRes = NExtract::NOperationResult::kDataError;
+          }
+          unpPos += block.UnpSize;
+          if (!outStreamSpec->IsFinishedOK())
+          {
+            if (realMethod && opRes == NExtract::NOperationResult::kOK)
+              opRes = NExtract::NOperationResult::kDataError;
+
+            while (outStreamSpec->GetRem() != 0)
+            {
+              UInt64 rem = outStreamSpec->GetRem();
+              UInt32 size = (UInt32)MyMin(rem, (UInt64)kZeroBufSize);
+              RINOK(WriteStream(outStream, zeroBuf, size));
+            }
+          }
+        }
+      }
+    }
+    outStream.Release();
+    RINOK(extractCallback->SetOperationResult(opRes));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"Dmg", L"dmg", 0, 0xE4, { 0 }, 0, false, CreateArc, 0 };
+
+REGISTER_ARC(Dmg)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/ElfHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/ElfHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/ElfHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/ElfHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,534 @@
+// ElfHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/Buffer.h"
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+
+#include "Windows/PropVariantUtils.h"
+
+#include "../Common/LimitedStreams.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+
+static UInt16 Get16(const Byte *p, int be) { if (be) return GetBe16(p); return GetUi16(p); }
+static UInt32 Get32(const Byte *p, int be) { if (be) return GetBe32(p); return GetUi32(p); }
+static UInt64 Get64(const Byte *p, int be) { if (be) return GetBe64(p); return GetUi64(p); }
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NElf {
+
+#define ELF_CLASS_32 1
+#define ELF_CLASS_64 2
+
+#define ELF_DATA_2LSB 1
+#define ELF_DATA_2MSB 2
+
+#define NUM_SCAN_SECTIONS_MAX (1 << 6)
+
+struct CHeader
+{
+  bool Mode64;
+  bool Be;
+  Byte Os;
+  Byte AbiVer;
+
+  UInt16 Type;
+  UInt16 Machine;
+  // UInt32 Version;
+
+  // UInt64 EntryVa;
+  UInt64 ProgOffset;
+  UInt64 SectOffset;
+  UInt32 Flags;
+  UInt16 ElfHeaderSize;
+  UInt16 SegmentEntrySize;
+  UInt16 NumSegments;
+  UInt16 SectEntrySize;
+  UInt16 NumSections;
+  // UInt16 SectNameStringTableIndex;
+
+  bool Parse(const Byte *buf);
+
+  bool CheckSegmentEntrySize() const
+  {
+    return (Mode64 && SegmentEntrySize == 0x38) || (!Mode64 && SegmentEntrySize == 0x20);
+  };
+
+  UInt64 GetHeadersSize() const
+    { return ElfHeaderSize +
+      (UInt64)SegmentEntrySize * NumSegments +
+      (UInt64)SectEntrySize * NumSections; }
+    
+};
+
+bool CHeader::Parse(const Byte *p)
+{
+  switch(p[4])
+  {
+    case ELF_CLASS_32: Mode64 = false; break;
+    case ELF_CLASS_64: Mode64 = true; break;
+    default: return false;
+  }
+  bool be;
+  switch(p[5])
+  {
+    case ELF_DATA_2LSB: be = false; break;
+    case ELF_DATA_2MSB: be = true; break;
+    default: return false;
+  }
+  Be = be;
+  if (p[6] != 1) // Version
+    return false;
+  Os = p[7];
+  AbiVer = p[8];
+  for (int i = 9; i < 16; i++)
+    if (p[i] != 0)
+      return false;
+
+  Type = Get16(p + 0x10, be);
+  Machine = Get16(p + 0x12, be);
+  if (Get32(p + 0x14, be) != 1) // Version
+    return false;
+
+  if (Mode64)
+  {
+    // EntryVa = Get64(p + 0x18, be);
+    ProgOffset = Get64(p + 0x20, be);
+    SectOffset = Get64(p + 0x28, be);
+    p += 0x30;
+  }
+  else
+  {
+    // EntryVa = Get32(p + 0x18, be);
+    ProgOffset = Get32(p + 0x1C, be);
+    SectOffset = Get32(p + 0x20, be);
+    p += 0x24;
+  }
+
+  Flags = Get32(p + 0, be);
+  ElfHeaderSize = Get16(p + 4, be);
+  SegmentEntrySize = Get16(p + 6, be);
+  NumSegments = Get16(p + 8, be);
+  SectEntrySize = Get16(p + 10, be);
+  NumSections = Get16(p + 12, be);
+  // SectNameStringTableIndex = Get16(p + 14, be);
+  return CheckSegmentEntrySize();
+}
+
+struct CSegment
+{
+  UInt32 Type;
+  UInt32 Flags;
+  UInt64 Offset;
+  UInt64 Va;
+  // UInt64 Pa;
+  UInt64 PSize;
+  UInt64 VSize;
+  // UInt64 Align;
+
+  void UpdateTotalSize(UInt64 &totalSize)
+  {
+    UInt64 t = Offset + PSize;
+    if (t > totalSize)
+      totalSize = t;
+  }
+  void Parse(const Byte *p, bool mode64, bool be);
+};
+
+void CSegment::Parse(const Byte *p, bool mode64, bool be)
+{
+  Type = Get32(p, be);
+  if (mode64)
+  {
+    Flags = Get32(p + 4, be);
+    Offset = Get64(p + 8, be);
+    Va = Get64(p + 0x10, be);
+    // Pa = Get64(p + 0x18, be);
+    PSize = Get64(p + 0x20, be);
+    VSize = Get64(p + 0x28, be);
+    // Align = Get64(p + 0x30, be);
+  }
+  else
+  {
+    Offset = Get32(p + 4, be);
+    Va = Get32(p + 8, be);
+    // Pa = Get32(p + 12, be);
+    PSize = Get32(p + 16, be);
+    VSize = Get32(p + 20, be);
+    Flags = Get32(p + 24, be);
+    // Align = Get32(p + 28, be);
+  }
+}
+
+static const CUInt32PCharPair g_MachinePairs[] =
+{
+  { 0, "None" },
+  { 1, "AT&T WE 32100" },
+  { 2, "SPARC" },
+  { 3, "Intel 386" },
+  { 4, "Motorola 68000" },
+  { 5, "Motorola 88000" },
+  { 6, "Intel 486" },
+  { 7, "Intel i860" },
+  { 8, "MIPS" },
+  { 9, "IBM S/370" },
+  { 10, "MIPS RS3000 LE" },
+  { 11, "RS6000" },
+
+  { 15, "PA-RISC" },
+  { 16, "nCUBE" },
+  { 17, "Fujitsu VPP500" },
+  { 18, "SPARC 32+" },
+  { 19, "Intel i960" },
+  { 20, "PowerPC" },
+  { 21, "PowerPC 64-bit" },
+  { 22, "IBM S/390" },
+
+  { 36, "NEX v800" },
+  { 37, "Fujitsu FR20" },
+  { 38, "TRW RH-32" },
+  { 39, "Motorola RCE" },
+  { 40, "ARM" },
+  { 41, "Alpha" },
+  { 42, "Hitachi SH" },
+  { 43, "SPARC-V9" },
+  { 44, "Siemens Tricore" },
+  { 45, "ARC" },
+  { 46, "H8/300" },
+  { 47, "H8/300H" },
+  { 48, "H8S" },
+  { 49, "H8/500" },
+  { 50, "IA-64" },
+  { 51, "Stanford MIPS-X" },
+  { 52, "Motorola ColdFire" },
+  { 53, "M68HC12" },
+  { 54, "Fujitsu MMA" },
+  { 55, "Siemens PCP" },
+  { 56, "Sony nCPU" },
+  { 57, "Denso NDR1" },
+  { 58, "Motorola StarCore" },
+  { 59, "Toyota ME16" },
+  { 60, "ST100" },
+  { 61, "Advanced Logic TinyJ" },
+  { 62, "AMD64" },
+  { 63, "Sony DSP" },
+
+  { 66, "Siemens FX66" },
+  { 67, "ST9+" },
+  { 68, "ST7" },
+  { 69, "MC68HC16" },
+  { 70, "MC68HC11" },
+  { 71, "MC68HC08" },
+  { 72, "MC68HC05" },
+  { 73, "Silicon Graphics SVx" },
+  { 74, "ST19" },
+  { 75, "Digital VAX" },
+  { 76, "Axis CRIS" },
+  { 77, "Infineon JAVELIN" },
+  { 78, "Element 14 FirePath" },
+  { 79, "LSI ZSP" },
+  { 80, "MMIX" },
+  { 81, "HUANY" },
+  { 82, "SiTera Prism" },
+  { 83, "Atmel AVR" },
+  { 84, "Fujitsu FR30" },
+  { 85, "Mitsubishi D10V" },
+  { 86, "Mitsubishi D30V" },
+  { 87, "NEC v850" },
+  { 88, "Mitsubishi M32R" },
+  { 89, "Matsushita MN10300" },
+  { 90, "Matsushita MN10200" },
+  { 91, "picoJava" },
+  { 92, "OpenRISC" },
+  { 93, "ARC Tangent-A5" },
+  { 94, "Tensilica Xtensa" },
+  { 0x9026, "Alpha" }
+};
+
+static const CUInt32PCharPair g_AbiOS[] =
+{
+  { 0, "None" },
+  { 1, "HP-UX" },
+  { 2, "NetBSD" },
+  { 3, "Linux" },
+
+  { 6, "Solaris" },
+  { 7, "AIX" },
+  { 8, "IRIX" },
+  { 9, "FreeBSD" },
+  { 10, "TRU64" },
+  { 11, "Novell Modesto" },
+  { 12, "OpenBSD" },
+  { 13, "OpenVMS" },
+  { 14, "HP NSK" },
+  { 15, "AROS" },
+  { 97, "ARM" },
+  { 255, "Standalone" }
+};
+
+static const CUInt32PCharPair g_SegmentFlags[] =
+{
+  { 0, "Execute" },
+  { 1, "Write" },
+  { 2, "Read" }
+};
+
+static const char *g_Types[] =
+{
+  "None",
+  "Relocatable file",
+  "Executable file",
+  "Shared object file",
+  "Core file"
+};
+
+static const char *g_SegnmentTypes[] =
+{
+  "Unused",
+  "Loadable segment",
+  "Dynamic linking tables",
+  "Program interpreter path name",
+  "Note section",
+  "SHLIB",
+  "Program header table",
+  "TLS"
+};
+
+class CHandler:
+  public IInArchive,
+  public CMyUnknownImp
+{
+  CMyComPtr<IInStream> _inStream;
+  CObjectVector<CSegment> _sections;
+  UInt32 _peOffset;
+  CHeader _header;
+  UInt64 _totalSize;
+  HRESULT Open2(IInStream *stream);
+  bool Parse(const Byte *buf, UInt32 size);
+public:
+  MY_UNKNOWN_IMP1(IInArchive)
+  INTERFACE_IInArchive(;)
+};
+
+#define ELF_PT_PHDR 6
+
+bool CHandler::Parse(const Byte *buf, UInt32 size)
+{
+  if (size < 64)
+    return false;
+  if (!_header.Parse(buf))
+    return false;
+  if (_header.ProgOffset > size ||
+      _header.ProgOffset + (UInt64)_header.SegmentEntrySize * _header.NumSegments > size ||
+      _header.NumSegments > NUM_SCAN_SECTIONS_MAX)
+    return false;
+  const Byte *p = buf + _header.ProgOffset;
+  _totalSize = _header.ProgOffset;
+  
+  for (int i = 0; i < _header.NumSegments; i++, p += _header.SegmentEntrySize)
+  {
+    CSegment sect;
+    sect.Parse(p, _header.Mode64, _header.Be);
+    sect.UpdateTotalSize(_totalSize);
+    if (sect.Type != ELF_PT_PHDR)
+      _sections.Add(sect);
+  }
+  UInt64 total2 = _header.SectOffset + (UInt64)_header.SectEntrySize * _header.NumSections;
+  if (total2 > _totalSize)
+    _totalSize = total2;
+  return true;
+}
+
+STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidCpu, VT_BSTR},
+  { NULL, kpidBit64, VT_BOOL},
+  { NULL, kpidBigEndian, VT_BOOL},
+  { NULL, kpidHostOS, VT_BSTR},
+  { NULL, kpidCharacts, VT_BSTR},
+  { NULL, kpidPhySize, VT_UI8},
+  { NULL, kpidHeadersSize, VT_UI8}
+ };
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidType, VT_BSTR},
+  { NULL, kpidCharacts, VT_BSTR},
+  { NULL, kpidOffset, VT_UI8},
+  { NULL, kpidVa, VT_UI8}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidPhySize:  prop = _totalSize; break;
+    case kpidHeadersSize:  prop = _header.GetHeadersSize(); break;
+    case kpidBit64:  if (_header.Mode64) prop = _header.Mode64; break;
+    case kpidBigEndian:  if (_header.Be) prop = _header.Be; break;
+    case kpidCpu:  PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); break;
+    case kpidHostOS:  PAIR_TO_PROP(g_AbiOS, _header.Os, prop); break;
+    case kpidCharacts:  TYPE_TO_PROP(g_Types, _header.Type, prop); break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NCOM::CPropVariant prop;
+  const CSegment &item = _sections[index];
+  switch(propID)
+  {
+    case kpidPath:
+    {
+      wchar_t sz[32];
+      ConvertUInt64ToString(index, sz);
+      prop = sz;
+      break;
+    }
+    case kpidSize:  prop = (UInt64)item.VSize; break;
+    case kpidPackSize:  prop = (UInt64)item.PSize; break;
+    case kpidOffset:  prop = item.Offset; break;
+    case kpidVa:  prop = item.Va; break;
+    case kpidType:  TYPE_TO_PROP(g_SegnmentTypes, item.Type, prop); break;
+    case kpidCharacts:  FLAGS_TO_PROP(g_SegmentFlags, item.Flags, prop); break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+HRESULT CHandler::Open2(IInStream *stream)
+{
+  const UInt32 kBufSize = 1 << 18;
+  const UInt32 kSigSize = 4;
+
+  CByteBuffer buffer;
+  buffer.SetCapacity(kBufSize);
+  Byte *buf = buffer;
+
+  size_t processed = kSigSize;
+  RINOK(ReadStream_FALSE(stream, buf, processed));
+  if (buf[0] != 0x7F || buf[1] != 'E' || buf[2] != 'L' || buf[3] != 'F')
+    return S_FALSE;
+  processed = kBufSize - kSigSize;
+  RINOK(ReadStream(stream, buf + kSigSize, &processed));
+  processed += kSigSize;
+  if (!Parse(buf, (UInt32)processed))
+    return S_FALSE;
+  UInt64 fileSize;
+  RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));
+  return (fileSize == _totalSize) ? S_OK : S_FALSE;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *inStream,
+    const UInt64 * /* maxCheckStartPosition */,
+    IArchiveOpenCallback * /* openArchiveCallback */)
+{
+  COM_TRY_BEGIN
+  Close();
+  RINOK(Open2(inStream));
+  _inStream = inStream;
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _inStream.Release();
+  _sections.Clear();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _sections.Size();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _sections.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt64 totalSize = 0;
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+    totalSize += _sections[allFilesMode ? i : indices[i]].PSize;
+  extractCallback->SetTotal(totalSize);
+
+  UInt64 currentTotalSize = 0;
+  UInt64 currentItemSize;
+  
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);
+  streamSpec->SetStream(_inStream);
+
+  for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
+  {
+    lps->InSize = lps->OutSize = currentTotalSize;
+    RINOK(lps->SetCur());
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    UInt32 index = allFilesMode ? i : indices[i];
+    const CSegment &item = _sections[index];
+    currentItemSize = item.PSize;
+    
+    CMyComPtr<ISequentialOutStream> outStream;
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));
+    if (!testMode && !outStream)
+      continue;
+      
+    RINOK(extractCallback->PrepareOperation(askMode));
+    RINOK(_inStream->Seek(item.Offset, STREAM_SEEK_SET, NULL));
+    streamSpec->Init(currentItemSize);
+    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
+    outStream.Release();
+    RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ?
+        NExtract::NOperationResult::kOK:
+        NExtract::NOperationResult::kDataError));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"ELF", L"", 0, 0xDE, { 0 }, 0, false, CreateArc, 0 };
+
+REGISTER_ARC(Elf)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/FatHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/FatHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/FatHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/FatHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,996 @@
+// FatHandler.cpp
+
+#include "StdAfx.h"
+
+// #include <stdio.h>
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/Buffer.h"
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+#include "Common/MyCom.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../Common/LimitedStreams.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+
+#include "Common/DummyOutStream.h"
+
+#define Get16(p) GetUi16(p)
+#define Get32(p) GetUi32(p)
+
+#define PRF(x) /* x */
+
+namespace NArchive {
+namespace NFat {
+
+static const UInt32 kFatItemUsedByDirMask = (UInt32)1 << 31;
+
+struct CHeader
+{
+  UInt32 NumSectors;
+  UInt16 NumReservedSectors;
+  Byte NumFats;
+  UInt32 NumFatSectors;
+  UInt32 RootDirSector;
+  UInt32 NumRootDirSectors;
+  UInt32 DataSector;
+
+  UInt32 FatSize;
+  UInt32 BadCluster;
+
+  Byte NumFatBits;
+  Byte SectorSizeLog;
+  Byte SectorsPerClusterLog;
+  Byte ClusterSizeLog;
+  
+  UInt16 SectorsPerTrack;
+  UInt16 NumHeads;
+  UInt32 NumHiddenSectors;
+
+  bool VolFieldsDefined;
+  
+  UInt32 VolId;
+  // Byte VolName[11];
+  // Byte FileSys[8];
+
+  // Byte OemName[5];
+  Byte MediaType;
+
+  // 32-bit FAT
+  UInt16 Flags;
+  UInt16 FsInfoSector;
+  UInt32 RootCluster;
+
+  bool IsFat32() const { return NumFatBits == 32; }
+  UInt64 GetPhySize() const { return (UInt64)NumSectors << SectorSizeLog; }
+  UInt32 SectorSize() const { return (UInt32)1 << SectorSizeLog; }
+  UInt32 ClusterSize() const { return (UInt32)1 << ClusterSizeLog; }
+  UInt32 ClusterToSector(UInt32 c) const { return DataSector + ((c - 2) << SectorsPerClusterLog); }
+  UInt32 IsEoc(UInt32 c) const { return c > BadCluster; }
+  UInt32 IsEocAndUnused(UInt32 c) const { return c > BadCluster && (c & kFatItemUsedByDirMask) == 0; }
+  UInt32 IsValidCluster(UInt32 c) const { return c >= 2 && c < FatSize; }
+  UInt32 SizeToSectors(UInt32 size) const { return (size + SectorSize() - 1) >> SectorSizeLog; }
+  UInt32 CalcFatSizeInSectors() const { return SizeToSectors((FatSize * (NumFatBits / 4) + 1) / 2); }
+
+  UInt32 GetFatSector() const
+  {
+    UInt32 index = (IsFat32() && (Flags & 0x80) != 0) ? (Flags & 0xF) : 0;
+    if (index > NumFats)
+      index = 0;
+    return NumReservedSectors + index * NumFatSectors;
+  }
+
+  UInt64 GetFilePackSize(UInt32 unpackSize) const
+  {
+    UInt64 mask = ClusterSize() - 1;
+    return (unpackSize + mask) & ~mask;
+  }
+
+  UInt32 GetNumClusters(UInt32 size) const
+    { return (UInt32)(((UInt64)size + ClusterSize() - 1) >> ClusterSizeLog); }
+
+  bool Parse(const Byte *p);
+};
+
+static int GetLog(UInt32 num)
+{
+  for (int i = 0; i < 31; i++)
+    if (((UInt32)1 << i) == num)
+      return i;
+  return -1;
+}
+
+bool CHeader::Parse(const Byte *p)
+{
+  if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA)
+    return false;
+
+  int codeOffset = 0;
+  switch (p[0])
+  {
+    case 0xE9: codeOffset = 3 + (Int16)Get16(p + 1); break;
+    case 0xEB: if (p[2] != 0x90) return false; codeOffset = 2 + (signed char)p[1]; break;
+    default: return false;
+  }
+  {
+    int s = GetLog(Get16(p + 11));
+    if (s < 9 || s > 12)
+      return false;
+    SectorSizeLog = (Byte)s;
+    s = GetLog(p[13]);
+    if (s < 0)
+      return false;
+    SectorsPerClusterLog = (Byte)s;
+    ClusterSizeLog = SectorSizeLog + SectorsPerClusterLog;
+  }
+
+  NumReservedSectors = Get16(p + 14);
+  if (NumReservedSectors == 0)
+    return false;
+
+  NumFats = p[16];
+  if (NumFats < 1 || NumFats > 4)
+    return false;
+
+  UInt16 numRootDirEntries = Get16(p + 17);
+  if (numRootDirEntries == 0)
+  {
+    if (codeOffset < 90)
+      return false;
+    NumFatBits = 32;
+    NumRootDirSectors = 0;
+  }
+  else
+  {
+    if (codeOffset < 62)
+      return false;
+    NumFatBits = 0;
+    UInt32 mask = (1 << (SectorSizeLog - 5)) - 1;
+    if ((numRootDirEntries & mask) != 0)
+      return false;
+    NumRootDirSectors = (numRootDirEntries + mask) >> (SectorSizeLog - 5);
+  }
+
+  NumSectors = Get16(p + 19);
+  if (NumSectors == 0)
+    NumSectors = Get32(p + 32);
+  else if (IsFat32())
+    return false;
+
+  MediaType = p[21];
+  NumFatSectors = Get16(p + 22);
+  SectorsPerTrack = Get16(p + 24);
+  NumHeads = Get16(p + 26);
+  NumHiddenSectors = Get32(p + 28);
+
+  // memcpy(OemName, p + 3, 5);
+
+  p += 36;
+  if (IsFat32())
+  {
+    if (NumFatSectors != 0)
+      return false;
+    NumFatSectors = Get32(p);
+    if (NumFatSectors >= (1 << 24))
+      return false;
+
+    Flags = Get16(p + 4);
+    if (Get16(p + 6) != 0)
+      return false;
+    RootCluster = Get32(p + 8);
+    FsInfoSector = Get16(p + 12);
+    for (int i = 16; i < 28; i++)
+      if (p[i] != 0)
+        return false;
+    p += 28;
+  }
+
+  // DriveNumber = p[0];
+  VolFieldsDefined = (p[2] == 0x29); // ExtendedBootSig
+  VolId = Get32(p + 3);
+  // memcpy(VolName, p + 7, 11);
+  // memcpy(FileSys, p + 18, 8);
+
+  if (NumFatSectors == 0)
+    return false;
+  RootDirSector = NumReservedSectors + NumFatSectors * NumFats;
+  DataSector = RootDirSector + NumRootDirSectors;
+  if (NumSectors < DataSector)
+    return false;
+  UInt32 numDataSectors = NumSectors - DataSector;
+  UInt32 numClusters = numDataSectors >> SectorsPerClusterLog;
+  
+  BadCluster = 0x0FFFFFF7;
+  if (numClusters < 0xFFF5)
+  {
+    if (NumFatBits == 32)
+      return false;
+    NumFatBits = (numClusters < 0xFF5) ? 12: 16;
+    BadCluster &= ((1 << NumFatBits) - 1);
+  }
+  else if (NumFatBits != 32)
+    return false;
+
+  FatSize = numClusters + 2;
+  if (FatSize > BadCluster || CalcFatSizeInSectors() > NumFatSectors)
+    return false;
+  return true;
+}
+
+struct CItem
+{
+  UString UName;
+  char DosName[11];
+  Byte CTime2;
+  UInt32 CTime;
+  UInt32 MTime;
+  UInt16 ADate;
+  Byte Attrib;
+  Byte Flags;
+  UInt32 Size;
+  UInt32 Cluster;
+  Int32 Parent;
+
+  // NT uses Flags to store Low Case status
+  bool NameIsLow() const { return (Flags & 0x8) != 0; }
+  bool ExtIsLow() const { return (Flags & 0x10) != 0; }
+  bool IsDir() const { return (Attrib & 0x10) != 0; }
+  UString GetShortName() const;
+  UString GetName() const;
+  UString GetVolName() const;
+};
+
+static int CopyAndTrim(char *dest, const char *src, int size, bool toLower)
+{
+  int i;
+  memcpy(dest, src, size);
+  if (toLower)
+    for (i = 0; i < size; i++)
+    {
+      char c = dest[i];
+      if (c >= 'A' && c <= 'Z')
+        dest[i] = c + 0x20;
+    }
+  for (i = size - 1; i >= 0 && dest[i] == ' '; i--);
+  return i + 1;
+}
+
+static UString FatStringToUnicode(const char *s)
+{
+  return MultiByteToUnicodeString(s, CP_OEMCP);
+}
+
+UString CItem::GetShortName() const
+{
+  char s[16];
+  int i = CopyAndTrim(s, DosName, 8, NameIsLow());
+  s[i++] = '.';
+  int j = CopyAndTrim(s + i, DosName + 8, 3, ExtIsLow());
+  if (j == 0)
+    j--;
+  s[i + j] = 0;
+  return FatStringToUnicode(s);
+}
+
+UString CItem::GetName() const
+{
+  if (!UName.IsEmpty())
+    return UName;
+  return GetShortName();
+}
+
+UString CItem::GetVolName() const
+{
+  if (!UName.IsEmpty())
+    return UName;
+  char s[12];
+  int i = CopyAndTrim(s, DosName, 11, false);
+  s[i] = 0;
+  return FatStringToUnicode(s);
+}
+
+struct CDatabase
+{
+  CHeader Header;
+  CObjectVector<CItem> Items;
+  UInt32 *Fat;
+  CMyComPtr<IInStream> InStream;
+  IArchiveOpenCallback *OpenCallback;
+
+  UInt32 NumFreeClusters;
+  bool VolItemDefined;
+  CItem VolItem;
+  UInt32 NumDirClusters;
+  CByteBuffer ByteBuf;
+  UInt64 NumCurUsedBytes;
+
+  CDatabase(): Fat(0) {}
+  ~CDatabase() { ClearAndClose(); }
+
+  void Clear();
+  void ClearAndClose();
+  HRESULT OpenProgressFat(bool changeTotal = true);
+  HRESULT OpenProgress();
+
+  UString GetItemPath(Int32 index) const;
+  HRESULT Open();
+  HRESULT ReadDir(Int32 parent, UInt32 cluster, int level);
+
+  UInt64 GetHeadersSize() const
+  {
+    return (UInt64)(Header.DataSector + (NumDirClusters << Header.SectorsPerClusterLog)) << Header.SectorSizeLog;
+  }
+  HRESULT SeekToSector(UInt32 sector);
+  HRESULT SeekToCluster(UInt32 cluster) { return SeekToSector(Header.ClusterToSector(cluster)); }
+};
+
+HRESULT CDatabase::SeekToSector(UInt32 sector)
+{
+  return InStream->Seek((UInt64)sector << Header.SectorSizeLog, STREAM_SEEK_SET, NULL);
+}
+
+void CDatabase::Clear()
+{
+  VolItemDefined = false;
+  NumDirClusters = 0;
+  NumCurUsedBytes = 0;
+
+  Items.Clear();
+  delete []Fat;
+  Fat = 0;
+}
+
+void CDatabase::ClearAndClose()
+{
+  Clear();
+  InStream.Release();
+}
+
+HRESULT CDatabase::OpenProgressFat(bool changeTotal)
+{
+  if (!OpenCallback)
+    return S_OK;
+  if (changeTotal)
+  {
+    UInt64 numTotalBytes = (Header.CalcFatSizeInSectors() << Header.SectorSizeLog) +
+        ((UInt64)(Header.FatSize - NumFreeClusters) << Header.ClusterSizeLog);
+    RINOK(OpenCallback->SetTotal(NULL, &numTotalBytes));
+  }
+  return OpenCallback->SetCompleted(NULL, &NumCurUsedBytes);
+}
+
+HRESULT CDatabase::OpenProgress()
+{
+  if (!OpenCallback)
+    return S_OK;
+  UInt64 numItems = Items.Size();
+  return OpenCallback->SetCompleted(&numItems, &NumCurUsedBytes);
+}
+
+UString CDatabase::GetItemPath(Int32 index) const
+{
+  const CItem *item = &Items[index];
+  UString name = item->GetName();
+  for (;;)
+  {
+    index = item->Parent;
+    if (index < 0)
+      return name;
+    item = &Items[index];
+    name = item->GetName() + WCHAR_PATH_SEPARATOR + name;
+  }
+}
+
+static wchar_t *AddSubStringToName(wchar_t *dest, const Byte *p, int numChars)
+{
+  for (int i = 0; i < numChars; i++)
+  {
+    wchar_t c = Get16(p + i * 2);
+    if (c != 0 && c != 0xFFFF)
+      *dest++ = c;
+  }
+  *dest = 0;
+  return dest;
+}
+
+HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, int level)
+{
+  int startIndex = Items.Size();
+  if (startIndex >= (1 << 30) || level > 256)
+    return S_FALSE;
+
+  UInt32 sectorIndex = 0;
+  UInt32 blockSize = Header.ClusterSize();
+  bool clusterMode = (Header.IsFat32() || parent >= 0);
+  if (!clusterMode)
+  {
+    blockSize = Header.SectorSize();
+    RINOK(SeekToSector(Header.RootDirSector));
+  }
+
+  ByteBuf.SetCapacity(blockSize);
+  UString curName;
+  int checkSum = -1;
+  int numLongRecords = -1;
+  for (UInt32 pos = blockSize;; pos += 32)
+  {
+    if (pos == blockSize)
+    {
+      pos = 0;
+
+      if ((NumDirClusters & 0xFF) == 0)
+      {
+        RINOK(OpenProgress());
+      }
+
+      if (clusterMode)
+      {
+        if (Header.IsEoc(cluster))
+          break;
+        if (!Header.IsValidCluster(cluster))
+          return S_FALSE;
+        PRF(printf("\nCluster = %4X", cluster));
+        RINOK(SeekToCluster(cluster));
+        UInt32 newCluster = Fat[cluster];
+        if ((newCluster & kFatItemUsedByDirMask) != 0)
+          return S_FALSE;
+        Fat[cluster] |= kFatItemUsedByDirMask;
+        cluster = newCluster;
+        NumDirClusters++;
+        NumCurUsedBytes += Header.ClusterSize();
+      }
+      else if (sectorIndex++ >= Header.NumRootDirSectors)
+        break;
+      
+      RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize));
+    }
+    const Byte *p = ByteBuf + pos;
+    if (p[0] == 0)
+    {
+      /*
+      // FreeDOS formats FAT partition with cluster chain longer than required.
+      if (clusterMode && !Header.IsEoc(cluster))
+        return S_FALSE;
+      */
+      break;
+    }
+    if (p[0] == 0xE5)
+    {
+      if (numLongRecords > 0)
+        return S_FALSE;
+      continue;
+    }
+    
+    Byte attrib = p[11];
+    if ((attrib & 0x3F) == 0xF)
+    {
+      if (p[0] > 0x7F || Get16(p + 26) != 0)
+        return S_FALSE;
+      int longIndex = p[0] & 0x3F;
+      if (longIndex == 0)
+        return S_FALSE;
+      bool isLast = (p[0] & 0x40) != 0;
+      if (numLongRecords < 0)
+      {
+        if (!isLast)
+          return S_FALSE;
+        numLongRecords = longIndex;
+      }
+      else if (isLast || numLongRecords != longIndex)
+        return S_FALSE;
+
+      numLongRecords--;
+      
+      if (p[12] == 0)
+      {
+        wchar_t nameBuf[14];
+        wchar_t *dest;
+        
+        dest = AddSubStringToName(nameBuf, p + 1, 5);
+        dest = AddSubStringToName(dest, p + 14, 6);
+        AddSubStringToName(dest, p + 28, 2);
+        curName = nameBuf + curName;
+        if (isLast)
+          checkSum = p[13];
+        if (checkSum != p[13])
+          return S_FALSE;
+      }
+    }
+    else
+    {
+      if (numLongRecords > 0)
+        return S_FALSE;
+      CItem item;
+      memcpy(item.DosName, p, 11);
+
+      if (checkSum >= 0)
+      {
+        Byte sum = 0;
+        for (int i = 0; i < 11; i++)
+          sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + (Byte)item.DosName[i];
+        if (sum == checkSum)
+          item.UName = curName;
+      }
+
+      if (item.DosName[0] == 5)
+        item.DosName[0] = (char)(Byte)0xE5;
+      item.Attrib = attrib;
+      item.Flags = p[12];
+      item.Size = Get32(p + 28);
+      item.Cluster = Get16(p + 26);
+      if (Header.NumFatBits > 16)
+        item.Cluster |= ((UInt32)Get16(p + 20) << 16);
+      else
+      {
+        // OS/2 and WinNT probably can store EA (extended atributes) in that field.
+      }
+
+      item.CTime = Get32(p + 14);
+      item.CTime2 = p[13];
+      item.ADate = Get16(p + 18);
+      item.MTime = Get32(p + 22);
+      item.Parent = parent;
+
+      if (attrib == 8)
+      {
+        VolItem = item;
+        VolItemDefined = true;
+      }
+      else
+        if (memcmp(item.DosName, ".          ", 11) != 0 &&
+            memcmp(item.DosName, "..         ", 11) != 0)
+      {
+        if (!item.IsDir())
+          NumCurUsedBytes += Header.GetFilePackSize(item.Size);
+        Items.Add(item);
+        PRF(printf("\n%7d: %S", Items.Size(), GetItemPath(Items.Size() - 1)));
+      }
+      numLongRecords = -1;
+      curName.Empty();
+      checkSum = -1;
+    }
+  }
+
+  int finishIndex = Items.Size();
+  for (int i = startIndex; i < finishIndex; i++)
+  {
+    const CItem &item = Items[i];
+    if (item.IsDir())
+    {
+      PRF(printf("\n%S", GetItemPath(i)));
+      RINOK(CDatabase::ReadDir(i, item.Cluster, level + 1));
+    }
+  }
+  return S_OK;
+}
+
+HRESULT CDatabase::Open()
+{
+  Clear();
+  bool numFreeClustersDefined = false;
+  {
+    static const UInt32 kHeaderSize = 512;
+    Byte buf[kHeaderSize];
+    RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize));
+    if (!Header.Parse(buf))
+      return S_FALSE;
+    UInt64 fileSize;
+    RINOK(InStream->Seek(0, STREAM_SEEK_END, &fileSize));
+
+    /* we comment that check to support truncated images */
+    /*
+    if (fileSize < Header.GetPhySize())
+      return S_FALSE;
+    */
+
+    if (Header.IsFat32())
+    {
+      SeekToSector(Header.FsInfoSector);
+      RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize));
+      if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)
+        return S_FALSE;
+      if (Get32(buf) == 0x41615252 && Get32(buf + 484) == 0x61417272)
+      {
+        NumFreeClusters = Get32(buf + 488);
+        numFreeClustersDefined = (NumFreeClusters <= Header.FatSize);
+      }
+    }
+  }
+
+  // numFreeClustersDefined = false; // to recalculate NumFreeClusters
+  if (!numFreeClustersDefined)
+    NumFreeClusters = 0;
+
+  CByteBuffer byteBuf;
+  Fat = new UInt32[Header.FatSize];
+
+  RINOK(OpenProgressFat());
+  RINOK(SeekToSector(Header.GetFatSector()));
+  if (Header.NumFatBits == 32)
+  {
+    const UInt32 kBufSize = (1 << 15);
+    byteBuf.SetCapacity(kBufSize);
+    for (UInt32 i = 0; i < Header.FatSize;)
+    {
+      UInt32 size = Header.FatSize - i;
+      const UInt32 kBufSize32 = kBufSize / 4;
+      if (size > kBufSize32)
+        size = kBufSize32;
+      UInt32 readSize = Header.SizeToSectors(size * 4) << Header.SectorSizeLog;
+      RINOK(ReadStream_FALSE(InStream, byteBuf, readSize));
+      NumCurUsedBytes += readSize;
+
+      const UInt32 *src = (const UInt32 *)(const Byte *)byteBuf;
+      UInt32 *dest = Fat + i;
+      if (numFreeClustersDefined)
+        for (UInt32 j = 0; j < size; j++)
+          dest[j] = Get32(src + j) & 0x0FFFFFFF;
+      else
+      {
+        UInt32 numFreeClusters = 0;
+        for (UInt32 j = 0; j < size; j++)
+        {
+          UInt32 v = Get32(src + j) & 0x0FFFFFFF;
+          numFreeClusters += (UInt32)(v - 1) >> 31;
+          dest[j] = v;
+        }
+        NumFreeClusters += numFreeClusters;
+      }
+      i += size;
+      if ((i & 0xFFFFF) == 0)
+      {
+        RINOK(OpenProgressFat(!numFreeClustersDefined));
+      }
+    }
+  }
+  else
+  {
+    const UInt32 kBufSize = (UInt32)Header.CalcFatSizeInSectors() << Header.SectorSizeLog;
+    NumCurUsedBytes += kBufSize;
+    byteBuf.SetCapacity(kBufSize);
+    Byte *p = byteBuf;
+    RINOK(ReadStream_FALSE(InStream, p, kBufSize));
+    UInt32 fatSize = Header.FatSize;
+    UInt32 *fat = &Fat[0];
+    if (Header.NumFatBits == 16)
+      for (UInt32 j = 0; j < fatSize; j++)
+        fat[j] = Get16(p + j * 2);
+    else
+      for (UInt32 j = 0; j < fatSize; j++)
+        fat[j] = (Get16(p + j * 3 / 2) >> ((j & 1) << 2)) & 0xFFF;
+
+    if (!numFreeClustersDefined)
+    {
+      UInt32 numFreeClusters = 0;
+      for (UInt32 i = 0; i < fatSize; i++)
+        numFreeClusters += (UInt32)(fat[i] - 1) >> 31;
+      NumFreeClusters = numFreeClusters;
+    }
+  }
+
+  RINOK(OpenProgressFat());
+
+  if ((Fat[0] & 0xFF) != Header.MediaType)
+     return S_FALSE;
+
+  return ReadDir(-1, Header.RootCluster, 0);
+}
+
+class CHandler:
+  public IInArchive,
+  public IInArchiveGetStream,
+  public CMyUnknownImp,
+  CDatabase
+{
+public:
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+  INTERFACE_IInArchive(;)
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+};
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+  COM_TRY_BEGIN
+  *stream = 0;
+  const CItem &item = Items[index];
+  CClusterInStream *streamSpec = new CClusterInStream;
+  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
+  streamSpec->Stream = InStream;
+  streamSpec->StartOffset = Header.DataSector << Header.SectorSizeLog;
+  streamSpec->BlockSizeLog = Header.ClusterSizeLog;
+  streamSpec->Size = item.Size;
+
+  UInt32 numClusters = Header.GetNumClusters(item.Size);
+  streamSpec->Vector.Reserve(numClusters);
+  UInt32 cluster = item.Cluster;
+  UInt32 size = item.Size;
+
+  if (size == 0)
+  {
+    if (cluster != 0)
+      return S_FALSE;
+  }
+  else
+  {
+    UInt32 clusterSize = Header.ClusterSize();
+    for (;; size -= clusterSize)
+    {
+      if (!Header.IsValidCluster(cluster))
+        return S_FALSE;
+      streamSpec->Vector.Add(cluster - 2);
+      cluster = Fat[cluster];
+      if (size <= clusterSize)
+        break;
+    }
+    if (!Header.IsEocAndUnused(cluster))
+      return S_FALSE;
+  }
+  RINOK(streamSpec->InitAndSeek());
+  *stream = streamTemp.Detach();
+  return S_OK;
+  COM_TRY_END
+}
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidIsDir, VT_BOOL},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMTime, VT_FILETIME},
+  { NULL, kpidCTime, VT_FILETIME},
+  { NULL, kpidATime, VT_FILETIME},
+  { NULL, kpidAttrib, VT_UI8},
+  { NULL, kpidShortName, VT_BSTR}
+};
+
+enum
+{
+  kpidNumFats = kpidUserDefined
+  // kpidOemName,
+  // kpidVolName,
+  // kpidFileSysType
+};
+
+STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidFileSystem, VT_BSTR},
+  { NULL, kpidClusterSize, VT_UI4},
+  { NULL, kpidPhySize, VT_UI8},
+  { NULL, kpidFreeSpace, VT_UI8},
+  { NULL, kpidHeadersSize, VT_UI8},
+  { NULL, kpidMTime, VT_FILETIME},
+  { NULL, kpidVolumeName, VT_BSTR},
+
+  { L"FATs", kpidNumFats, VT_UI4},
+  { NULL, kpidSectorSize, VT_UI4},
+  { NULL, kpidId, VT_UI4},
+  // { L"OEM Name", kpidOemName, VT_BSTR},
+  // { L"Volume Name", kpidVolName, VT_BSTR},
+  // { L"File System Type", kpidFileSysType, VT_BSTR}
+  // { NULL, kpidSectorsPerTrack, VT_UI4},
+  // { NULL, kpidNumHeads, VT_UI4},
+  // { NULL, kpidHiddenSectors, VT_UI4}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_WITH_NAME
+
+static void FatTimeToProp(UInt32 dosTime, UInt32 ms10, NWindows::NCOM::CPropVariant &prop)
+{
+  FILETIME localFileTime, utc;
+  if (NWindows::NTime::DosTimeToFileTime(dosTime, localFileTime))
+    if (LocalFileTimeToFileTime(&localFileTime, &utc))
+    {
+      UInt64 t64 = (((UInt64)utc.dwHighDateTime) << 32) + utc.dwLowDateTime;
+      t64 += ms10 * 100000;
+      utc.dwLowDateTime = (DWORD)t64;
+      utc.dwHighDateTime = (DWORD)(t64 >> 32);
+      prop = utc;
+    }
+}
+
+/*
+static void StringToProp(const Byte *src, int size, NWindows::NCOM::CPropVariant &prop)
+{
+  char dest[32];
+  memcpy(dest, src, size);
+  dest[size] = 0;
+  prop = FatStringToUnicode(dest);
+}
+
+#define STRING_TO_PROP(s, p) StringToProp(s, sizeof(s), prop)
+*/
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidFileSystem:
+    {
+      wchar_t s[32] = { L'F', L'A', L'T' };
+      ConvertUInt32ToString(Header.NumFatBits, s + 3);
+      prop = s;
+      break;
+    }
+    case kpidClusterSize: prop = Header.ClusterSize(); break;
+    case kpidPhySize: prop = Header.GetPhySize(); break;
+    case kpidFreeSpace: prop = (UInt64)NumFreeClusters << Header.ClusterSizeLog; break;
+    case kpidHeadersSize: prop = GetHeadersSize(); break;
+    case kpidMTime: if (VolItemDefined) FatTimeToProp(VolItem.MTime, 0, prop); break;
+    case kpidVolumeName: if (VolItemDefined) prop = VolItem.GetVolName(); break;
+    case kpidNumFats: if (Header.NumFats != 2) prop = Header.NumFats; break;
+    case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break;
+    // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break;
+    // case kpidNumHeads: prop = Header.NumHeads; break;
+    // case kpidOemName: STRING_TO_PROP(Header.OemName, prop); break;
+    case kpidId: if (Header.VolFieldsDefined) prop = Header.VolId; break;
+    // case kpidVolName: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.VolName, prop); break;
+    // case kpidFileSysType: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.FileSys, prop); break;
+    // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  const CItem &item = Items[index];
+  switch(propID)
+  {
+    case kpidPath: prop = GetItemPath(index); break;
+    case kpidShortName: prop = item.GetShortName(); break;
+    case kpidIsDir: prop = item.IsDir(); break;
+    case kpidMTime: FatTimeToProp(item.MTime, 0, prop); break;
+    case kpidCTime: FatTimeToProp(item.CTime, item.CTime2, prop); break;
+    case kpidATime: FatTimeToProp(((UInt32)item.ADate << 16), 0, prop); break;
+    case kpidAttrib: prop = (UInt32)item.Attrib; break;
+    case kpidSize: if (!item.IsDir()) prop = item.Size; break;
+    case kpidPackSize: if (!item.IsDir()) prop = Header.GetFilePackSize(item.Size); break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)
+{
+  COM_TRY_BEGIN
+  {
+    OpenCallback = callback;
+    InStream = stream;
+    HRESULT res;
+    try
+    {
+      res = CDatabase::Open();
+      if (res == S_OK)
+        return S_OK;
+    }
+    catch(...)
+    {
+      Close();
+      throw;
+    }
+    Close();
+    return res;
+  }
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  ClearAndClose();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = Items.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt32 i;
+  UInt64 totalSize = 0;
+  for (i = 0; i < numItems; i++)
+  {
+    const CItem &item = Items[allFilesMode ? i : indices[i]];
+    if (!item.IsDir())
+      totalSize += item.Size;
+  }
+  RINOK(extractCallback->SetTotal(totalSize));
+
+  UInt64 totalPackSize;
+  totalSize = totalPackSize = 0;
+  
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  CDummyOutStream *outStreamSpec = new CDummyOutStream;
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+
+  for (i = 0; i < numItems; i++)
+  {
+    lps->InSize = totalPackSize;
+    lps->OutSize = totalSize;
+    RINOK(lps->SetCur());
+    CMyComPtr<ISequentialOutStream> realOutStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    Int32 index = allFilesMode ? i : indices[i];
+    const CItem &item = Items[index];
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+    if (item.IsDir())
+    {
+      RINOK(extractCallback->PrepareOperation(askMode));
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+      continue;
+    }
+
+    totalPackSize += Header.GetFilePackSize(item.Size);
+    totalSize += item.Size;
+
+    if (!testMode && !realOutStream)
+      continue;
+    RINOK(extractCallback->PrepareOperation(askMode));
+
+    outStreamSpec->SetStream(realOutStream);
+    realOutStream.Release();
+    outStreamSpec->Init();
+
+    int res = NExtract::NOperationResult::kDataError;
+    CMyComPtr<ISequentialInStream> inStream;
+    HRESULT hres = GetStream(index, &inStream);
+    if (hres != S_FALSE)
+    {
+      RINOK(hres);
+      if (inStream)
+      {
+        RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
+        if (copyCoderSpec->TotalSize == item.Size)
+          res = NExtract::NOperationResult::kOK;
+      }
+    }
+    outStreamSpec->ReleaseStream();
+    RINOK(extractCallback->SetOperationResult(res));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = Items.Size();
+  return S_OK;
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"FAT", L"fat img", 0, 0xDA, { 0x55, 0xAA }, 2, false, CreateArc, 0 };
+
+REGISTER_ARC(Fat)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/FlvHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/FlvHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/FlvHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/FlvHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,544 @@
+// FlvHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/Buffer.h"
+#include "Common/ComTry.h"
+// #include "Common/Defs.h"
+#include "Common/MyString.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamObjects.h"
+#include "../Common/StreamUtils.h"
+
+#define GetBe24(p) ( \
+    ((UInt32)((const Byte *)(p))[0] << 16) | \
+    ((UInt32)((const Byte *)(p))[1] <<  8) | \
+             ((const Byte *)(p))[2] )
+
+#define Get16(p) GetBe16(p)
+#define Get24(p) GetBe24(p)
+#define Get32(p) GetBe32(p)
+
+namespace NArchive {
+namespace NFlv {
+
+static const UInt32 kFileSizeMax = (UInt32)1 << 30;
+static const int kNumChunksMax = (UInt32)1 << 23;
+
+const UInt32 kTagHeaderSize = 11;
+
+static const Byte kFlag_Video = 1;
+static const Byte kFlag_Audio = 4;
+
+static const Byte kType_Audio = 8;
+static const Byte kType_Video = 9;
+static const Byte kType_Meta = 18;
+static const int kNumTypes = 19;
+
+struct CItem
+{
+  UInt32 Offset;
+  UInt32 Size;
+  // UInt32 Time;
+  Byte Type;
+};
+
+struct CItem2
+{
+  Byte Type;
+  Byte SubType;
+  Byte Props;
+  bool SameSubTypes;
+  int NumChunks;
+  size_t Size;
+
+  CReferenceBuf *BufSpec;
+  CMyComPtr<IUnknown> RefBuf;
+
+  bool IsAudio() const { return Type == kType_Audio; }
+};
+
+class CHandler:
+  public IInArchive,
+  public IInArchiveGetStream,
+  public CMyUnknownImp
+{
+  int _isRaw;
+  CMyComPtr<IInStream> _stream;
+  CObjectVector<CItem2> _items2;
+  // CByteBuffer _metadata;
+  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
+  AString GetComment();
+public:
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+  INTERFACE_IInArchive(;)
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+};
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidNumBlocks, VT_UI4},
+  { NULL, kpidComment, VT_BSTR}
+};
+
+/*
+STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidComment, VT_BSTR}
+};
+*/
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_NO
+
+static const char *g_AudioTypes[16] =
+{
+  "pcm",
+  "adpcm",
+  "mp3",
+  "pcm_le",
+  "nellymoser16",
+  "nellymoser8",
+  "nellymoser",
+  "g711a",
+  "g711m",
+  "audio9",
+  "aac",
+  "speex",
+  "audio12",
+  "audio13",
+  "mp3",
+  "audio15"
+};
+
+static const char *g_VideoTypes[16] =
+{
+  "video0",
+  "jpeg",
+  "h263",
+  "screen",
+  "vp6",
+  "vp6alpha",
+  "screen2",
+  "avc",
+  "video8",
+  "video9",
+  "video10",
+  "video11",
+  "video12",
+  "video13",
+  "video14",
+  "video15"
+};
+
+static const char *g_Rates[4] =
+{
+  "5.5 kHz",
+  "11 kHz",
+  "22 kHz",
+  "44 kHz"
+};
+
+static void MyStrCat(char *d, const char *s)
+{
+  MyStringCopy(d + MyStringLen(d), s);
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  NWindows::NCOM::CPropVariant prop;
+  const CItem2 &item = _items2[index];
+  switch(propID)
+  {
+    case kpidExtension:
+      prop = _isRaw ?
+        (item.IsAudio() ? g_AudioTypes[item.SubType] : g_VideoTypes[item.SubType]) :
+        (item.IsAudio() ? "audio.flv" : "video.flv");
+      break;
+    case kpidSize:
+    case kpidPackSize:
+      prop = (UInt64)item.Size;
+      break;
+    case kpidNumBlocks: prop = (UInt32)item.NumChunks; break;
+    case kpidComment:
+    {
+      char sz[64];
+      MyStringCopy(sz, (item.IsAudio() ? g_AudioTypes[item.SubType] : g_VideoTypes[item.SubType]) );
+      if (item.IsAudio())
+      {
+        MyStrCat(sz, " ");
+        MyStrCat(sz, g_Rates[(item.Props >> 2) & 3]);
+        MyStrCat(sz, (item.Props & 2) ? " 16-bit" : " 8-bit");
+        MyStrCat(sz, (item.Props & 1) ? " stereo" : " mono");
+      }
+      prop = sz;
+      break;
+    }
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+/*
+AString CHandler::GetComment()
+{
+  const Byte *p = _metadata;
+  size_t size = _metadata.GetCapacity();
+  AString res;
+  if (size > 0)
+  {
+    p++;
+    size--;
+    for (;;)
+    {
+      if (size < 2)
+        break;
+      int len = Get16(p);
+      p += 2;
+      size -= 2;
+      if (len == 0 || (size_t)len > size)
+        break;
+      {
+        AString temp;
+        char *sz = temp.GetBuffer(len);
+        memcpy(sz, p, len);
+        sz[len] = 0;
+        temp.ReleaseBuffer();
+        if (!res.IsEmpty())
+          res += '\n';
+        res += temp;
+      }
+      p += len;
+      size -= len;
+      if (size < 1)
+        break;
+      Byte type = *p++;
+      size--;
+      bool ok = false;
+      switch(type)
+      {
+        case 0:
+        {
+          if (size < 8)
+            break;
+          ok = true;
+          Byte reverse[8];
+          for (int i = 0; i < 8; i++)
+          {
+            bool little_endian = 1;
+            if (little_endian)
+              reverse[i] = p[7 - i];
+            else
+              reverse[i] = p[i];
+          }
+          double d = *(double *)reverse;
+          char temp[32];
+          sprintf(temp, " = %.3f", d);
+          res += temp;
+          p += 8;
+          size -= 8;
+          break;
+        }
+        case 8:
+        {
+          if (size < 4)
+            break;
+          ok = true;
+          // UInt32 numItems = Get32(p);
+          p += 4;
+          size -= 4;
+          break;
+        }
+      }
+      if (!ok)
+        break;
+    }
+  }
+  return res;
+}
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidComment: prop = GetComment(); break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+*/
+
+HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
+{
+  CRecordVector<CItem> items;
+
+  const UInt32 kHeaderSize = 13;
+  Byte header[kHeaderSize];
+  RINOK(ReadStream_FALSE(stream, header, kHeaderSize));
+  if (header[0] != 'F' ||
+      header[1] != 'L' ||
+      header[2] != 'V' ||
+      header[3] != 1 ||
+      (header[4] & 0xFA) != 0)
+    return S_FALSE;
+  UInt32 offset = Get32(header + 5);
+  if (offset != 9 || Get32(header + 9) != 0)
+    return S_FALSE;
+  offset += 4;
+ 
+  CByteBuffer inBuf;
+  size_t fileSize;
+  {
+    UInt64 fileSize64;
+    RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize64));
+    if (fileSize64 > kFileSizeMax)
+      return S_FALSE;
+
+    if (callback)
+      RINOK(callback->SetTotal(NULL, &fileSize64))
+
+    RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
+    fileSize = (size_t)fileSize64;
+    inBuf.SetCapacity(fileSize);
+    for (size_t pos = 0; pos < fileSize;)
+    {
+      UInt64 offset64 = pos;
+      if (callback)
+        RINOK(callback->SetCompleted(NULL, &offset64))
+      size_t rem = MyMin(fileSize - pos, (size_t)(1 << 20));
+      RINOK(ReadStream_FALSE(stream, inBuf + pos, rem));
+      pos += rem;
+    }
+  }
+
+  int lasts[kNumTypes];
+  int i;
+  for (i = 0; i < kNumTypes; i++)
+    lasts[i] = -1;
+
+  while (offset < fileSize)
+  {
+    CItem item;
+    item.Offset = offset;
+    const Byte *buf = inBuf + offset;
+    offset += kTagHeaderSize;
+    if (offset > fileSize)
+      return S_FALSE;
+
+    item.Type = buf[0];
+    UInt32 size = Get24(buf + 1);
+    if (size < 1)
+      return S_FALSE;
+    // item.Time = Get24(buf + 4);
+    // item.Time |= (UInt32)buf[7] << 24;
+    if (Get24(buf + 8) != 0) // streamID
+      return S_FALSE;
+
+    UInt32 curSize = kTagHeaderSize + size + 4;
+    item.Size = curSize;
+    
+    offset += curSize - kTagHeaderSize;
+    if (offset > fileSize)
+      return S_FALSE;
+    
+    if (Get32(buf + kTagHeaderSize + size) != kTagHeaderSize + size)
+      return S_FALSE;
+
+    // printf("\noffset = %6X type = %2d time = %6d size = %6d", (UInt32)offset, item.Type, item.Time, item.Size);
+
+    if (item.Type == kType_Meta)
+    {
+      // _metadata = item.Buf;
+    }
+    else
+    {
+      if (item.Type != kType_Audio && item.Type != kType_Video)
+        return S_FALSE;
+      if (items.Size() >= kNumChunksMax)
+        return S_FALSE;
+      Byte firstByte = buf[kTagHeaderSize];
+      Byte subType, props;
+      if (item.Type == kType_Audio)
+      {
+        subType = firstByte >> 4;
+        props = firstByte & 0xF;
+      }
+      else
+      {
+        subType = firstByte & 0xF;
+        props = firstByte >> 4;
+      }
+      int last = lasts[item.Type];
+      if (last < 0)
+      {
+        CItem2 item2;
+        item2.RefBuf = item2.BufSpec = new CReferenceBuf;
+        item2.Size = curSize;
+        item2.Type = item.Type;
+        item2.SubType = subType;
+        item2.Props = props;
+        item2.NumChunks = 1;
+        item2.SameSubTypes = true;
+        lasts[item.Type] = _items2.Add(item2);
+      }
+      else
+      {
+        CItem2 &item2 = _items2[last];
+        if (subType != item2.SubType)
+          item2.SameSubTypes = false;
+        item2.Size += curSize;
+        item2.NumChunks++;
+      }
+      items.Add(item);
+    }
+  }
+
+  _isRaw = (_items2.Size() == 1);
+  for (i = 0; i < _items2.Size(); i++)
+  {
+    CItem2 &item2 = _items2[i];
+    CByteBuffer &itemBuf = item2.BufSpec->Buf;
+    if (_isRaw)
+    {
+      if (!item2.SameSubTypes)
+        return S_FALSE;
+      itemBuf.SetCapacity((size_t)item2.Size - (kTagHeaderSize + 4 + 1) * item2.NumChunks);
+      item2.Size = 0;
+    }
+    else
+    {
+      itemBuf.SetCapacity(kHeaderSize + (size_t)item2.Size);
+      memcpy(itemBuf, header, kHeaderSize);
+      itemBuf[4] = item2.IsAudio() ? kFlag_Audio : kFlag_Video;
+      item2.Size = kHeaderSize;
+    }
+  }
+
+  for (i = 0; i < items.Size(); i++)
+  {
+    const CItem &item = items[i];
+    CItem2 &item2 = _items2[lasts[item.Type]];
+    size_t size = item.Size;
+    const Byte *src = inBuf + item.Offset;
+    if (_isRaw)
+    {
+      src += kTagHeaderSize + 1;
+      size -= (kTagHeaderSize + 4 + 1);
+    }
+    memcpy(item2.BufSpec->Buf + item2.Size, src, size);
+    item2.Size += size;
+  }
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback)
+{
+  COM_TRY_BEGIN
+  Close();
+  HRESULT res;
+  try
+  {
+    res = Open2(inStream, callback);
+    if (res == S_OK)
+      _stream = inStream;
+  }
+  catch(...) { res = S_FALSE; }
+  if (res != S_OK)
+  {
+    Close();
+    return S_FALSE;
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _stream.Release();
+  _items2.Clear();
+  // _metadata.SetCapacity(0);
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _items2.Size();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _items2.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt64 totalSize = 0;
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+    totalSize += _items2[allFilesMode ? i : indices[i]].Size;
+  extractCallback->SetTotal(totalSize);
+
+  totalSize = 0;
+  
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  for (i = 0; i < numItems; i++)
+  {
+    lps->InSize = lps->OutSize = totalSize;
+    RINOK(lps->SetCur());
+    CMyComPtr<ISequentialOutStream> outStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    UInt32 index = allFilesMode ? i : indices[i];
+    const CItem2 &item = _items2[index];
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));
+    totalSize += item.Size;
+    if (!testMode && !outStream)
+      continue;
+    RINOK(extractCallback->PrepareOperation(askMode));
+    if (outStream)
+    {
+      RINOK(WriteStream(outStream, item.BufSpec->Buf, item.BufSpec->Buf.GetCapacity()));
+    }
+    RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+  COM_TRY_BEGIN
+  *stream = 0;
+  CBufInStream *streamSpec = new CBufInStream;
+  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
+  streamSpec->Init(_items2[index].BufSpec);
+  *stream = streamTemp.Detach();
+  return S_OK;
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"FLV", L"flv", 0, 0xD6, { 'F', 'L', 'V' }, 3, false, CreateArc, 0 };
+
+REGISTER_ARC(Flv)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/GzHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/GzHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/GzHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/GzHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,698 @@
+// GzHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/ComTry.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+#include "../Compress/DeflateDecoder.h"
+#include "../Compress/DeflateEncoder.h"
+
+#include "Common/InStreamWithCRC.h"
+#include "Common/OutStreamWithCRC.h"
+
+#include "DeflateProps.h"
+
+#define Get32(p) GetUi32(p)
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NGz {
+
+static const UInt16 kSignature = 0x8B1F;
+
+namespace NHeader
+{
+  namespace NFlags
+  {
+    const Byte kIsText = 1 << 0;
+    const Byte kCrc = 1 << 1;
+    const Byte kExtra = 1 << 2;
+    const Byte kName = 1 << 3;
+    const Byte kComment = 1 << 4;
+  }
+  
+  namespace NExtraFlags
+  {
+    const Byte kMaximum = 2;
+    const Byte kFastest = 4;
+  }
+  
+  namespace NCompressionMethod
+  {
+    const Byte kDeflate = 8;
+  }
+
+  namespace NHostOS
+  {
+    enum EEnum
+    {
+      kFAT = 0,
+      kAMIGA,
+      kVMS,
+      kUnix,
+      kVM_CMS,
+      kAtari,
+      kHPFS,
+      kMac,
+      kZ_System,
+      kCPM,
+      kTOPS20,
+      kNTFS,
+      kQDOS,
+      kAcorn,
+      kVFAT,
+      kMVS,
+      kBeOS,
+      kTandem,
+      
+      kUnknown = 255
+    };
+  }
+}
+
+static const char *kHostOSes[] =
+{
+  "FAT",
+  "AMIGA",
+  "VMS",
+  "Unix",
+  "VM/CMS",
+  "Atari",
+  "HPFS",
+  "Macintosh",
+  "Z-System",
+  "CP/M",
+  "TOPS-20",
+  "NTFS",
+  "SMS/QDOS",
+  "Acorn",
+  "VFAT",
+  "MVS",
+  "BeOS",
+  "Tandem",
+  "OS/400",
+  "OS/X"
+};
+
+static const char *kUnknownOS = "Unknown";
+
+class CItem
+{
+  bool TestFlag(Byte flag) const { return (Flags & flag) != 0; }
+public:
+  Byte Method;
+  Byte Flags;
+  Byte ExtraFlags;
+  Byte HostOS;
+  UInt32 Time;
+  UInt32 Crc;
+  UInt32 Size32;
+
+  AString Name;
+  AString Comment;
+  // CByteBuffer Extra;
+
+  // bool IsText() const { return TestFlag(NHeader::NFlags::kIsText); }
+  bool HeaderCrcIsPresent() const { return TestFlag(NHeader::NFlags::kCrc); }
+  bool ExtraFieldIsPresent() const { return TestFlag(NHeader::NFlags::kExtra); }
+  bool NameIsPresent() const { return TestFlag(NHeader::NFlags::kName); }
+  bool CommentIsPresent() const { return TestFlag(NHeader::NFlags::kComment); }
+
+  void Clear()
+  {
+    Name.Empty();
+    Comment.Empty();
+    // Extra.SetCapacity(0);
+  }
+
+  HRESULT ReadHeader(NCompress::NDeflate::NDecoder::CCOMCoder *stream);
+  HRESULT ReadFooter1(NCompress::NDeflate::NDecoder::CCOMCoder *stream);
+  HRESULT ReadFooter2(ISequentialInStream *stream);
+
+  HRESULT WriteHeader(ISequentialOutStream *stream);
+  HRESULT WriteFooter(ISequentialOutStream *stream);
+};
+
+static HRESULT ReadBytes(NCompress::NDeflate::NDecoder::CCOMCoder *stream, Byte *data, UInt32 size)
+{
+  for (UInt32 i = 0; i < size; i++)
+    data[i] = stream->ReadByte();
+  return stream->InputEofError() ? S_FALSE : S_OK;
+}
+
+static HRESULT SkipBytes(NCompress::NDeflate::NDecoder::CCOMCoder *stream, UInt32 size)
+{
+  for (UInt32 i = 0; i < size; i++)
+    stream->ReadByte();
+  return stream->InputEofError() ? S_FALSE : S_OK;
+}
+
+static HRESULT ReadUInt16(NCompress::NDeflate::NDecoder::CCOMCoder *stream, UInt16 &value /* , UInt32 &crc */)
+{
+  value = 0;
+  for (int i = 0; i < 2; i++)
+  {
+    Byte b = stream->ReadByte();
+    if (stream->InputEofError())
+      return S_FALSE;
+    // crc = CRC_UPDATE_BYTE(crc, b);
+    value |= (UInt16(b) << (8 * i));
+  }
+  return S_OK;
+}
+
+static HRESULT ReadString(NCompress::NDeflate::NDecoder::CCOMCoder *stream, AString &s, UInt32 limit /* , UInt32 &crc */)
+{
+  s.Empty();
+  for (UInt32 i = 0; i < limit; i++)
+  {
+    Byte b = stream->ReadByte();
+    if (stream->InputEofError())
+      return S_FALSE;
+    // crc = CRC_UPDATE_BYTE(crc, b);
+    if (b == 0)
+      return S_OK;
+    s += (char)b;
+  }
+  return S_FALSE;
+}
+
+HRESULT CItem::ReadHeader(NCompress::NDeflate::NDecoder::CCOMCoder *stream)
+{
+  Clear();
+
+  // Header-CRC field had another meaning in old version of gzip!
+  // UInt32 crc = CRC_INIT_VAL;
+  Byte buf[10];
+
+  RINOK(ReadBytes(stream, buf, 10));
+  
+  if (GetUi16(buf) != kSignature)
+    return S_FALSE;
+
+  Method = buf[2];
+
+  if (Method != NHeader::NCompressionMethod::kDeflate)
+    return S_FALSE;
+
+  Flags = buf[3];
+  Time = Get32(buf + 4);
+  ExtraFlags = buf[8];
+  HostOS = buf[9];
+
+  // crc = CrcUpdate(crc, buf, 10);
+  
+  if (ExtraFieldIsPresent())
+  {
+    UInt16 extraSize;
+    RINOK(ReadUInt16(stream, extraSize /* , crc */));
+    RINOK(SkipBytes(stream, extraSize));
+    // Extra.SetCapacity(extraSize);
+    // RINOK(ReadStream_FALSE(stream, Extra, extraSize));
+    // crc = CrcUpdate(crc, Extra, extraSize);
+  }
+  if (NameIsPresent())
+    RINOK(ReadString(stream, Name, (1 << 10) /* , crc */));
+  if (CommentIsPresent())
+    RINOK(ReadString(stream, Comment, (1 << 16) /* , crc */));
+
+  if (HeaderCrcIsPresent())
+  {
+    UInt16 headerCRC;
+    // UInt32 dummy = 0;
+    RINOK(ReadUInt16(stream, headerCRC /* , dummy */));
+    /*
+    if ((UInt16)CRC_GET_DIGEST(crc) != headerCRC)
+      return S_FALSE;
+    */
+  }
+  return stream->InputEofError() ? S_FALSE : S_OK;
+}
+
+HRESULT CItem::ReadFooter1(NCompress::NDeflate::NDecoder::CCOMCoder *stream)
+{
+  Byte buf[8];
+  RINOK(ReadBytes(stream, buf, 8));
+  Crc = Get32(buf);
+  Size32 = Get32(buf + 4);
+  return stream->InputEofError() ? S_FALSE : S_OK;
+}
+
+HRESULT CItem::ReadFooter2(ISequentialInStream *stream)
+{
+  Byte buf[8];
+  RINOK(ReadStream_FALSE(stream, buf, 8));
+  Crc = Get32(buf);
+  Size32 = Get32(buf + 4);
+  return S_OK;
+}
+
+HRESULT CItem::WriteHeader(ISequentialOutStream *stream)
+{
+  Byte buf[10];
+  SetUi16(buf, kSignature);
+  buf[2] = Method;
+  buf[3] = Flags & NHeader::NFlags::kName;
+  // buf[3] |= NHeader::NFlags::kCrc;
+  SetUi32(buf + 4, Time);
+  buf[8] = ExtraFlags;
+  buf[9] = HostOS;
+  RINOK(WriteStream(stream, buf, 10));
+  // crc = CrcUpdate(CRC_INIT_VAL, buf, 10);
+  if (NameIsPresent())
+  {
+    // crc = CrcUpdate(crc, (const char *)Name, Name.Length() + 1);
+    RINOK(WriteStream(stream, (const char *)Name, Name.Length() + 1));
+  }
+  // SetUi16(buf, (UInt16)CRC_GET_DIGEST(crc));
+  // RINOK(WriteStream(stream, buf, 2));
+  return S_OK;
+}
+
+HRESULT CItem::WriteFooter(ISequentialOutStream *stream)
+{
+  Byte buf[8];
+  SetUi32(buf, Crc);
+  SetUi32(buf + 4, Size32);
+  return WriteStream(stream, buf, 8);
+}
+
+class CHandler:
+  public IInArchive,
+  public IArchiveOpenSeq,
+  public IOutArchive,
+  public ISetProperties,
+  public CMyUnknownImp
+{
+  CItem _item;
+  UInt64 _startPosition;
+  UInt64 _headerSize;
+  UInt64 _packSize;
+  bool _packSizeDefined;
+  CMyComPtr<IInStream> _stream;
+  CMyComPtr<ICompressCoder> _decoder;
+  NCompress::NDeflate::NDecoder::CCOMCoder *_decoderSpec;
+
+  CDeflateProps _method;
+
+public:
+  MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)
+  INTERFACE_IInArchive(;)
+  INTERFACE_IOutArchive(;)
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);
+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);
+
+  CHandler()
+  {
+    _decoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder;
+    _decoder = _decoderSpec;
+  }
+};
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMTime, VT_FILETIME},
+  { NULL, kpidHostOS, VT_BSTR},
+  { NULL, kpidCRC, VT_UI4}
+  // { NULL, kpidComment, VT_BSTR}
+}
+;
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_NO_Table
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = 1;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID,  PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidPath:
+      if (_item.NameIsPresent())
+        prop = MultiByteToUnicodeString(_item.Name, CP_ACP);
+      break;
+    // case kpidComment: if (_item.CommentIsPresent()) prop = MultiByteToUnicodeString(_item.Comment, CP_ACP); break;
+    case kpidMTime:
+    {
+      if (_item.Time != 0)
+      {
+        FILETIME utc;
+        NTime::UnixTimeToFileTime(_item.Time, utc);
+        prop = utc;
+      }
+      break;
+    }
+    case kpidSize: if (_stream) prop = (UInt64)_item.Size32; break;
+    case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;
+    case kpidHostOS: prop = (_item.HostOS < sizeof(kHostOSes) / sizeof(kHostOSes[0])) ?
+          kHostOSes[_item.HostOS] : kUnknownOS; break;
+    case kpidCRC: if (_stream) prop = _item.Crc; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *)
+{
+  COM_TRY_BEGIN
+  HRESULT res;
+  try
+  {
+    RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPosition));
+    res = OpenSeq(stream);
+    if (res == S_OK)
+    {
+      UInt64 endPos;
+      res = stream->Seek(-8, STREAM_SEEK_END, &endPos);
+      _packSize = endPos + 8 - _startPosition;
+      _packSizeDefined = true;
+      if (res == S_OK)
+      {
+        res = _item.ReadFooter2(stream);
+        _stream = stream;
+      }
+    }
+  }
+  catch(...) { res = S_FALSE; }
+  if (res != S_OK)
+    Close();
+  return res;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
+{
+  COM_TRY_BEGIN
+  HRESULT res;
+  try
+  {
+    Close();
+    _decoderSpec->SetInStream(stream);
+    _decoderSpec->InitInStream(true);
+    res = _item.ReadHeader(_decoderSpec);
+    _headerSize = _decoderSpec->GetInputProcessedSize();
+  }
+  catch(...) { res = S_FALSE; }
+  if (res != S_OK)
+    Close();
+  return res;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _packSizeDefined = false;
+  _stream.Release();
+  _decoderSpec->ReleaseInStream();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  if (numItems == 0)
+    return S_OK;
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
+    return E_INVALIDARG;
+
+  if (_stream)
+    extractCallback->SetTotal(_packSize);
+  UInt64 currentTotalPacked = 0;
+  RINOK(extractCallback->SetCompleted(&currentTotalPacked));
+  CMyComPtr<ISequentialOutStream> realOutStream;
+  Int32 askMode = testMode ?
+      NExtract::NAskMode::kTest :
+      NExtract::NAskMode::kExtract;
+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
+  if (!testMode && !realOutStream)
+    return S_OK;
+
+  extractCallback->PrepareOperation(askMode);
+
+  COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+  outStreamSpec->SetStream(realOutStream);
+  outStreamSpec->Init();
+  realOutStream.Release();
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, true);
+
+  if (_stream)
+  {
+    RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));
+    _decoderSpec->InitInStream(true);
+  }
+  bool firstItem = true;
+  Int32 opRes;
+  for (;;)
+  {
+    lps->InSize = _packSize = _decoderSpec->GetInputProcessedSize();
+    _packSizeDefined = true;
+    lps->OutSize = outStreamSpec->GetSize();
+    RINOK(lps->SetCur());
+
+    CItem item;
+    if (!firstItem || _stream)
+    {
+      HRESULT result = item.ReadHeader(_decoderSpec);
+      if (result != S_OK)
+      {
+        if (result != S_FALSE)
+          return result;
+        opRes = firstItem ?
+            NExtract::NOperationResult::kDataError :
+            NExtract::NOperationResult::kOK;
+        break;
+      }
+    }
+    firstItem = false;
+
+    UInt64 startOffset = outStreamSpec->GetSize();
+    outStreamSpec->InitCRC();
+
+    HRESULT result = _decoderSpec->CodeResume(outStream, NULL, progress);
+    if (result != S_OK)
+    {
+      if (result != S_FALSE)
+        return result;
+      opRes = NExtract::NOperationResult::kDataError;
+      break;
+    }
+
+    _decoderSpec->AlignToByte();
+    if (item.ReadFooter1(_decoderSpec) != S_OK)
+    {
+      opRes = NExtract::NOperationResult::kDataError;
+      break;
+    }
+    if (item.Crc != outStreamSpec->GetCRC() ||
+        item.Size32 != (UInt32)(outStreamSpec->GetSize() - startOffset))
+    {
+      opRes = NExtract::NOperationResult::kCRCError;
+      break;
+    }
+  }
+  outStream.Release();
+  return extractCallback->SetOperationResult(opRes);
+  COM_TRY_END
+}
+
+static const Byte kHostOS =
+  #ifdef _WIN32
+  NHeader::NHostOS::kFAT;
+  #else
+  NHeader::NHostOS::kUnix;
+  #endif
+
+static HRESULT UpdateArchive(
+    ISequentialOutStream *outStream,
+    UInt64 unpackSize,
+    const CItem &newItem,
+    CDeflateProps &deflateProps,
+    IArchiveUpdateCallback *updateCallback)
+{
+  UInt64 complexity = 0;
+  RINOK(updateCallback->SetTotal(unpackSize));
+  RINOK(updateCallback->SetCompleted(&complexity));
+
+  CMyComPtr<ISequentialInStream> fileInStream;
+
+  RINOK(updateCallback->GetStream(0, &fileInStream));
+
+  CSequentialInStreamWithCRC *inStreamSpec = new CSequentialInStreamWithCRC;
+  CMyComPtr<ISequentialInStream> crcStream(inStreamSpec);
+  inStreamSpec->SetStream(fileInStream);
+  inStreamSpec->Init();
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(updateCallback, true);
+  
+  CItem item = newItem;
+  item.Method = NHeader::NCompressionMethod::kDeflate;
+  item.ExtraFlags = deflateProps.IsMaximum() ?
+      NHeader::NExtraFlags::kMaximum :
+      NHeader::NExtraFlags::kFastest;
+
+  item.HostOS = kHostOS;
+
+  RINOK(item.WriteHeader(outStream));
+
+  NCompress::NDeflate::NEncoder::CCOMCoder *deflateEncoderSpec = new NCompress::NDeflate::NEncoder::CCOMCoder;
+  CMyComPtr<ICompressCoder> deflateEncoder = deflateEncoderSpec;
+  RINOK(deflateProps.SetCoderProperties(deflateEncoderSpec));
+  RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, progress));
+
+  item.Crc = inStreamSpec->GetCRC();
+  item.Size32 = (UInt32)inStreamSpec->GetSize();
+  RINOK(item.WriteFooter(outStream));
+  return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
+}
+
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
+{
+  *timeType = NFileTimeType::kUnix;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+    IArchiveUpdateCallback *updateCallback)
+{
+  if (numItems != 1)
+    return E_INVALIDARG;
+
+  Int32 newData, newProps;
+  UInt32 indexInArchive;
+  if (!updateCallback)
+    return E_FAIL;
+  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));
+
+  CItem newItem = _item;
+  newItem.ExtraFlags = 0;
+  newItem.Flags = 0;
+  if (IntToBool(newProps))
+  {
+    {
+      FILETIME utcTime;
+      NCOM::CPropVariant prop;
+      RINOK(updateCallback->GetProperty(0, kpidMTime, &prop));
+      if (prop.vt != VT_FILETIME)
+        return E_INVALIDARG;
+      utcTime = prop.filetime;
+      if (!NTime::FileTimeToUnixTime(utcTime, newItem.Time))
+        return E_INVALIDARG;
+    }
+    {
+      NCOM::CPropVariant prop;
+      RINOK(updateCallback->GetProperty(0, kpidPath, &prop));
+      if (prop.vt == VT_BSTR)
+      {
+        UString name = prop.bstrVal;
+        int dirDelimiterPos = name.ReverseFind(CHAR_PATH_SEPARATOR);
+        if (dirDelimiterPos >= 0)
+          name = name.Mid(dirDelimiterPos + 1);
+        newItem.Name = UnicodeStringToMultiByte(name, CP_ACP);
+        if (!newItem.Name.IsEmpty())
+          newItem.Flags |= NHeader::NFlags::kName;
+      }
+      else if (prop.vt != VT_EMPTY)
+        return E_INVALIDARG;
+    }
+    {
+      NCOM::CPropVariant prop;
+      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));
+      if (prop.vt == VT_BOOL)
+      {
+        if (prop.boolVal != VARIANT_FALSE)
+          return E_INVALIDARG;
+      }
+      else if (prop.vt != VT_EMPTY)
+        return E_INVALIDARG;
+    }
+  }
+
+  if (IntToBool(newData))
+  {
+    UInt64 size;
+    {
+      NCOM::CPropVariant prop;
+      RINOK(updateCallback->GetProperty(0, kpidSize, &prop));
+      if (prop.vt != VT_UI8)
+        return E_INVALIDARG;
+      size = prop.uhVal.QuadPart;
+    }
+
+    return UpdateArchive(outStream, size, newItem, _method, updateCallback);
+  }
+    
+  if (indexInArchive != 0)
+    return E_INVALIDARG;
+
+  if (!_stream)
+    return E_NOTIMPL;
+
+  UInt64 offset = _startPosition;
+  if (IntToBool(newProps))
+  {
+    newItem.WriteHeader(outStream);
+    offset += _headerSize;
+  }
+  RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL));
+  return NCompress::CopyStream(_stream, outStream, NULL);
+}
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
+{
+  return _method.SetProperties(names, values, numProps);
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+#ifndef EXTRACT_ONLY
+static IOutArchive *CreateArcOut() { return new CHandler; }
+#else
+#define CreateArcOut 0
+#endif
+
+static CArcInfo g_ArcInfo =
+  { L"gzip", L"gz gzip tgz tpz", L"* * .tar .tar", 0xEF, { 0x1F, 0x8B, 8 }, 3, true, CreateArc, CreateArcOut };
+
+REGISTER_ARC(GZip)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,243 @@
+// HfsHandler.cpp
+
+#include "StdAfx.h"
+
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "../../Common/StreamUtils.h"
+#include "HfsHandler.h"
+
+namespace NArchive {
+namespace NHfs {
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidIsDir, VT_BOOL},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidCTime, VT_FILETIME},
+  { NULL, kpidMTime, VT_FILETIME},
+  { NULL, kpidATime, VT_FILETIME}
+};
+
+STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidMethod, VT_BSTR},
+  { NULL, kpidClusterSize, VT_UI4},
+  { NULL, kpidFreeSpace, VT_UI8},
+  { NULL, kpidCTime, VT_FILETIME},
+  { NULL, kpidMTime, VT_FILETIME}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+static void HfsTimeToProp(UInt32 hfsTime, NWindows::NCOM::CPropVariant &prop)
+{
+  FILETIME ft;
+  HfsTimeToFileTime(hfsTime, ft);
+  prop = ft;
+}
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidMethod: prop = _db.Header.IsHfsX() ? L"HFSX" : L"HFS+"; break;
+    case kpidClusterSize: prop = (UInt32)1 << _db.Header.BlockSizeLog; break;
+    case kpidFreeSpace: prop = (UInt64)_db.Header.NumFreeBlocks << _db.Header.BlockSizeLog; break;
+    case kpidMTime: HfsTimeToProp(_db.Header.MTime, prop); break;
+    case kpidCTime:
+    {
+      FILETIME localFt, ft;
+      HfsTimeToFileTime(_db.Header.CTime, localFt);
+      if (LocalFileTimeToFileTime(&localFt, &ft))
+        prop = ft;
+      break;
+    }
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  const CItem &item = _db.Items[index];
+  switch(propID)
+  {
+    case kpidPath: prop = _db.GetItemPath(index); break;
+    case kpidIsDir: prop = item.IsDir(); break;
+
+    case kpidCTime:  HfsTimeToProp(item.CTime, prop); break;
+    case kpidMTime:  HfsTimeToProp(item.MTime, prop); break;
+    case kpidATime:  HfsTimeToProp(item.ATime, prop); break;
+
+    case kpidPackSize: if (!item.IsDir()) prop = (UInt64)item.NumBlocks << _db.Header.BlockSizeLog; break;
+    case kpidSize:     if (!item.IsDir()) prop = item.Size; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+class CProgressImp: public CProgressVirt
+{
+  CMyComPtr<IArchiveOpenCallback> _callback;
+public:
+  HRESULT SetTotal(UInt64 numFiles);
+  HRESULT SetCompleted(UInt64 numFiles);
+  CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {}
+};
+
+HRESULT CProgressImp::SetTotal(UInt64 numFiles)
+{
+  if (_callback)
+    return _callback->SetTotal(&numFiles, NULL);
+  return S_OK;
+}
+
+HRESULT CProgressImp::SetCompleted(UInt64 numFiles)
+{
+  if (_callback)
+    return _callback->SetCompleted(&numFiles, NULL);
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *inStream,
+    const UInt64 * /* maxCheckStartPosition */,
+    IArchiveOpenCallback *callback)
+{
+  COM_TRY_BEGIN
+  Close();
+  try
+  {
+    CProgressImp progressImp(callback);
+    HRESULT res = _db.Open(inStream, &progressImp);
+    if (res == E_ABORT)
+      return res;
+    if (res != S_OK)
+      return S_FALSE;
+    _stream = inStream;
+  }
+  catch(...) { return S_FALSE; }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _stream.Release();
+  _db.Clear();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _db.Items.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt32 i;
+  UInt64 totalSize = 0;
+  for (i = 0; i < numItems; i++)
+  {
+    const CItem &item = _db.Items[allFilesMode ? i : indices[i]];
+    if (!item.IsDir())
+      totalSize += item.Size;
+  }
+  RINOK(extractCallback->SetTotal(totalSize));
+
+  UInt64 currentTotalSize = 0, currentItemSize = 0;
+  
+  CByteBuffer buf;
+  const UInt32 kBufSize = (1 << 16);
+  buf.SetCapacity(kBufSize);
+
+  for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
+  {
+    RINOK(extractCallback->SetCompleted(&currentTotalSize));
+    Int32 index = allFilesMode ? i : indices[i];
+    const CItem &item = _db.Items[index];
+    currentItemSize = 0;
+    if (!item.IsDir())
+      currentItemSize = item.Size;
+
+    CMyComPtr<ISequentialOutStream> realOutStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+    if (item.IsDir())
+    {
+      RINOK(extractCallback->PrepareOperation(askMode));
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+      continue;
+    }
+    if (!testMode && !realOutStream)
+      continue;
+    RINOK(extractCallback->PrepareOperation(askMode));
+    UInt64 pos = 0;
+    int res = NExtract::NOperationResult::kOK;
+    int i;
+    for (i = 0; i < item.Extents.Size(); i++)
+    {
+      if (item.Size == pos)
+        break;
+      if (res != NExtract::NOperationResult::kOK)
+        break;
+      const CExtent &e = item.Extents[i];
+      RINOK(_stream->Seek((UInt64)e.Pos << _db.Header.BlockSizeLog, STREAM_SEEK_SET, NULL));
+      UInt64 extentSize = (UInt64)e.NumBlocks << _db.Header.BlockSizeLog;
+      for (;;)
+      {
+        if (extentSize == 0)
+          break;
+        UInt64 rem = item.Size - pos;
+        if (rem == 0)
+        {
+          if (extentSize >= (UInt64)((UInt32)1 << _db.Header.BlockSizeLog))
+            res = NExtract::NOperationResult::kDataError;
+          break;
+        }
+        UInt32 curSize = kBufSize;
+        if (curSize > rem)
+          curSize = (UInt32)rem;
+        if (curSize > extentSize)
+          curSize = (UInt32)extentSize;
+        RINOK(ReadStream_FALSE(_stream, buf, curSize));
+        if (realOutStream)
+        {
+          RINOK(WriteStream(realOutStream, buf, curSize));
+        }
+        pos += curSize;
+        extentSize -= curSize;
+        UInt64 processed = currentTotalSize + pos;
+        RINOK(extractCallback->SetCompleted(&processed));
+      }
+    }
+    if (i != item.Extents.Size() || item.Size != pos)
+      res = NExtract::NOperationResult::kDataError;
+    realOutStream.Release();
+    RINOK(extractCallback->SetOperationResult(res));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _db.Items.Size();
+  return S_OK;
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsHandler.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsHandler.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsHandler.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsHandler.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,26 @@
+// HfsHandler.h
+
+#ifndef __ARCHIVE_HFS_HANDLER_H
+#define __ARCHIVE_HFS_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+#include "HfsIn.h"
+
+namespace NArchive {
+namespace NHfs {
+
+class CHandler:
+  public IInArchive,
+  public CMyUnknownImp
+{
+  CMyComPtr<IInStream> _stream;
+  CDatabase _db;
+public:
+  MY_UNKNOWN_IMP1(IInArchive)
+  INTERFACE_IInArchive(;)
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsIn.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsIn.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsIn.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsIn.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,480 @@
+// HfsIn.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/StreamUtils.h"
+#include "Common/IntToString.h"
+
+#include "HfsIn.h"
+
+#include "../../../../C/CpuArch.h"
+
+#define Get16(p) GetBe16(p)
+#define Get32(p) GetBe32(p)
+#define Get64(p) GetBe64(p)
+
+namespace NArchive {
+namespace NHfs {
+
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+
+static int CompareIdToIndex(const CIdIndexPair *p1, const CIdIndexPair *p2, void * /* param */)
+{
+  RINOZ(MyCompare(p1->ID, p2->ID));
+  return MyCompare(p1->Index, p2->Index);
+}
+
+bool operator< (const CIdIndexPair &a1, const CIdIndexPair &a2) { return (a1.ID  < a2.ID); }
+bool operator> (const CIdIndexPair &a1, const CIdIndexPair &a2) { return (a1.ID  > a2.ID); }
+bool operator==(const CIdIndexPair &a1, const CIdIndexPair &a2) { return (a1.ID == a2.ID); }
+bool operator!=(const CIdIndexPair &a1, const CIdIndexPair &a2) { return (a1.ID != a2.ID); }
+
+static UString GetSpecName(const UString &name, UInt32 /* id */)
+{
+  UString name2 = name;
+  name2.Trim();
+  if (name2.IsEmpty())
+  {
+    /*
+    wchar_t s[32];
+    ConvertUInt64ToString(id, s);
+    return L"[" + (UString)s + L"]";
+    */
+    return L"[]";
+  }
+  return name;
+}
+
+UString CDatabase::GetItemPath(int index) const
+{
+  const CItem *item = &Items[index];
+  UString name = GetSpecName(item->Name, item->ID);
+
+  for (int i = 0; i < 1000; i++)
+  {
+    if (item->ParentID < 16 && item->ParentID != 2)
+    {
+      if (item->ParentID != 1)
+        break;
+      return name;
+    }
+    CIdIndexPair pair;
+    pair.ID = item->ParentID;
+    pair.Index = 0;
+    int indexInMap = IdToIndexMap.FindInSorted(pair);
+    if (indexInMap < 0)
+      break;
+    item = &Items[IdToIndexMap[indexInMap].Index];
+    name = GetSpecName(item->Name, item->ID) + WCHAR_PATH_SEPARATOR + name;
+  }
+  return (UString)L"Unknown" + WCHAR_PATH_SEPARATOR + name;
+}
+
+void CFork::Parse(const Byte *p)
+{
+  Size = Get64(p);
+  // ClumpSize = Get32(p + 8);
+  NumBlocks = Get32(p + 0xC);
+  for (int i = 0; i < 8; i++)
+  {
+    CExtent &e = Extents[i];
+    e.Pos = Get32(p + 0x10 + i * 8);
+    e.NumBlocks = Get32(p + 0x10 + i * 8 + 4);
+  }
+}
+
+static HRESULT ReadExtent(int blockSizeLog, IInStream *inStream, Byte *buf, const CExtent &e)
+{
+  RINOK(inStream->Seek((UInt64)e.Pos << blockSizeLog, STREAM_SEEK_SET, NULL));
+  return ReadStream_FALSE(inStream, buf, (size_t)e.NumBlocks << blockSizeLog);
+}
+
+HRESULT CDatabase::ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inStream)
+{
+  if (fork.NumBlocks >= Header.NumBlocks)
+    return S_FALSE;
+  size_t totalSize = (size_t)fork.NumBlocks << Header.BlockSizeLog;
+  if ((totalSize >> Header.BlockSizeLog) != fork.NumBlocks)
+    return S_FALSE;
+  buf.SetCapacity(totalSize);
+  UInt32 curBlock = 0;
+  for (int i = 0; i < 8; i++)
+  {
+    if (curBlock >= fork.NumBlocks)
+      break;
+    const CExtent &e = fork.Extents[i];
+    if (fork.NumBlocks - curBlock < e.NumBlocks || e.Pos >= Header.NumBlocks)
+      return S_FALSE;
+    RINOK(ReadExtent(Header.BlockSizeLog, inStream,
+        (Byte *)buf + ((size_t)curBlock << Header.BlockSizeLog), e));
+    curBlock += e.NumBlocks;
+  }
+  return S_OK;
+}
+
+struct CNodeDescriptor
+{
+  UInt32 fLink;
+  UInt32 bLink;
+  Byte Kind;
+  Byte Height;
+  UInt16 NumRecords;
+  // UInt16 Reserved;
+  void Parse(const Byte *p);
+};
+
+void CNodeDescriptor::Parse(const Byte *p)
+{
+  fLink = Get32(p);
+  bLink = Get32(p + 4);
+  Kind = p[8];
+  Height = p[9];
+  NumRecords = Get16(p + 10);
+}
+
+struct CHeaderRec
+{
+  // UInt16 TreeDepth;
+  // UInt32 RootNode;
+  // UInt32 LeafRecords;
+  UInt32 FirstLeafNode;
+  // UInt32 LastLeafNode;
+  int NodeSizeLog;
+  // UInt16 MaxKeyLength;
+  UInt32 TotalNodes;
+  // UInt32 FreeNodes;
+  // UInt16 Reserved1;
+  // UInt32 ClumpSize;
+  // Byte BtreeType;
+  // Byte KeyCompareType;
+  // UInt32 Attributes;
+  // UInt32 Reserved3[16];
+  
+  HRESULT Parse(const Byte *p);
+};
+
+HRESULT CHeaderRec::Parse(const Byte *p)
+{
+  // TreeDepth = Get16(p);
+  // RootNode = Get32(p + 2);
+  // LeafRecords = Get32(p + 6);
+  FirstLeafNode = Get32(p + 0xA);
+  // LastLeafNode = Get32(p + 0xE);
+  UInt32 nodeSize = Get16(p + 0x12);
+
+  int i;
+  for (i = 9; ((UInt32)1 << i) != nodeSize; i++)
+    if (i == 16)
+      return S_FALSE;
+  NodeSizeLog = i;
+
+  // MaxKeyLength = Get16(p + 0x14);
+  TotalNodes = Get32(p + 0x16);
+  // FreeNodes = Get32(p + 0x1A);
+  // Reserved1 = Get16(p + 0x1E);
+  // ClumpSize = Get32(p + 0x20);
+  // BtreeType = p[0x24];
+  // KeyCompareType = p[0x25];
+  // Attributes = Get32(p + 0x26);
+  /*
+  for (int i = 0; i < 16; i++)
+    Reserved3[i] = Get32(p + 0x2A + i * 4);
+  */
+  return S_OK;
+}
+
+
+enum ENodeType
+{
+  NODE_TYPE_LEAF = 0xFF,
+  NODE_TYPE_INDEX = 0,
+  NODE_TYPE_HEADER = 1,
+  NODE_TYPE_MODE = 2
+};
+
+HRESULT CDatabase::LoadExtentFile(IInStream *inStream)
+{
+  // FileExtents.Clear();
+  // ResExtents.Clear();
+
+  CByteBuffer extents;
+  RINOK(ReadFile(Header.ExtentsFile, extents, inStream));
+
+  const Byte *p = (const Byte *)extents;
+
+  // CNodeDescriptor nodeDesc;
+  // nodeDesc.Parse(p);
+  CHeaderRec hr;
+  RINOK(hr.Parse(p + 14));
+
+  UInt32 node = hr.FirstLeafNode;
+  if (node != 0)
+    return S_FALSE;
+  /*
+  while (node != 0)
+  {
+    size_t nodeOffset = node * hr.NodeSize;
+    if ((node + 1)* hr.NodeSize > CatalogBuf.GetCapacity())
+      return S_FALSE;
+    CNodeDescriptor desc;
+    desc.Parse(p + nodeOffset);
+    if (desc.Kind != NODE_TYPE_LEAF)
+      return S_FALSE;
+    UInt32 ptr = hr.NodeSize;
+    for (int i = 0; i < desc.NumRecords; i++)
+    {
+      UInt32 offs = Get16(p + nodeOffset + hr.NodeSize - (i + 1) * 2);
+      UInt32 offsNext = Get16(p + nodeOffset + hr.NodeSize - (i + 2) * 2);
+
+      const Byte *r = p + nodeOffset + offs;
+      int keyLength = Get16(r);
+      Byte forkType = r[2];
+      UInt32 id = Get16(r + 4);
+      UInt32 startBlock = Get16(r + 4);
+      CObjectVector<CIdExtents> *extents = (forkType == 0) ? &FileExtents : &ResExtents;
+      if (extents->Size() == 0)
+        extents->Add(CIdExtents());
+      else
+      {
+        CIdExtents &e = extents->Back();
+        if (e.ID != id)
+        {
+          if (e.ID > id)
+            return S_FALSE;
+          extents->Add(CIdExtents());
+        }
+      }
+      CIdExtents &e = extents->Back();
+      for (UInt32 k = offs + 10 + 2; k + 8 <= offsNext; k += 8)
+      {
+        CExtent ee;
+        ee.Pos = Get32(p + nodeOffset + k);
+        ee.NumBlocks  = Get32(p + nodeOffset + k * 4);
+        e.Extents.Add(ee);
+      }
+    }
+    node = desc.fLink;
+  }
+  */
+  return S_OK;
+}
+
+
+HRESULT CDatabase::LoadCatalog(IInStream *inStream, CProgressVirt *progress)
+{
+  Items.Clear();
+  IdToIndexMap.ClearAndFree();
+
+  CByteBuffer catalogBuf;
+  RINOK(ReadFile(Header.CatalogFile, catalogBuf, inStream));
+  const Byte *p = (const Byte *)catalogBuf;
+
+  // CNodeDescriptor nodeDesc;
+  // nodeDesc.Parse(p);
+  CHeaderRec hr;
+  hr.Parse(p + 14);
+  
+  // CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC);
+
+  if ((catalogBuf.GetCapacity() >> hr.NodeSizeLog) < hr.TotalNodes)
+    return S_FALSE;
+
+  CByteBuffer usedBuf;
+  usedBuf.SetCapacity(hr.TotalNodes);
+  for (UInt32 i = 0; i < hr.TotalNodes; i++)
+    usedBuf[i] = 0;
+
+  UInt32 node = hr.FirstLeafNode;
+  while (node != 0)
+  {
+    if (node >= hr.TotalNodes)
+      return S_FALSE;
+    if (usedBuf[node])
+      return S_FALSE;
+    usedBuf[node] = 1;
+    size_t nodeOffset = (size_t)node << hr.NodeSizeLog;
+    CNodeDescriptor desc;
+    desc.Parse(p + nodeOffset);
+    if (desc.Kind != NODE_TYPE_LEAF)
+      return S_FALSE;
+    for (int i = 0; i < desc.NumRecords; i++)
+    {
+      UInt32 nodeSize = (1 << hr.NodeSizeLog);
+      UInt32 offs = Get16(p + nodeOffset + nodeSize - (i + 1) * 2);
+      UInt32 offsNext = Get16(p + nodeOffset + nodeSize - (i + 2) * 2);
+      UInt32 recSize = offsNext - offs;
+      if (offsNext >= nodeSize || offsNext < offs || recSize < 6)
+        return S_FALSE;
+
+      CItem item;
+
+      const Byte *r = p + nodeOffset + offs;
+      UInt32 keyLength = Get16(r);
+      item.ParentID = Get32(r + 2);
+      UString name;
+      if (keyLength < 6 || (keyLength & 1) != 0 || keyLength + 2 > recSize)
+        return S_FALSE;
+      r += 6;
+      recSize -= 6;
+      keyLength -= 6;
+      
+      int nameLength = Get16(r);
+      if (nameLength * 2 != (int)keyLength)
+        return S_FALSE;
+      r += 2;
+      recSize -= 2;
+     
+      wchar_t *pp = name.GetBuffer(nameLength + 1);
+      
+      int j;
+      for (j = 0; j < nameLength; j++)
+        pp[j] = ((wchar_t)r[j * 2] << 8) | r[j * 2 + 1];
+      pp[j] = 0;
+      name.ReleaseBuffer();
+      r += j * 2;
+      recSize -= j * 2;
+
+      if (recSize < 2)
+        return S_FALSE;
+      item.Type = Get16(r);
+
+      if (item.Type != RECORD_TYPE_FOLDER && item.Type != RECORD_TYPE_FILE)
+        continue;
+      if (recSize < 0x58)
+        return S_FALSE;
+
+      // item.Flags = Get16(r + 2);
+      // item.Valence = Get32(r + 4);
+      item.ID = Get32(r + 8);
+      item.CTime = Get32(r + 0xC);
+      item.MTime = Get32(r + 0x10);
+      // item.AttrMTime = Get32(r + 0x14);
+      item.ATime = Get32(r + 0x18);
+      // item.BackupDate = Get32(r + 0x1C);
+      
+      /*
+      item.OwnerID = Get32(r + 0x20);
+      item.GroupID = Get32(r + 0x24);
+      item.AdminFlags = r[0x28];
+      item.OwnerFlags = r[0x29];
+      item.FileMode = Get16(r + 0x2A);
+      item.special.iNodeNum = Get16(r + 0x2C);
+      */
+
+      item.Name = name;
+
+      if (item.IsDir())
+      {
+        CIdIndexPair pair;
+        pair.ID = item.ID;
+        pair.Index = Items.Size();
+        IdToIndexMap.Add(pair);
+      }
+      else
+      {
+        CFork fd;
+        recSize -= 0x58;
+        r += 0x58;
+        if (recSize < 0x50 * 2)
+          return S_FALSE;
+        fd.Parse(r);
+        item.Size = fd.Size;
+        item.NumBlocks = fd.NumBlocks;
+        UInt32 curBlock = 0;
+        for (int j = 0; j < 8; j++)
+        {
+          if (curBlock >= fd.NumBlocks)
+            break;
+          const CExtent &e = fd.Extents[j];
+          item.Extents.Add(e);
+          curBlock += e.NumBlocks;
+        }
+      }
+      Items.Add(item);
+      if (progress && Items.Size() % 100 == 0)
+      {
+        RINOK(progress->SetCompleted(Items.Size()));
+      }
+    }
+    node = desc.fLink;
+  }
+  IdToIndexMap.Sort(CompareIdToIndex, NULL);
+  return S_OK;
+}
+
+HRESULT CDatabase::Open(IInStream *inStream, CProgressVirt *progress)
+{
+  static const UInt32 kHeaderSize = 1024 + 512;
+  Byte buf[kHeaderSize];
+  RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize));
+  int i;
+  for (i = 0; i < 1024; i++)
+    if (buf[i] != 0)
+      return S_FALSE;
+  const Byte *p = buf + 1024;
+  CVolHeader &h = Header;
+
+  h.Header[0] = p[0];
+  h.Header[1] = p[1];
+  if (p[0] != 'H' || (p[1] != '+' && p[1] != 'X'))
+    return S_FALSE;
+  h.Version = Get16(p + 2);
+  if (h.Version < 4 || h.Version > 5)
+    return S_FALSE;
+
+  // h.Attr = Get32(p + 4);
+  // h.LastMountedVersion = Get32(p + 8);
+  // h.JournalInfoBlock = Get32(p + 0xC);
+
+  h.CTime = Get32(p + 0x10);
+  h.MTime = Get32(p + 0x14);
+  // h.BackupTime = Get32(p + 0x18);
+  // h.CheckedTime = Get32(p + 0x1C);
+
+  // h.NumFiles = Get32(p + 0x20);
+  // h.NumFolders = Get32(p + 0x24);
+  
+  UInt32 numFiles = Get32(p + 0x20);
+  UInt32 numFolders = Get32(p + 0x24);;
+  if (progress)
+  {
+    RINOK(progress->SetTotal(numFolders + numFiles));
+  }
+
+  UInt32 blockSize = Get32(p + 0x28);
+
+  for (i = 9; ((UInt32)1 << i) != blockSize; i++)
+    if (i == 31)
+      return S_FALSE;
+  h.BlockSizeLog = i;
+
+  h.NumBlocks = Get32(p + 0x2C);
+  h.NumFreeBlocks = Get32(p + 0x30);
+
+  /*
+  h.WriteCount = Get32(p + 0x44);
+  for (i = 0; i < 6; i++)
+    h.FinderInfo[i] = Get32(p + 0x50 + i * 4);
+  h.VolID = Get64(p + 0x68);
+  */
+
+  UInt64 endPos;
+  RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos));
+  if ((endPos >> h.BlockSizeLog) < h.NumBlocks)
+    return S_FALSE;
+
+  // h.AllocationFile.Parse(p + 0x70 + 0x50 * 0);
+  h.ExtentsFile.Parse(   p + 0x70 + 0x50 * 1);
+  h.CatalogFile.Parse(   p + 0x70 + 0x50 * 2);
+  // h.AttributesFile.Parse(p + 0x70 + 0x50 * 3);
+  // h.StartupFile.Parse(   p + 0x70 + 0x50 * 4);
+
+  RINOK(LoadExtentFile(inStream));
+  RINOK(LoadCatalog(inStream, progress));
+
+  // if (Header.NumFiles + Header.NumFolders != (UInt32)Items.Size()) return S_OK;
+
+  return S_OK;
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsIn.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsIn.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsIn.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsIn.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,154 @@
+// HfsIn.h
+
+#ifndef __ARCHIVE_HFS_IN_H
+#define __ARCHIVE_HFS_IN_H
+
+#include "Common/MyString.h"
+#include "Common/Buffer.h"
+
+namespace NArchive {
+namespace NHfs {
+
+struct CExtent
+{
+  UInt32 Pos;
+  UInt32 NumBlocks;
+};
+
+struct CFork
+{
+  UInt64 Size;
+  // UInt32 ClumpSize;
+  UInt32 NumBlocks;
+  CExtent Extents[8];
+  void Parse(const Byte *p);
+};
+
+struct CVolHeader
+{
+  Byte Header[2];
+  UInt16 Version;
+  // UInt32 Attr;
+  // UInt32 LastMountedVersion;
+  // UInt32 JournalInfoBlock;
+
+  UInt32 CTime;
+  UInt32 MTime;
+  // UInt32 BackupTime;
+  // UInt32 CheckedTime;
+  
+  // UInt32 NumFiles;
+  // UInt32 NumFolders;
+  int BlockSizeLog;
+  UInt32 NumBlocks;
+  UInt32 NumFreeBlocks;
+
+  // UInt32 WriteCount;
+  // UInt32 FinderInfo[8];
+  // UInt64 VolID;
+
+  // CFork AllocationFile;
+  CFork ExtentsFile;
+  CFork CatalogFile;
+  // CFork AttributesFile;
+  // CFork StartupFile;
+
+  bool IsHfsX() const { return Version > 4; }
+};
+
+inline void HfsTimeToFileTime(UInt32 hfsTime, FILETIME &ft)
+{
+  UInt64 v = ((UInt64)3600 * 24 * (365 * 303 + 24 * 3) + hfsTime) * 10000000;
+  ft.dwLowDateTime = (DWORD)v;
+  ft.dwHighDateTime = (DWORD)(v >> 32);
+}
+
+enum ERecordType
+{
+  RECORD_TYPE_FOLDER = 1,
+  RECORD_TYPE_FILE = 2,
+  RECORD_TYPE_FOLDER_THREAD = 3,
+  RECORD_TYPE_FILE_THREAD = 4
+};
+
+struct CItem
+{
+  UString Name;
+  
+  UInt32 ParentID;
+
+  UInt16 Type;
+  // UInt16 Flags;
+  // UInt32 Valence;
+  UInt32 ID;
+  UInt32 CTime;
+  UInt32 MTime;
+  // UInt32 AttrMTime;
+  UInt32 ATime;
+  // UInt32 BackupDate;
+
+  /*
+  UInt32 OwnerID;
+  UInt32 GroupID;
+  Byte AdminFlags;
+  Byte OwnerFlags;
+  UInt16 FileMode;
+  union
+  {
+    UInt32  iNodeNum;
+    UInt32  LinkCount;
+    UInt32  RawDevice;
+  } special;
+  */
+
+  UInt64 Size;
+  UInt32 NumBlocks;
+  CRecordVector<CExtent> Extents;
+
+  bool IsDir() const { return Type == RECORD_TYPE_FOLDER; }
+  CItem(): Size(0), NumBlocks(0) {}
+};
+
+struct CIdIndexPair
+{
+  UInt32 ID;
+  int Index;
+};
+
+struct CProgressVirt
+{
+  virtual HRESULT SetTotal(UInt64 numFiles) PURE;
+  virtual HRESULT SetCompleted(UInt64 numFiles) PURE;
+};
+
+class CDatabase
+{
+  // CObjectVector<CIdExtents> FileExtents;
+  // CObjectVector<CIdExtents> ResExtents;
+  CRecordVector<CIdIndexPair> IdToIndexMap;
+
+  HRESULT LoadExtentFile(IInStream *inStream);
+  HRESULT LoadCatalog(IInStream *inStream, CProgressVirt *progress);
+
+  HRESULT ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inStream);
+public:
+  CVolHeader Header;
+  CObjectVector<CItem> Items;
+  // bool CaseSensetive;
+
+  void Clear()
+  {
+    // CaseSensetive = false;
+    Items.Clear();
+    // FileExtents.Clear();
+    // ResExtents.Clear();
+    IdToIndexMap.Clear();
+  }
+
+  UString GetItemPath(int index) const;
+  HRESULT Open(IInStream *inStream, CProgressVirt *progress);
+};
+
+}}
+  
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsRegister.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsRegister.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsRegister.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Hfs/HfsRegister.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,13 @@
+// HfsRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterArc.h"
+
+#include "HfsHandler.h"
+static IInArchive *CreateArc() { return new NArchive::NHfs::CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"HFS", L"hfs", 0, 0xE3, { 'H', '+', 0, 4 }, 4, false, CreateArc, 0 };
+
+REGISTER_ARC(Hfs)

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/IArchive.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/IArchive.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/IArchive.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/IArchive.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,234 @@
+// IArchive.h
+
+#ifndef __IARCHIVE_H
+#define __IARCHIVE_H
+
+#include "../IProgress.h"
+#include "../IStream.h"
+#include "../PropID.h"
+
+#define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x)
+#define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x)
+
+namespace NFileTimeType
+{
+  enum EEnum
+  {
+    kWindows,
+    kUnix,
+    kDOS
+  };
+}
+
+namespace NArchive
+{
+  enum
+  {
+    kName = 0,
+    kClassID,
+    kExtension,
+    kAddExtension,
+    kUpdate,
+    kKeepName,
+    kStartSignature,
+    kFinishSignature,
+    kAssociate
+  };
+
+  namespace NExtract
+  {
+    namespace NAskMode
+    {
+      enum
+      {
+        kExtract = 0,
+        kTest,
+        kSkip
+      };
+    }
+    namespace NOperationResult
+    {
+      enum
+      {
+        kOK = 0,
+        kUnSupportedMethod,
+        kDataError,
+        kCRCError
+      };
+    }
+  }
+  namespace NUpdate
+  {
+    namespace NOperationResult
+    {
+      enum
+      {
+        kOK = 0,
+        kError
+      };
+    }
+  }
+}
+
+#define INTERFACE_IArchiveOpenCallback(x) \
+  STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \
+  STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \
+
+ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10)
+{
+  INTERFACE_IArchiveOpenCallback(PURE);
+};
+
+
+#define INTERFACE_IArchiveExtractCallback(x) \
+  INTERFACE_IProgress(x) \
+  STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream,  Int32 askExtractMode) x; \
+  STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \
+  STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \
+
+ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)
+{
+  INTERFACE_IArchiveExtractCallback(PURE)
+};
+
+
+#define INTERFACE_IArchiveOpenVolumeCallback(x) \
+  STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \
+  STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \
+
+ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30)
+{
+  INTERFACE_IArchiveOpenVolumeCallback(PURE);
+};
+
+
+ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40)
+{
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE;
+};
+
+
+ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50)
+{
+  STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE;
+};
+
+
+/*
+IInArchive::Extract:
+  indices must be sorted
+  numItems = 0xFFFFFFFF means "all files"
+  testMode != 0 means "test files without writing to outStream"
+*/
+
+#define INTERFACE_IInArchive(x) \
+  STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \
+  STDMETHOD(Close)() x; \
+  STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \
+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
+  STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \
+  STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \
+  STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \
+  STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
+  STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \
+  STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x;
+
+ARCHIVE_INTERFACE(IInArchive, 0x60)
+{
+  INTERFACE_IInArchive(PURE)
+};
+
+ARCHIVE_INTERFACE(IArchiveOpenSeq, 0x61)
+{
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE;
+};
+
+#define INTERFACE_IArchiveUpdateCallback(x) \
+  INTERFACE_IProgress(x); \
+  STDMETHOD(GetUpdateItemInfo)(UInt32 index,  \
+      Int32 *newData, /*1 - new data, 0 - old data */ \
+      Int32 *newProperties, /* 1 - new properties, 0 - old properties */ \
+      UInt32 *indexInArchive /* -1 if there is no in archive, or if doesn't matter */ \
+      )  x; \
+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \
+  STDMETHOD(SetOperationResult)(Int32 operationResult) x; \
+
+ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80)
+{
+  INTERFACE_IArchiveUpdateCallback(PURE);
+};
+
+#define INTERFACE_IArchiveUpdateCallback2(x) \
+  INTERFACE_IArchiveUpdateCallback(x) \
+  STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \
+  STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \
+
+ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82)
+{
+  INTERFACE_IArchiveUpdateCallback2(PURE);
+};
+
+
+#define INTERFACE_IOutArchive(x) \
+  STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \
+  STDMETHOD(GetFileTimeType)(UInt32 *type) x;
+
+ARCHIVE_INTERFACE(IOutArchive, 0xA0)
+{
+  INTERFACE_IOutArchive(PURE)
+};
+
+
+ARCHIVE_INTERFACE(ISetProperties, 0x03)
+{
+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE;
+};
+
+
+#define IMP_IInArchive_GetProp(k) \
+  (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
+    { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \
+    const STATPROPSTG &srcItem = k[index]; \
+    *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \
+
+#define IMP_IInArchive_GetProp_WITH_NAME(k) \
+  (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
+    { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \
+    const STATPROPSTG &srcItem = k[index]; \
+    *propID = srcItem.propid; *varType = srcItem.vt; \
+    if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \
+
+#define IMP_IInArchive_Props \
+  STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \
+    { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \
+  STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps)
+
+#define IMP_IInArchive_Props_WITH_NAME \
+  STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \
+    { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \
+  STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps)
+
+
+#define IMP_IInArchive_ArcProps \
+  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \
+    { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \
+  STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps)
+
+#define IMP_IInArchive_ArcProps_WITH_NAME \
+  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \
+    { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \
+  STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps)
+
+#define IMP_IInArchive_ArcProps_NO_Table \
+  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \
+    { *numProperties = 0; return S_OK; } \
+  STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \
+    { return E_NOTIMPL; } \
+
+#define IMP_IInArchive_ArcProps_NO \
+  IMP_IInArchive_ArcProps_NO_Table \
+  STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \
+    { value->vt = VT_EMPTY; return S_OK; }
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,326 @@
+// IsoHandler.cpp
+
+#include "StdAfx.h"
+
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/ProgressUtils.h"
+
+#include "../../Compress/CopyCoder.h"
+
+#include "../Common/ItemNameUtils.h"
+
+#include "IsoHandler.h"
+
+using namespace NWindows;
+using namespace NTime;
+
+namespace NArchive {
+namespace NIso {
+
+static const STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidIsDir, VT_BOOL},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMTime, VT_FILETIME}
+};
+
+static const STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidComment, VT_BSTR},
+  { NULL, kpidCTime, VT_FILETIME},
+  { NULL, kpidMTime, VT_FILETIME}
+  // { NULL, kpidPhySize, VT_UI8},
+  // { NULL, kpidHeadersSize, VT_UI8}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+    const UInt64 * /* maxCheckStartPosition */,
+    IArchiveOpenCallback * /* openArchiveCallback */)
+{
+  COM_TRY_BEGIN
+  Close();
+  // try
+  {
+    if (_archive.Open(stream) != S_OK)
+      return S_FALSE;
+    _stream = stream;
+  }
+  // catch(...) { return S_FALSE; }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _archive.Clear();
+  _stream.Release();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _archive.Refs.Size() + _archive.BootEntries.Size();
+  return S_OK;
+}
+
+static void AddString(AString &s, const char *name, const Byte *p, int size)
+{
+  int i;
+  for (i = 0; i < size && p[i]; i++);
+  for (; i > 0 && p[i - 1] == ' '; i--);
+  if (i != 0)
+  {
+    AString d;
+    memcpy(d.GetBuffer(i), p, i);
+    d.ReleaseBuffer(i);
+    s += '\n';
+    s += name;
+    s += ": ";
+    s += d;
+  }
+}
+
+#define ADD_STRING(n, V) AddString(s, n, vol. V, sizeof(vol. V))
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  const CVolumeDescriptor &vol = _archive.VolDescs[_archive.MainVolDescIndex];
+  switch(propID)
+  {
+    case kpidComment:
+    {
+      AString s;
+      ADD_STRING("System", SystemId);
+      ADD_STRING("Volume", VolumeId);
+      ADD_STRING("VolumeSet", VolumeSetId);
+      ADD_STRING("Publisher", PublisherId);
+      ADD_STRING("Preparer", DataPreparerId);
+      ADD_STRING("Application", ApplicationId);
+      ADD_STRING("Copyright", CopyrightFileId);
+      ADD_STRING("Abstract", AbstractFileId);
+      ADD_STRING("Bib", BibFileId);
+      prop = s;
+      break;
+    }
+    case kpidCTime: { FILETIME utc; if (vol.CTime.GetFileTime(utc)) prop = utc; break; }
+    case kpidMTime: { FILETIME utc; if (vol.MTime.GetFileTime(utc)) prop = utc; break; }
+    // case kpidPhySize: break;
+    // case kpidHeadersSize: break;
+    case kpidError: if (_archive.IncorrectBigEndian) prop = "Incorrect big-endian headers"; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  if (index >= (UInt32)_archive.Refs.Size())
+  {
+    index -= _archive.Refs.Size();
+    const CBootInitialEntry &be = _archive.BootEntries[index];
+    switch(propID)
+    {
+      case kpidPath:
+      {
+        // wchar_t name[32];
+        // ConvertUInt64ToString(index + 1, name);
+        UString s = L"[BOOT]" WSTRING_PATH_SEPARATOR;
+        // s += name;
+        // s += L"-";
+        s += be.GetName();
+        prop = (const wchar_t *)s;
+        break;
+      }
+      case kpidIsDir: prop = false; break;
+      case kpidSize:
+      case kpidPackSize:
+        prop = (UInt64)_archive.GetBootItemSize(index);
+        break;
+    }
+  }
+  else
+  {
+    const CRef &ref = _archive.Refs[index];
+    const CDir &item = ref.Dir->_subItems[ref.Index];
+    switch(propID)
+    {
+      case kpidPath:
+        // if (item.FileId.GetCapacity() >= 0)
+        {
+          UString s;
+          if (_archive.IsJoliet())
+            s = item.GetPathU();
+          else
+            s = MultiByteToUnicodeString(item.GetPath(_archive.IsSusp, _archive.SuspSkipSize), CP_OEMCP);
+
+          int pos = s.ReverseFind(L';');
+          if (pos >= 0 && pos == s.Length() - 2)
+              if (s[s.Length() - 1] == L'1')
+                s = s.Left(pos);
+          if (!s.IsEmpty())
+            if (s[s.Length() - 1] == L'.')
+              s = s.Left(s.Length() - 1);
+          prop = (const wchar_t *)NItemName::GetOSName2(s);
+        }
+        break;
+      case kpidIsDir: prop = item.IsDir(); break;
+      case kpidSize:
+      case kpidPackSize:
+        if (!item.IsDir())
+          prop = (UInt64)item.DataLength;
+        break;
+      case kpidMTime:
+      {
+        FILETIME utc;
+        if (item.DateTime.GetFileTime(utc))
+          prop = utc;
+        break;
+      }
+    }
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _archive.Refs.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt64 totalSize = 0;
+  UInt32 i;
+  for(i = 0; i < numItems; i++)
+  {
+    UInt32 index = (allFilesMode ? i : indices[i]);
+    if (index < (UInt32)_archive.Refs.Size())
+    {
+      const CRef &ref = _archive.Refs[index];
+      const CDir &item = ref.Dir->_subItems[ref.Index];
+      totalSize += item.DataLength;
+    }
+    else
+    {
+      totalSize += _archive.GetBootItemSize(index - _archive.Refs.Size());
+    }
+  }
+  extractCallback->SetTotal(totalSize);
+
+  UInt64 currentTotalSize = 0;
+  UInt64 currentItemSize;
+  
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);
+  streamSpec->SetStream(_stream);
+
+  CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+
+  for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
+  {
+    lps->InSize = lps->OutSize = currentTotalSize;
+    RINOK(lps->SetCur());
+    currentItemSize = 0;
+    CMyComPtr<ISequentialOutStream> realOutStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    UInt32 index = allFilesMode ? i : indices[i];
+    
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+    UInt64 blockIndex;
+    if (index < (UInt32)_archive.Refs.Size())
+    {
+      const CRef &ref = _archive.Refs[index];
+      const CDir &item = ref.Dir->_subItems[ref.Index];
+      if (item.IsDir())
+      {
+        RINOK(extractCallback->PrepareOperation(askMode));
+        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+        continue;
+      }
+      currentItemSize = item.DataLength;
+      blockIndex = item.ExtentLocation;
+    }
+    else
+    {
+      int bootIndex = index - _archive.Refs.Size();
+      const CBootInitialEntry &be = _archive.BootEntries[bootIndex];
+      currentItemSize = _archive.GetBootItemSize(bootIndex);
+      blockIndex = be.LoadRBA;
+    }
+   
+    if (!testMode && !realOutStream)
+      continue;
+    RINOK(extractCallback->PrepareOperation(askMode));
+    outStreamSpec->SetStream(realOutStream);
+    realOutStream.Release();
+    outStreamSpec->Init(currentItemSize);
+    RINOK(_stream->Seek(blockIndex * _archive.BlockSize, STREAM_SEEK_SET, NULL));
+    streamSpec->Init(currentItemSize);
+    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
+    outStreamSpec->ReleaseStream();
+    RINOK(extractCallback->SetOperationResult(outStreamSpec->IsFinishedOK() ?
+        NExtract::NOperationResult::kOK:
+        NExtract::NOperationResult::kDataError));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+  COM_TRY_BEGIN
+  *stream = 0;
+  UInt64 blockIndex;
+  UInt64 currentItemSize;
+  if (index < (UInt32)_archive.Refs.Size())
+  {
+    const CRef &ref = _archive.Refs[index];
+    const CDir &item = ref.Dir->_subItems[ref.Index];
+    if (item.IsDir())
+      return S_FALSE;
+    currentItemSize = item.DataLength;
+    blockIndex = item.ExtentLocation;
+  }
+  else
+  {
+    int bootIndex = index - _archive.Refs.Size();
+    const CBootInitialEntry &be = _archive.BootEntries[bootIndex];
+    currentItemSize = _archive.GetBootItemSize(bootIndex);
+    blockIndex = be.LoadRBA;
+  }
+  return CreateLimitedInStream(_stream, blockIndex * _archive.BlockSize, currentItemSize, stream);
+  COM_TRY_END
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoHandler.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoHandler.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoHandler.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoHandler.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,30 @@
+// IsoHandler.h
+
+#ifndef __ISO_HANDLER_H
+#define __ISO_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+
+#include "IsoIn.h"
+#include "IsoItem.h"
+
+namespace NArchive {
+namespace NIso {
+
+class CHandler:
+  public IInArchive,
+  public IInArchiveGetStream,
+  public CMyUnknownImp
+{
+  CMyComPtr<IInStream> _stream;
+  CInArchive _archive;
+public:
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+  INTERFACE_IInArchive(;)
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoHeader.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoHeader.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoHeader.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoHeader.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,21 @@
+// Archive/Iso/Header.h
+
+#include "StdAfx.h"
+
+#include "IsoHeader.h"
+
+namespace NArchive {
+namespace NIso {
+
+const char *kElToritoSpec = "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0";
+
+const wchar_t *kMediaTypes[5] =
+{
+  L"NoEmulation",
+  L"1.2M",
+  L"1.44M",
+  L"2.88M",
+  L"HardDisk"
+};
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoHeader.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoHeader.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoHeader.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoHeader.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,61 @@
+// Archive/IsoHeader.h
+
+#ifndef __ARCHIVE_ISO_HEADER_H
+#define __ARCHIVE_ISO_HEADER_H
+
+#include "Common/Types.h"
+
+namespace NArchive {
+namespace NIso {
+
+namespace NVolDescType
+{
+  const Byte kBootRecord = 0;
+  const Byte kPrimaryVol = 1;
+  const Byte kSupplementaryVol = 2;
+  const Byte kVolParttition = 3;
+  const Byte kTerminator = 255;
+}
+
+const Byte kVersion = 1;
+
+namespace NFileFlags
+{
+  const Byte kDirectory = 1 << 1;
+}
+
+extern const char *kElToritoSpec;
+
+const UInt32 kStartPos = 0x8000;
+
+namespace NBootEntryId
+{
+  const Byte kValidationEntry = 1;
+  const Byte kInitialEntryNotBootable = 0;
+  const Byte kInitialEntryBootable = 0x88;
+}
+
+namespace NBootPlatformId
+{
+  const Byte kX86 = 0;
+  const Byte kPowerPC = 1;
+  const Byte kMac = 2;
+}
+
+const BYTE kBootMediaTypeMask = 0xF;
+
+namespace NBootMediaType
+{
+  const Byte kNoEmulation = 0;
+  const Byte k1d2Floppy = 1;
+  const Byte k1d44Floppy = 2;
+  const Byte k2d88Floppy = 3;
+  const Byte kHardDisk = 4;
+}
+
+const int kNumBootMediaTypes = 5;
+extern const wchar_t *kMediaTypes[];
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoIn.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoIn.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoIn.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoIn.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,453 @@
+// Archive/IsoIn.cpp
+
+#include "StdAfx.h"
+
+#include "IsoIn.h"
+
+#include "../../Common/StreamUtils.h"
+
+namespace NArchive {
+namespace NIso {
+ 
+Byte CInArchive::ReadByte()
+{
+  if (m_BufferPos >= BlockSize)
+    m_BufferPos = 0;
+  if (m_BufferPos == 0)
+  {
+    size_t processedSize = BlockSize;
+    if (ReadStream(_stream, m_Buffer, &processedSize) != S_OK)
+      throw 1;
+    if (processedSize != BlockSize)
+      throw 1;
+  }
+  Byte b = m_Buffer[m_BufferPos++];
+  _position++;
+  return b;
+}
+
+void CInArchive::ReadBytes(Byte *data, UInt32 size)
+{
+  for (UInt32 i = 0; i < size; i++)
+    data[i] = ReadByte();
+}
+
+void CInArchive::Skip(size_t size)
+{
+  while (size-- != 0)
+    ReadByte();
+}
+
+void CInArchive::SkipZeros(size_t size)
+{
+  while (size-- != 0)
+  {
+    Byte b = ReadByte();
+    if (b != 0)
+      throw 1;
+  }
+}
+
+UInt16 CInArchive::ReadUInt16Spec()
+{
+  UInt16 value = 0;
+  for (int i = 0; i < 2; i++)
+    value |= ((UInt16)(ReadByte()) << (8 * i));
+  return value;
+}
+
+
+UInt16 CInArchive::ReadUInt16()
+{
+  Byte b[4];
+  ReadBytes(b, 4);
+  UInt32 value = 0;
+  for (int i = 0; i < 2; i++)
+  {
+    if (b[i] != b[3 - i])
+      IncorrectBigEndian = true;
+    value |= ((UInt16)(b[i]) << (8 * i));
+  }
+  return (UInt16)value;
+}
+
+UInt32 CInArchive::ReadUInt32Le()
+{
+  UInt32 value = 0;
+  for (int i = 0; i < 4; i++)
+    value |= ((UInt32)(ReadByte()) << (8 * i));
+  return value;
+}
+
+UInt32 CInArchive::ReadUInt32Be()
+{
+  UInt32 value = 0;
+  for (int i = 0; i < 4; i++)
+  {
+    value <<= 8;
+    value |= ReadByte();
+  }
+  return value;
+}
+
+UInt32 CInArchive::ReadUInt32()
+{
+  Byte b[8];
+  ReadBytes(b, 8);
+  UInt32 value = 0;
+  for (int i = 0; i < 4; i++)
+  {
+    if (b[i] != b[7 - i])
+      throw 1;
+    value |= ((UInt32)(b[i]) << (8 * i));
+  }
+  return value;
+}
+
+UInt32 CInArchive::ReadDigits(int numDigits)
+{
+  UInt32 res = 0;
+  for (int i = 0; i < numDigits; i++)
+  {
+    Byte b = ReadByte();
+    if (b < '0' || b > '9')
+    {
+      if (b == 0) // it's bug in some CD's
+        b = '0';
+      else
+        throw 1;
+    }
+    UInt32 d = (UInt32)(b - '0');
+    res *= 10;
+    res += d;
+  }
+  return res;
+}
+
+void CInArchive::ReadDateTime(CDateTime &d)
+{
+  d.Year = (UInt16)ReadDigits(4);
+  d.Month = (Byte)ReadDigits(2);
+  d.Day = (Byte)ReadDigits(2);
+  d.Hour = (Byte)ReadDigits(2);
+  d.Minute = (Byte)ReadDigits(2);
+  d.Second = (Byte)ReadDigits(2);
+  d.Hundredths = (Byte)ReadDigits(2);
+  d.GmtOffset = (signed char)ReadByte();
+}
+
+void CInArchive::ReadBootRecordDescriptor(CBootRecordDescriptor &d)
+{
+  ReadBytes(d.BootSystemId, sizeof(d.BootSystemId));
+  ReadBytes(d.BootId, sizeof(d.BootId));
+  ReadBytes(d.BootSystemUse, sizeof(d.BootSystemUse));
+}
+
+void CInArchive::ReadRecordingDateTime(CRecordingDateTime &t)
+{
+  t.Year = ReadByte();
+  t.Month = ReadByte();
+  t.Day = ReadByte();
+  t.Hour = ReadByte();
+  t.Minute = ReadByte();
+  t.Second = ReadByte();
+  t.GmtOffset = (signed char)ReadByte();
+}
+
+void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len)
+{
+  r.ExtendedAttributeRecordLen = ReadByte();
+  if (r.ExtendedAttributeRecordLen != 0)
+    throw 1;
+  r.ExtentLocation = ReadUInt32();
+  r.DataLength = ReadUInt32();
+  ReadRecordingDateTime(r.DateTime);
+  r.FileFlags = ReadByte();
+  r.FileUnitSize = ReadByte();
+  r.InterleaveGapSize = ReadByte();
+  r.VolSequenceNumber = ReadUInt16();
+  Byte idLen = ReadByte();
+  r.FileId.SetCapacity(idLen);
+  ReadBytes((Byte *)r.FileId, idLen);
+  int padSize = 1 - (idLen & 1);
+  
+  // SkipZeros(1 - (idLen & 1));
+  Skip(1 - (idLen & 1)); // it's bug in some cd's. Must be zeros
+
+  int curPos = 33 + idLen + padSize;
+  if (curPos > len)
+    throw 1;
+  int rem = len - curPos;
+  r.SystemUse.SetCapacity(rem);
+  ReadBytes((Byte *)r.SystemUse, rem);
+}
+
+void CInArchive::ReadDirRecord(CDirRecord &r)
+{
+  Byte len = ReadByte();
+  // Some CDs can have incorrect value len = 48 ('0') in VolumeDescriptor.
+  // But maybe we must use real "len" for other records.
+  len = 34;
+  ReadDirRecord2(r, len);
+}
+
+void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d)
+{
+  d.VolFlags = ReadByte();
+  ReadBytes(d.SystemId, sizeof(d.SystemId));
+  ReadBytes(d.VolumeId, sizeof(d.VolumeId));
+  SkipZeros(8);
+  d.VolumeSpaceSize = ReadUInt32();
+  ReadBytes(d.EscapeSequence, sizeof(d.EscapeSequence));
+  d.VolumeSetSize = ReadUInt16();
+  d.VolumeSequenceNumber = ReadUInt16();
+  d.LogicalBlockSize = ReadUInt16();
+  d.PathTableSize = ReadUInt32();
+  d.LPathTableLocation = ReadUInt32Le();
+  d.LOptionalPathTableLocation = ReadUInt32Le();
+  d.MPathTableLocation = ReadUInt32Be();
+  d.MOptionalPathTableLocation = ReadUInt32Be();
+  ReadDirRecord(d.RootDirRecord);
+  ReadBytes(d.VolumeSetId, sizeof(d.VolumeSetId));
+  ReadBytes(d.PublisherId, sizeof(d.PublisherId));
+  ReadBytes(d.DataPreparerId, sizeof(d.DataPreparerId));
+  ReadBytes(d.ApplicationId, sizeof(d.ApplicationId));
+  ReadBytes(d.CopyrightFileId, sizeof(d.CopyrightFileId));
+  ReadBytes(d.AbstractFileId, sizeof(d.AbstractFileId));
+  ReadBytes(d.BibFileId, sizeof(d.BibFileId));
+  ReadDateTime(d.CTime);
+  ReadDateTime(d.MTime);
+  ReadDateTime(d.ExpirationTime);
+  ReadDateTime(d.EffectiveTime);
+  d.FileStructureVersion = ReadByte(); // = 1
+  SkipZeros(1);
+  ReadBytes(d.ApplicationUse, sizeof(d.ApplicationUse));
+  SkipZeros(653);
+}
+
+static const Byte kSig_CD001[5] = { 'C', 'D', '0', '0', '1' };
+
+static const Byte kSig_NSR02[5] = { 'N', 'S', 'R', '0', '2' };
+static const Byte kSig_NSR03[5] = { 'N', 'S', 'R', '0', '3' };
+static const Byte kSig_BEA01[5] = { 'B', 'E', 'A', '0', '1' };
+static const Byte kSig_TEA01[5] = { 'T', 'E', 'A', '0', '1' };
+
+static inline bool CheckSignature(const Byte *sig, const Byte *data)
+{
+  for (int i = 0; i < 5; i++)
+    if (sig[i] != data[i])
+      return false;
+  return true;
+}
+
+void CInArchive::SeekToBlock(UInt32 blockIndex)
+{
+  if (_stream->Seek((UInt64)blockIndex * VolDescs[MainVolDescIndex].LogicalBlockSize, STREAM_SEEK_SET, &_position) != S_OK)
+    throw 1;
+  m_BufferPos = 0;
+}
+
+void CInArchive::ReadDir(CDir &d, int level)
+{
+  if (!d.IsDir())
+    return;
+  SeekToBlock(d.ExtentLocation);
+  UInt64 startPos = _position;
+
+  bool firstItem = true;
+  for (;;)
+  {
+    UInt64 offset = _position - startPos;
+    if (offset >= d.DataLength)
+      break;
+    Byte len = ReadByte();
+    if (len == 0)
+      continue;
+    CDir subItem;
+    ReadDirRecord2(subItem, len);
+    if (firstItem && level == 0)
+      IsSusp = subItem.CheckSusp(SuspSkipSize);
+      
+    if (!subItem.IsSystemItem())
+      d._subItems.Add(subItem);
+
+    firstItem = false;
+  }
+  for (int i = 0; i < d._subItems.Size(); i++)
+    ReadDir(d._subItems[i], level + 1);
+}
+
+void CInArchive::CreateRefs(CDir &d)
+{
+  if (!d.IsDir())
+    return;
+  for (int i = 0; i < d._subItems.Size(); i++)
+  {
+    CRef ref;
+    CDir &subItem = d._subItems[i];
+    subItem.Parent = &d;
+    ref.Dir = &d;
+    ref.Index = i;
+    Refs.Add(ref);
+    CreateRefs(subItem);
+  }
+}
+
+void CInArchive::ReadBootInfo()
+{
+  if (!_bootIsDefined)
+    return;
+  if (memcmp(_bootDesc.BootSystemId, kElToritoSpec, sizeof(_bootDesc.BootSystemId)) != 0)
+    return;
+  
+  const Byte *p = (const Byte *)_bootDesc.BootSystemUse;
+  UInt32 blockIndex = p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24);
+  SeekToBlock(blockIndex);
+  Byte b = ReadByte();
+  if (b != NBootEntryId::kValidationEntry)
+    return;
+  {
+    CBootValidationEntry e;
+    e.PlatformId = ReadByte();
+    if (ReadUInt16Spec() != 0)
+      throw 1;
+    ReadBytes(e.Id, sizeof(e.Id));
+    /* UInt16 checkSum = */ ReadUInt16Spec();
+    if (ReadByte() != 0x55)
+      throw 1;
+    if (ReadByte() != 0xAA)
+      throw 1;
+  }
+  b = ReadByte();
+  if (b == NBootEntryId::kInitialEntryBootable || b == NBootEntryId::kInitialEntryNotBootable)
+  {
+    CBootInitialEntry e;
+    e.Bootable = (b == NBootEntryId::kInitialEntryBootable);
+    e.BootMediaType = ReadByte();
+    e.LoadSegment = ReadUInt16Spec();
+    e.SystemType = ReadByte();
+    if (ReadByte() != 0)
+      throw 1;
+    e.SectorCount = ReadUInt16Spec();
+    e.LoadRBA = ReadUInt32Le();
+    if (ReadByte() != 0)
+      throw 1;
+    BootEntries.Add(e);
+  }
+  else
+    return;
+}
+
+HRESULT CInArchive::Open2()
+{
+  Clear();
+  RINOK(_stream->Seek(kStartPos, STREAM_SEEK_CUR, &_position));
+
+  m_BufferPos = 0;
+  BlockSize = kBlockSize;
+  for (;;)
+  {
+    Byte sig[7];
+    ReadBytes(sig, 7);
+    Byte ver = sig[6];
+    if (!CheckSignature(kSig_CD001, sig + 1))
+    {
+      return S_FALSE;
+      /*
+      if (sig[0] != 0 || ver != 1)
+        break;
+      if (CheckSignature(kSig_BEA01, sig + 1))
+      {
+      }
+      else if (CheckSignature(kSig_TEA01, sig + 1))
+      {
+        break;
+      }
+      else if (CheckSignature(kSig_NSR02, sig + 1))
+      {
+      }
+      else
+        break;
+      SkipZeros(0x800 - 7);
+      continue;
+      */
+    }
+    // version = 2 for ISO 9660:1999?
+    if (ver > 2)
+      throw S_FALSE;
+
+    if (sig[0] == NVolDescType::kTerminator)
+    {
+      break;
+      // Skip(0x800 - 7);
+      // continue;
+    }
+    switch(sig[0])
+    {
+      case NVolDescType::kBootRecord:
+      {
+        _bootIsDefined = true;
+        ReadBootRecordDescriptor(_bootDesc);
+        break;
+      }
+      case NVolDescType::kPrimaryVol:
+      case NVolDescType::kSupplementaryVol:
+      {
+        // some ISOs have two PrimaryVols.
+        CVolumeDescriptor vd;
+        ReadVolumeDescriptor(vd);
+        if (sig[0] == NVolDescType::kPrimaryVol)
+        {
+          // some burners write "Joliet" Escape Sequence to primary volume
+          memset(vd.EscapeSequence, 0, sizeof(vd.EscapeSequence));
+        }
+        VolDescs.Add(vd);
+        break;
+      }
+      default:
+        break;
+    }
+  }
+  if (VolDescs.IsEmpty())
+    return S_FALSE;
+  for (MainVolDescIndex = VolDescs.Size() - 1; MainVolDescIndex > 0; MainVolDescIndex--)
+    if (VolDescs[MainVolDescIndex].IsJoliet())
+      break;
+  // MainVolDescIndex = 0; // to read primary volume
+  const CVolumeDescriptor &vd = VolDescs[MainVolDescIndex];
+  if (vd.LogicalBlockSize != kBlockSize)
+    return S_FALSE;
+  (CDirRecord &)_rootDir = vd.RootDirRecord;
+  ReadDir(_rootDir, 0);
+  CreateRefs(_rootDir);
+  ReadBootInfo();
+  return S_OK;
+}
+
+HRESULT CInArchive::Open(IInStream *inStream)
+{
+  _stream = inStream;
+  UInt64 pos;
+  RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &pos));
+  RINOK(_stream->Seek(0, STREAM_SEEK_END, &_archiveSize));
+  RINOK(_stream->Seek(pos, STREAM_SEEK_SET, &_position));
+  HRESULT res = S_FALSE;
+  try { res = Open2(); }
+  catch(...) { Clear(); res = S_FALSE; }
+  _stream.Release();
+  return res;
+}
+
+void CInArchive::Clear()
+{
+  IncorrectBigEndian = false;
+  Refs.Clear();
+  _rootDir.Clear();
+  VolDescs.Clear();
+  _bootIsDefined = false;
+  BootEntries.Clear();
+  SuspSkipSize = 0;
+  IsSusp = false;
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoIn.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoIn.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoIn.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoIn.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,315 @@
+// Archive/IsoIn.h
+
+#ifndef __ARCHIVE_ISO_IN_H
+#define __ARCHIVE_ISO_IN_H
+
+#include "Common/IntToString.h"
+#include "Common/MyCom.h"
+
+#include "../../IStream.h"
+
+#include "IsoHeader.h"
+#include "IsoItem.h"
+
+namespace NArchive {
+namespace NIso {
+
+struct CDir: public CDirRecord
+{
+  CDir *Parent;
+  CObjectVector<CDir> _subItems;
+
+  void Clear()
+  {
+    Parent = 0;
+    _subItems.Clear();
+  }
+  
+  int GetLength(bool checkSusp, int skipSize) const
+  {
+    int len = GetLengthCur(checkSusp, skipSize);
+    if (Parent != 0)
+      if (Parent->Parent != 0)
+        len += 1 + Parent->GetLength(checkSusp, skipSize);
+    return len;
+  }
+
+  int GetLengthU() const
+  {
+    int len = (int)(FileId.GetCapacity() / 2);
+    if (Parent != 0)
+      if (Parent->Parent != 0)
+        len += 1 + Parent->GetLengthU();
+    return len;
+  }
+  
+  AString GetPath(bool checkSusp, int skipSize) const
+  {
+    AString s;
+    int len = GetLength(checkSusp, skipSize);
+    char *p = s.GetBuffer(len +  1);
+    p += len;
+    *p = 0;
+    const CDir *cur = this;
+    for (;;)
+    {
+      int curLen = cur->GetLengthCur(checkSusp, skipSize);
+      p -= curLen;
+      memmove(p, (const char *)(const Byte *)cur->GetNameCur(checkSusp, skipSize), curLen);
+      cur = cur->Parent;
+      if (cur == 0)
+        break;
+      if (cur->Parent == 0)
+        break;
+      p--;
+      *p = CHAR_PATH_SEPARATOR;
+    }
+    s.ReleaseBuffer();
+    return s;
+  }
+
+  UString GetPathU() const
+  {
+    UString s;
+    int len = GetLengthU();
+    wchar_t *p = s.GetBuffer(len +  1);
+    p += len;
+    *p = 0;
+    const CDir *cur = this;
+    for (;;)
+    {
+      int curLen = (int)(cur->FileId.GetCapacity() / 2);
+      p -= curLen;
+      for (int i = 0; i < curLen; i++)
+      {
+        Byte b0 = ((const Byte *)cur->FileId)[i * 2];
+        Byte b1 = ((const Byte *)cur->FileId)[i * 2 + 1];
+        p[i] = (wchar_t)(((wchar_t)b0 << 8) | b1);
+      }
+      cur = cur->Parent;
+      if (cur == 0)
+        break;
+      if (cur->Parent == 0)
+        break;
+      p--;
+      *p = WCHAR_PATH_SEPARATOR;
+    }
+    s.ReleaseBuffer();
+    return s;
+  }
+};
+
+struct CDateTime
+{
+  UInt16 Year;
+  Byte Month;
+  Byte Day;
+  Byte Hour;
+  Byte Minute;
+  Byte Second;
+  Byte Hundredths;
+  signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded.
+  bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 &&
+      Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; }
+
+  bool GetFileTime(FILETIME &ft) const
+  {
+    UInt64 value;
+    bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, value);
+    if (res)
+    {
+      value -= (UInt64)((Int64)GmtOffset * 15 * 60);
+      value *= 10000000;
+    }
+    ft.dwLowDateTime = (DWORD)value;
+    ft.dwHighDateTime = (DWORD)(value >> 32);
+    return res;
+  }
+};
+
+struct CBootRecordDescriptor
+{
+  Byte BootSystemId[32];  // a-characters
+  Byte BootId[32];        // a-characters
+  Byte BootSystemUse[1977];
+};
+
+struct CBootValidationEntry
+{
+  Byte PlatformId;
+  Byte Id[24]; // to identify the manufacturer/developer of the CD-ROM.
+};
+
+struct CBootInitialEntry
+{
+  bool Bootable;
+  Byte BootMediaType;
+  UInt16 LoadSegment;
+  /* This is the load segment for the initial boot image. If this
+     value is 0 the system will use the traditional segment of 7C0. If this value
+     is non-zero the system will use the specified segment. This applies to x86
+     architectures only. For "flat" model architectures (such as Motorola) this
+     is the address divided by 10. */
+  Byte SystemType;    // This must be a copy of byte 5 (System Type) from the
+                      // Partition Table found in the boot image.
+  UInt16 SectorCount; // This is the number of virtual/emulated sectors the system
+                      // will store at Load Segment during the initial boot procedure.
+  UInt32 LoadRBA;     // This is the start address of the virtual disk. CDÂ’s use
+                      // Relative/Logical block addressing.
+
+  UInt64 GetSize() const
+  {
+    // if (BootMediaType == NBootMediaType::k1d44Floppy) (1440 << 10);
+    return SectorCount * 512;
+  }
+
+  UString GetName() const
+  {
+    UString s;
+    if (Bootable)
+      s += L"Bootable";
+    else
+      s += L"NotBootable";
+    s += L"_";
+    if (BootMediaType >= kNumBootMediaTypes)
+    {
+      wchar_t name[16];
+      ConvertUInt32ToString(BootMediaType, name);
+      s += name;
+    }
+    else
+      s += kMediaTypes[BootMediaType];
+    s += L".img";
+    return s;
+  }
+};
+
+struct CVolumeDescriptor
+{
+  Byte VolFlags;
+  Byte SystemId[32]; // a-characters. An identification of a system
+                     // which can recognize and act upon the content of the Logical
+                     // Sectors with logical Sector Numbers 0 to 15 of the volume.
+  Byte VolumeId[32]; // d-characters. An identification of the volume.
+  UInt32 VolumeSpaceSize; // the number of Logical Blocks in which the Volume Space of the volume is recorded
+  Byte EscapeSequence[32];
+  UInt16 VolumeSetSize;
+  UInt16 VolumeSequenceNumber; // the ordinal number of the volume in the Volume Set of which the volume is a member.
+  UInt16 LogicalBlockSize;
+  UInt32 PathTableSize;
+  UInt32 LPathTableLocation;
+  UInt32 LOptionalPathTableLocation;
+  UInt32 MPathTableLocation;
+  UInt32 MOptionalPathTableLocation;
+  CDirRecord RootDirRecord;
+  Byte VolumeSetId[128];
+  Byte PublisherId[128];
+  Byte DataPreparerId[128];
+  Byte ApplicationId[128];
+  Byte CopyrightFileId[37];
+  Byte AbstractFileId[37];
+  Byte BibFileId[37];
+  CDateTime CTime;
+  CDateTime MTime;
+  CDateTime ExpirationTime;
+  CDateTime EffectiveTime;
+  Byte FileStructureVersion; // = 1;
+  Byte ApplicationUse[512];
+
+  bool IsJoliet() const
+  {
+    if ((VolFlags & 1) != 0)
+      return false;
+    Byte b = EscapeSequence[2];
+    return (EscapeSequence[0] == 0x25 && EscapeSequence[1] == 0x2F &&
+      (b == 0x40 || b == 0x43 || b == 0x45));
+  }
+};
+
+struct CRef
+{
+  CDir *Dir;
+  UInt32 Index;
+};
+
+const UInt32 kBlockSize = 1 << 11;
+
+class CInArchive
+{
+  CMyComPtr<IInStream> _stream;
+  UInt64 _position;
+
+  Byte m_Buffer[kBlockSize];
+  UInt32 m_BufferPos;
+  
+  CDir _rootDir;
+  bool _bootIsDefined;
+  CBootRecordDescriptor _bootDesc;
+
+  void Skip(size_t size);
+  void SkipZeros(size_t size);
+  Byte ReadByte();
+  void ReadBytes(Byte *data, UInt32 size);
+  UInt16 ReadUInt16Spec();
+  UInt16 ReadUInt16();
+  UInt32 ReadUInt32Le();
+  UInt32 ReadUInt32Be();
+  UInt32 ReadUInt32();
+  UInt64 ReadUInt64();
+  UInt32 ReadDigits(int numDigits);
+  void ReadDateTime(CDateTime &d);
+  void ReadRecordingDateTime(CRecordingDateTime &t);
+  void ReadDirRecord2(CDirRecord &r, Byte len);
+  void ReadDirRecord(CDirRecord &r);
+
+  void ReadBootRecordDescriptor(CBootRecordDescriptor &d);
+  void ReadVolumeDescriptor(CVolumeDescriptor &d);
+
+  void SeekToBlock(UInt32 blockIndex);
+  void ReadDir(CDir &d, int level);
+  void CreateRefs(CDir &d);
+
+  void ReadBootInfo();
+  HRESULT Open2();
+public:
+  HRESULT Open(IInStream *inStream);
+  void Clear();
+
+  UInt64 _archiveSize;
+
+  CRecordVector<CRef> Refs;
+  CObjectVector<CVolumeDescriptor> VolDescs;
+  int MainVolDescIndex;
+  UInt32 BlockSize;
+  CObjectVector<CBootInitialEntry> BootEntries;
+  bool IncorrectBigEndian;
+
+
+  bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); }
+
+  UInt64 GetBootItemSize(int index) const
+  {
+    const CBootInitialEntry &be = BootEntries[index];
+    UInt64 size = be.GetSize();
+    if (be.BootMediaType == NBootMediaType::k1d2Floppy)
+      size = (1200 << 10);
+    else if (be.BootMediaType == NBootMediaType::k1d44Floppy)
+      size = (1440 << 10);
+    else if (be.BootMediaType == NBootMediaType::k2d88Floppy)
+      size = (2880 << 10);
+    UInt64 startPos = be.LoadRBA * BlockSize;
+    if (startPos < _archiveSize)
+    {
+      if (_archiveSize - startPos < size)
+        size = _archiveSize - startPos;
+    }
+    return size;
+  }
+
+  bool IsSusp;
+  int SuspSkipSize;
+};
+  
+}}
+  
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoItem.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoItem.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoItem.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoItem.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,141 @@
+// Archive/IsoItem.h
+
+#ifndef __ARCHIVE_ISO_ITEM_H
+#define __ARCHIVE_ISO_ITEM_H
+
+#include "Common/Types.h"
+#include "Common/MyString.h"
+#include "Common/Buffer.h"
+
+#include "Windows/Time.h"
+
+#include "IsoHeader.h"
+
+namespace NArchive {
+namespace NIso {
+
+struct CRecordingDateTime
+{
+  Byte Year;
+  Byte Month;
+  Byte Day;
+  Byte Hour;
+  Byte Minute;
+  Byte Second;
+  signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded.
+  
+  bool GetFileTime(FILETIME &ft) const
+  {
+    UInt64 value;
+    bool res = NWindows::NTime::GetSecondsSince1601(Year + 1900, Month, Day, Hour, Minute, Second, value);
+    if (res)
+    {
+      value -= (UInt64)((Int64)GmtOffset * 15 * 60);
+      value *= 10000000;
+    }
+    ft.dwLowDateTime = (DWORD)value;
+    ft.dwHighDateTime = (DWORD)(value >> 32);
+    return res;
+  }
+};
+
+struct CDirRecord
+{
+  Byte ExtendedAttributeRecordLen;
+  UInt32 ExtentLocation;
+  UInt32 DataLength;
+  CRecordingDateTime DateTime;
+  Byte FileFlags;
+  Byte FileUnitSize;
+  Byte InterleaveGapSize;
+  UInt16 VolSequenceNumber;
+  CByteBuffer FileId;
+  CByteBuffer SystemUse;
+
+  bool IsDir() const { return  (FileFlags & NFileFlags::kDirectory) != 0; }
+  bool IsSystemItem() const
+  {
+    if (FileId.GetCapacity() != 1)
+      return false;
+    Byte b = *(const Byte *)FileId;
+    return (b == 0 || b == 1);
+  }
+
+  const Byte* FindSuspName(int skipSize, int &lenRes) const
+  {
+    lenRes = 0;
+    const Byte *p = (const Byte *)SystemUse + skipSize;
+    int length = (int)(SystemUse.GetCapacity() - skipSize);
+    while (length >= 5)
+    {
+      int len = p[2];
+      if (p[0] == 'N' && p[1] == 'M' && p[3] == 1)
+      {
+        lenRes = len - 5;
+        return p + 5;
+      }
+      p += len;
+      length -= len;
+    }
+    return 0;
+  }
+
+  int GetLengthCur(bool checkSusp, int skipSize) const
+  {
+    if (checkSusp)
+    {
+      int len;
+      const Byte *res = FindSuspName(skipSize, len);
+      if (res != 0)
+        return len;
+    }
+    return (int)FileId.GetCapacity();
+  }
+
+  const Byte* GetNameCur(bool checkSusp, int skipSize) const
+  {
+    if (checkSusp)
+    {
+      int len;
+      const Byte *res = FindSuspName(skipSize, len);
+      if (res != 0)
+        return res;
+    }
+    return (const Byte *)FileId;
+  }
+
+
+  bool CheckSusp(const Byte *p, int &startPos) const
+  {
+    if (p[0] == 'S' &&
+        p[1] == 'P' &&
+        p[2] == 0x7 &&
+        p[3] == 0x1 &&
+        p[4] == 0xBE &&
+        p[5] == 0xEF)
+    {
+      startPos = p[6];
+      return true;
+    }
+    return false;
+  }
+
+  bool CheckSusp(int &startPos) const
+  {
+    const Byte *p = (const Byte *)SystemUse;
+    int length = (int)SystemUse.GetCapacity();
+    const int kMinLen = 7;
+    if (length < kMinLen)
+      return false;
+    if (CheckSusp(p, startPos))
+      return true;
+    const int kOffset2 = 14;
+    if (length < kOffset2 + kMinLen)
+      return false;
+    return CheckSusp(p + kOffset2, startPos);
+  }
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoRegister.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoRegister.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoRegister.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Iso/IsoRegister.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,13 @@
+// IsoRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterArc.h"
+
+#include "IsoHandler.h"
+static IInArchive *CreateArc() { return new NArchive::NIso::CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"Iso", L"iso img", 0, 0xE7, { 'C', 'D', '0', '0', '1', 0x1 }, 7, false, CreateArc, 0 };
+
+REGISTER_ARC(Iso)

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/LzhHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/LzhHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/LzhHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/LzhHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,775 @@
+// LzhHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/Buffer.h"
+#include "Common/ComTry.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../ICoder.h"
+
+#include "../Common/LimitedStreams.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+#include "../Compress/LzhDecoder.h"
+
+#include "IArchive.h"
+
+#include "Common/ItemNameUtils.h"
+
+using namespace NWindows;
+using namespace NTime;
+
+#define Get16(p) GetUi16(p)
+#define Get32(p) GetUi32(p)
+
+namespace NArchive {
+namespace NLzh{
+
+const int kMethodIdSize = 5;
+
+const Byte kExtIdFileName = 0x01;
+const Byte kExtIdDirName  = 0x02;
+const Byte kExtIdUnixTime = 0x54;
+
+struct CExtension
+{
+  Byte Type;
+  CByteBuffer Data;
+  AString GetString() const
+  {
+    AString s;
+    for (size_t i = 0; i < Data.GetCapacity(); i++)
+    {
+      char c = (char)Data[i];
+      if (c == 0)
+        break;
+      s += c;
+    }
+    return s;
+  }
+};
+
+struct CItem
+{
+  AString Name;
+  Byte Method[kMethodIdSize];
+  Byte Attributes;
+  Byte Level;
+  Byte OsId;
+  UInt32 PackSize;
+  UInt32 Size;
+  UInt32 ModifiedTime;
+  UInt16 CRC;
+  CObjectVector<CExtension> Extensions;
+
+  bool IsValidMethod() const  { return (Method[0] == '-' && Method[1] == 'l' && Method[4] == '-'); }
+  bool IsLhMethod() const  {return (IsValidMethod() && Method[2] == 'h'); }
+  bool IsDir() const {return (IsLhMethod() && Method[3] == 'd'); }
+
+  bool IsCopyMethod() const
+  {
+    return (IsLhMethod() && Method[3] == '0') ||
+      (IsValidMethod() && Method[2] == 'z' && Method[3] == '4');
+  }
+  
+  bool IsLh1GroupMethod() const
+  {
+    if (!IsLhMethod())
+      return false;
+    switch(Method[3])
+    {
+      case '1':
+        return true;
+    }
+    return false;
+  }
+  
+  bool IsLh4GroupMethod() const
+  {
+    if (!IsLhMethod())
+      return false;
+    switch(Method[3])
+    {
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+        return true;
+    }
+    return false;
+  }
+  
+  int GetNumDictBits() const
+  {
+    if (!IsLhMethod())
+      return 0;
+    switch(Method[3])
+    {
+      case '1': return 12;
+      case '2': return 13;
+      case '3': return 13;
+      case '4': return 12;
+      case '5': return 13;
+      case '6': return 15;
+      case '7': return 16;
+    }
+    return 0;
+  }
+
+  int FindExt(Byte type) const
+  {
+    for (int i = 0; i < Extensions.Size(); i++)
+      if (Extensions[i].Type == type)
+        return i;
+    return -1;
+  }
+  bool GetUnixTime(UInt32 &value) const
+  {
+    int index = FindExt(kExtIdUnixTime);
+    if (index < 0)
+    {
+      if (Level == 2)
+      {
+        value = ModifiedTime;
+        return true;
+      }
+      return false;
+    }
+    const Byte *data = (const Byte *)(Extensions[index].Data);
+    value = GetUi32(data);
+    return true;
+  }
+
+  AString GetDirName() const
+  {
+    int index = FindExt(kExtIdDirName);
+    if (index < 0)
+      return AString();
+    return Extensions[index].GetString();
+  }
+
+  AString GetFileName() const
+  {
+    int index = FindExt(kExtIdFileName);
+    if (index < 0)
+      return Name;
+    return Extensions[index].GetString();
+  }
+
+  AString GetName() const
+  {
+    AString dirName = GetDirName();
+    const char kDirSeparator = CHAR_PATH_SEPARATOR; // '\\';
+    // check kDirSeparator in Linux
+    dirName.Replace((char)(unsigned char)0xFF, kDirSeparator);
+    if (!dirName.IsEmpty() && dirName.Back() != kDirSeparator)
+      dirName += kDirSeparator;
+    return dirName + GetFileName();
+  }
+};
+
+struct CItemEx: public CItem
+{
+  UInt64 DataPosition;
+};
+
+class CInArchive
+{
+  CMyComPtr<IInStream> m_Stream;
+  UInt64 m_Position;
+  
+  HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize);
+  HRESULT CheckReadBytes(void *data, UInt32 size);
+public:
+  HRESULT Open(IInStream *inStream);
+  HRESULT GetNextItem(bool &filled, CItemEx &itemInfo);
+  HRESULT Skip(UInt64 numBytes);
+};
+
+HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
+{
+  size_t realProcessedSize = size;
+  RINOK(ReadStream(m_Stream, data, &realProcessedSize));
+  processedSize = (UInt32)realProcessedSize;
+  m_Position += processedSize;
+  return S_OK;
+}
+
+HRESULT CInArchive::CheckReadBytes(void *data, UInt32 size)
+{
+  UInt32 processedSize;
+  RINOK(ReadBytes(data, size, processedSize));
+  return (processedSize == size) ? S_OK: S_FALSE;
+}
+
+HRESULT CInArchive::Open(IInStream *inStream)
+{
+  RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));
+  m_Stream = inStream;
+  return S_OK;
+}
+
+static const Byte *ReadUInt16(const Byte *p, UInt16 &v)
+{
+  v = Get16(p);
+  return p + 2;
+}
+
+static const Byte *ReadString(const Byte *p, size_t size, AString &s)
+{
+  s.Empty();
+  for (size_t i = 0; i < size; i++)
+  {
+    char c = p[i];
+    if (c == 0)
+      break;
+    s += c;
+  }
+  return p + size;
+}
+
+static Byte CalcSum(const Byte *data, size_t size)
+{
+  Byte sum = 0;
+  for (size_t i = 0; i < size; i++)
+    sum = (Byte)(sum + data[i]);
+  return sum;
+}
+
+HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
+{
+  filled = false;
+
+  UInt32 processedSize;
+  Byte startHeader[2];
+  RINOK(ReadBytes(startHeader, 2, processedSize))
+  if (processedSize == 0)
+    return S_OK;
+  if (processedSize == 1)
+    return (startHeader[0] == 0) ? S_OK: S_FALSE;
+  if (startHeader[0] == 0 && startHeader[1] == 0)
+    return S_OK;
+
+  Byte header[256];
+  const UInt32 kBasicPartSize = 22;
+  RINOK(ReadBytes(header, kBasicPartSize, processedSize));
+  if (processedSize != kBasicPartSize)
+    return (startHeader[0] == 0) ? S_OK: S_FALSE;
+
+  const Byte *p = header;
+  memcpy(item.Method, p, kMethodIdSize);
+  if (!item.IsValidMethod())
+    return S_OK;
+  p += kMethodIdSize;
+  item.PackSize = Get32(p);
+  item.Size = Get32(p + 4);
+  item.ModifiedTime = Get32(p + 8);
+  item.Attributes = p[12];
+  item.Level = p[13];
+  p += 14;
+  if (item.Level > 2)
+    return S_FALSE;
+  UInt32 headerSize;
+  if (item.Level < 2)
+  {
+    headerSize = startHeader[0];
+    if (headerSize < kBasicPartSize)
+      return S_FALSE;
+    UInt32 remain = headerSize - kBasicPartSize;
+    RINOK(CheckReadBytes(header + kBasicPartSize, remain));
+    if (startHeader[1] != CalcSum(header, headerSize))
+      return S_FALSE;
+    size_t nameLength = *p++;
+    if ((p - header) + nameLength + 2 > headerSize)
+      return S_FALSE;
+    p = ReadString(p, nameLength, item.Name);
+  }
+  else
+   headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8);
+  p = ReadUInt16(p, item.CRC);
+  if (item.Level != 0)
+  {
+    if (item.Level == 2)
+    {
+      RINOK(CheckReadBytes(header + kBasicPartSize, 2));
+    }
+    if ((size_t)(p - header) + 3 > headerSize)
+      return S_FALSE;
+    item.OsId = *p++;
+    UInt16 nextSize;
+    p = ReadUInt16(p, nextSize);
+    while (nextSize != 0)
+    {
+      if (nextSize < 3)
+        return S_FALSE;
+      if (item.Level == 1)
+      {
+        if (item.PackSize < nextSize)
+          return S_FALSE;
+        item.PackSize -= nextSize;
+      }
+      CExtension ext;
+      RINOK(CheckReadBytes(&ext.Type, 1))
+      nextSize -= 3;
+      ext.Data.SetCapacity(nextSize);
+      RINOK(CheckReadBytes((Byte *)ext.Data, nextSize))
+      item.Extensions.Add(ext);
+      Byte hdr2[2];
+      RINOK(CheckReadBytes(hdr2, 2));
+      ReadUInt16(hdr2, nextSize);
+    }
+  }
+  item.DataPosition = m_Position;
+  filled = true;
+  return S_OK;
+}
+
+HRESULT CInArchive::Skip(UInt64 numBytes)
+{
+  UInt64 newPostion;
+  RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion));
+  m_Position += numBytes;
+  if (m_Position != newPostion)
+    return E_FAIL;
+  return S_OK;
+}
+
+struct COsPair
+{
+  Byte Id;
+  const char *Name;
+};
+
+static COsPair g_OsPairs[] =
+{
+  {   0, "MS-DOS" },
+  { 'M', "MS-DOS" },
+  { '2', "OS/2" },
+  { '9', "OS9" },
+  { 'K', "OS/68K" },
+  { '3', "OS/386" },
+  { 'H', "HUMAN" },
+  { 'U', "UNIX" },
+  { 'C', "CP/M" },
+  { 'F', "FLEX" },
+  { 'm', "Mac" },
+  { 'R', "Runser" },
+  { 'T', "TownsOS" },
+  { 'X', "XOSK" },
+  { 'w', "Windows 95" },
+  { 'W', "Windows NT" },
+  { 'J', "Java VM" }
+};
+
+static const char *kUnknownOS = "Unknown";
+
+static const char *GetOS(Byte osId)
+{
+  for (int i = 0; i < sizeof(g_OsPairs) / sizeof(g_OsPairs[0]); i++)
+    if (g_OsPairs[i].Id == osId)
+      return g_OsPairs[i].Name;
+  return kUnknownOS;
+}
+
+static STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidIsDir, VT_BOOL},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMTime, VT_FILETIME},
+  // { NULL, kpidAttrib, VT_UI4},
+  { NULL, kpidCRC, VT_UI4},
+  { NULL, kpidMethod, VT_BSTR},
+  { NULL, kpidHostOS, VT_BSTR}
+};
+
+class CCRC
+{
+  UInt16 _value;
+public:
+  static UInt16 Table[256];
+  static void InitTable();
+  
+  CCRC(): _value(0) {}
+  void Init() { _value = 0; }
+  void Update(const void *data, size_t size);
+  UInt16 GetDigest() const { return _value; }
+};
+
+static const UInt16 kCRCPoly = 0xA001;
+
+UInt16 CCRC::Table[256];
+
+void CCRC::InitTable()
+{
+  for (UInt32 i = 0; i < 256; i++)
+  {
+    UInt32 r = i;
+    for (int j = 0; j < 8; j++)
+      if (r & 1)
+        r = (r >> 1) ^ kCRCPoly;
+      else
+        r >>= 1;
+    CCRC::Table[i] = (UInt16)r;
+  }
+}
+
+class CCRCTableInit
+{
+public:
+  CCRCTableInit() { CCRC::InitTable(); }
+} g_CRCTableInit;
+
+void CCRC::Update(const void *data, size_t size)
+{
+  UInt16 v = _value;
+  const Byte *p = (const Byte *)data;
+  for (; size > 0; size--, p++)
+    v = (UInt16)(Table[((Byte)(v)) ^ *p] ^ (v >> 8));
+  _value = v;
+}
+
+
+class COutStreamWithCRC:
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+private:
+  CCRC _crc;
+  CMyComPtr<ISequentialOutStream> _stream;
+public:
+  void Init(ISequentialOutStream *stream)
+  {
+    _stream = stream;
+    _crc.Init();
+  }
+  void ReleaseStream() { _stream.Release(); }
+  UInt32 GetCRC() const { return _crc.GetDigest(); }
+  void InitCRC() { _crc.Init(); }
+};
+
+STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 realProcessedSize;
+  HRESULT result;
+  if (!_stream)
+  {
+    realProcessedSize = size;
+    result = S_OK;
+  }
+  else
+    result = _stream->Write(data, size, &realProcessedSize);
+  _crc.Update(data, realProcessedSize);
+  if (processedSize != NULL)
+    *processedSize = realProcessedSize;
+  return result;
+}
+
+class CHandler:
+  public IInArchive,
+  public CMyUnknownImp
+{
+  CObjectVector<CItemEx> _items;
+  CMyComPtr<IInStream> _stream;
+public:
+  MY_UNKNOWN_IMP1(IInArchive)
+  INTERFACE_IInArchive(;)
+  CHandler();
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_NO
+
+CHandler::CHandler() {}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _items.Size();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID,  PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  const CItemEx &item = _items[index];
+  switch(propID)
+  {
+    case kpidPath:
+    {
+      UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetName(), CP_OEMCP));
+      if (!s.IsEmpty())
+      {
+        if (s[s.Length() - 1] == WCHAR_PATH_SEPARATOR)
+           s.Delete(s.Length() - 1);
+        prop = s;
+      }
+      break;
+    }
+    case kpidIsDir:  prop = item.IsDir(); break;
+    case kpidSize:   prop = item.Size; break;
+    case kpidPackSize:  prop = item.PackSize; break;
+    case kpidCRC:  prop = (UInt32)item.CRC; break;
+    case kpidHostOS:  prop = GetOS(item.OsId); break;
+    case kpidMTime:
+    {
+      FILETIME utc;
+      UInt32 unixTime;
+      if (item.GetUnixTime(unixTime))
+        NTime::UnixTimeToFileTime(unixTime, utc);
+      else
+      {
+        FILETIME localFileTime;
+        if (DosTimeToFileTime(item.ModifiedTime, localFileTime))
+        {
+          if (!LocalFileTimeToFileTime(&localFileTime, &utc))
+            utc.dwHighDateTime = utc.dwLowDateTime = 0;
+        }
+        else
+          utc.dwHighDateTime = utc.dwLowDateTime = 0;
+      }
+      prop = utc;
+      break;
+    }
+    // case kpidAttrib:  prop = (UInt32)item.Attributes; break;
+    case kpidMethod:
+    {
+      char method2[kMethodIdSize + 1];
+      method2[kMethodIdSize] = 0;
+      memcpy(method2, item.Method, kMethodIdSize);
+      prop = method2;
+      break;
+    }
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+    const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback)
+{
+  COM_TRY_BEGIN
+  try
+  {
+    _items.Clear();
+    CInArchive archive;
+
+    UInt64 endPos = 0;
+    bool needSetTotal = true;
+
+    if (callback != NULL)
+    {
+      RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));
+      RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
+    }
+
+    RINOK(archive.Open(stream));
+    for (;;)
+    {
+      CItemEx item;
+      bool filled;
+      HRESULT result = archive.GetNextItem(filled, item);
+      if (result == S_FALSE)
+        return S_FALSE;
+      if (result != S_OK)
+        return S_FALSE;
+      if (!filled)
+        break;
+      _items.Add(item);
+      archive.Skip(item.PackSize);
+      if (callback != NULL)
+      {
+        if (needSetTotal)
+        {
+          RINOK(callback->SetTotal(NULL, &endPos));
+          needSetTotal = false;
+        }
+        if (_items.Size() % 100 == 0)
+        {
+          UInt64 numFiles = _items.Size();
+          UInt64 numBytes = item.DataPosition;
+          RINOK(callback->SetCompleted(&numFiles, &numBytes));
+        }
+      }
+    }
+    if (_items.IsEmpty())
+      return S_FALSE;
+
+    _stream = stream;
+  }
+  catch(...)
+  {
+    return S_FALSE;
+  }
+  COM_TRY_END
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _items.Clear();
+  _stream.Release();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testModeSpec, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool testMode = (testModeSpec != 0);
+  UInt64 totalUnPacked = 0, totalPacked = 0;
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _items.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+  {
+    const CItemEx &item = _items[allFilesMode ? i : indices[i]];
+    totalUnPacked += item.Size;
+    totalPacked += item.PackSize;
+  }
+  RINOK(extractCallback->SetTotal(totalUnPacked));
+
+  UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0;
+  UInt64 currentItemUnPacked, currentItemPacked;
+  
+  NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0;
+  CMyComPtr<ICompressCoder> lzhDecoder;
+  CMyComPtr<ICompressCoder> lzh1Decoder;
+  CMyComPtr<ICompressCoder> arj2Decoder;
+
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);
+  streamSpec->SetStream(_stream);
+
+  for (i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked,
+      currentTotalPacked += currentItemPacked)
+  {
+    currentItemUnPacked = 0;
+    currentItemPacked = 0;
+
+    lps->InSize = currentTotalPacked;
+    lps->OutSize = currentTotalUnPacked;
+    RINOK(lps->SetCur());
+
+    CMyComPtr<ISequentialOutStream> realOutStream;
+    Int32 askMode;
+    askMode = testMode ? NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    Int32 index = allFilesMode ? i : indices[i];
+    const CItemEx &item = _items[index];
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+    if (item.IsDir())
+    {
+      // if (!testMode)
+      {
+        RINOK(extractCallback->PrepareOperation(askMode));
+        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+      }
+      continue;
+    }
+
+    if (!testMode && !realOutStream)
+      continue;
+
+    RINOK(extractCallback->PrepareOperation(askMode));
+    currentItemUnPacked = item.Size;
+    currentItemPacked = item.PackSize;
+
+    {
+      COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
+      CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+      outStreamSpec->Init(realOutStream);
+      realOutStream.Release();
+      
+      UInt64 pos;
+      _stream->Seek(item.DataPosition, STREAM_SEEK_SET, &pos);
+
+      streamSpec->Init(item.PackSize);
+
+      HRESULT result = S_OK;
+      Int32 opRes = NExtract::NOperationResult::kOK;
+
+      if (item.IsCopyMethod())
+      {
+        result = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
+        if (result == S_OK && copyCoderSpec->TotalSize != item.PackSize)
+          result = S_FALSE;
+      }
+      else if (item.IsLh4GroupMethod())
+      {
+        if (!lzhDecoder)
+        {
+          lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder;
+          lzhDecoder = lzhDecoderSpec;
+        }
+        lzhDecoderSpec->SetDictionary(item.GetNumDictBits());
+        result = lzhDecoder->Code(inStream, outStream, NULL, &currentItemUnPacked, progress);
+      }
+      /*
+      else if (item.IsLh1GroupMethod())
+      {
+        if (!lzh1Decoder)
+        {
+          lzh1DecoderSpec = new NCompress::NLzh1::NDecoder::CCoder;
+          lzh1Decoder = lzh1DecoderSpec;
+        }
+        lzh1DecoderSpec->SetDictionary(item.GetNumDictBits());
+        result = lzh1Decoder->Code(inStream, outStream, NULL, &currentItemUnPacked, progress);
+      }
+      */
+      else
+        opRes = NExtract::NOperationResult::kUnSupportedMethod;
+
+      if (opRes == NExtract::NOperationResult::kOK)
+      {
+        if (result == S_FALSE)
+          opRes = NExtract::NOperationResult::kDataError;
+        else
+        {
+          RINOK(result);
+          if (outStreamSpec->GetCRC() != item.CRC)
+            opRes = NExtract::NOperationResult::kCRCError;
+        }
+      }
+      outStream.Release();
+      RINOK(extractCallback->SetOperationResult(opRes));
+    }
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"Lzh", L"lzh lha", 0, 6, { '-', 'l' }, 2, false, CreateArc, 0 };
+
+REGISTER_ARC(Lzh)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/LzmaHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/LzmaHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/LzmaHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/LzmaHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,430 @@
+// LzmaHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../Common/CreateCoder.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/LzmaDecoder.h"
+
+#include "Common/DummyOutStream.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NLzma {
+
+static bool CheckDicSize(const Byte *p)
+{
+  UInt32 dicSize = GetUi32(p);
+  for (int i = 1; i <= 30; i++)
+    if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i))
+      return true;
+  return (dicSize == 0xFFFFFFFF);
+}
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMethod, VT_BSTR}
+};
+
+struct CHeader
+{
+  UInt64 Size;
+  Byte FilterID;
+  Byte LzmaProps[5];
+
+  UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); }
+  bool HasSize() const { return (Size != (UInt64)(Int64)-1); }
+  bool Parse(const Byte *buf, bool isThereFilter);
+};
+
+bool CHeader::Parse(const Byte *buf, bool isThereFilter)
+{
+  FilterID = 0;
+  if (isThereFilter)
+    FilterID = buf[0];
+  const Byte *sig = buf + (isThereFilter ? 1 : 0);
+  for (int i = 0; i < 5; i++)
+    LzmaProps[i] = sig[i];
+  Size = GetUi64(sig + 5);
+  return
+    LzmaProps[0] < 5 * 5 * 9 &&
+    FilterID < 2 &&
+    (!HasSize() || Size < ((UInt64)1 << 56)) &&
+    CheckDicSize(LzmaProps + 1);
+}
+
+class CDecoder
+{
+  NCompress::NLzma::CDecoder *_lzmaDecoderSpec;
+  CMyComPtr<ICompressCoder> _lzmaDecoder;
+  CMyComPtr<ISequentialOutStream> _bcjStream;
+public:
+  ~CDecoder();
+  HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS
+      bool filtered, ISequentialInStream *inStream);
+
+  HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress);
+
+  UInt64 GetInputProcessedSize() const { return _lzmaDecoderSpec->GetInputProcessedSize(); }
+
+  void ReleaseInStream() { if (_lzmaDecoder) _lzmaDecoderSpec->ReleaseInStream(); }
+
+  HRESULT ReadInput(Byte *data, UInt32 size, UInt32 *processedSize)
+    { return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); }
+};
+
+static const UInt64 k_BCJ = 0x03030103;
+  
+HRESULT CDecoder::Create(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    bool filteredMode, ISequentialInStream *inStream)
+{
+  if (!_lzmaDecoder)
+  {
+    _lzmaDecoderSpec = new NCompress::NLzma::CDecoder;
+    _lzmaDecoder = _lzmaDecoderSpec;
+  }
+
+  if (filteredMode)
+  {
+    if (!_bcjStream)
+    {
+      CMyComPtr<ICompressCoder> coder;
+      RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false));
+      if (!coder)
+        return E_NOTIMPL;
+      coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream);
+      if (!_bcjStream)
+        return E_NOTIMPL;
+    }
+  }
+
+  return _lzmaDecoderSpec->SetInStream(inStream);
+}
+
+CDecoder::~CDecoder()
+{
+  ReleaseInStream();
+}
+
+HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
+    ICompressProgressInfo *progress)
+{
+  if (header.FilterID > 1)
+    return E_NOTIMPL;
+
+  {
+    CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
+    _lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
+    if (!setDecoderProperties)
+      return E_NOTIMPL;
+    RINOK(setDecoderProperties->SetDecoderProperties2(header.LzmaProps, 5));
+  }
+
+  CMyComPtr<ICompressSetOutStream> setOutStream;
+
+  bool filteredMode = (header.FilterID == 1);
+
+  if (filteredMode)
+  {
+    _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
+    if (!setOutStream)
+      return E_NOTIMPL;
+    RINOK(setOutStream->SetOutStream(outStream));
+    outStream = _bcjStream;
+  }
+
+  const UInt64 *Size = header.HasSize() ? &header.Size : NULL;
+  HRESULT res = _lzmaDecoderSpec->CodeResume(outStream, Size, progress);
+
+  if (filteredMode)
+  {
+    CMyComPtr<IOutStreamFlush> flush;
+    _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush);
+    if (flush)
+    {
+      HRESULT res2 = flush->Flush();
+      if (res == S_OK)
+        res = res2;
+    }
+    HRESULT res2 = setOutStream->ReleaseOutStream();
+    if (res == S_OK)
+      res = res2;
+  }
+  RINOK(res);
+
+  return S_OK;
+}
+
+
+class CHandler:
+  public IInArchive,
+  public IArchiveOpenSeq,
+  PUBLIC_ISetCompressCodecsInfo
+  public CMyUnknownImp
+{
+  CHeader _header;
+  bool _lzma86;
+  UInt64 _startPosition;
+  UInt64 _packSize;
+  bool _packSizeDefined;
+  CMyComPtr<IInStream> _stream;
+  CMyComPtr<ISequentialInStream> _seqStream;
+
+  DECL_EXTERNAL_CODECS_VARS
+  DECL_ISetCompressCodecsInfo
+
+public:
+  MY_QUERYINTERFACE_BEGIN2(IInArchive)
+  MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq)
+  QUERY_ENTRY_ISetCompressCodecsInfo
+  MY_QUERYINTERFACE_END
+  MY_ADDREF_RELEASE
+
+  INTERFACE_IInArchive(;)
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);
+
+  CHandler(bool lzma86) { _lzma86 = lzma86; }
+
+  unsigned GetHeaderSize() const { return 5 + 8 + (_lzma86 ? 1 : 0); }
+
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_NO_Table
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = 1;
+  return S_OK;
+}
+
+static void DictSizeToString(UInt32 value, char *s)
+{
+  for (int i = 0; i <= 31; i++)
+    if ((UInt32(1) << i) == value)
+    {
+      ::ConvertUInt32ToString(i, s);
+      return;
+    }
+  char c = 'b';
+  if ((value & ((1 << 20) - 1)) == 0)
+  {
+    value >>= 20;
+    c = 'm';
+  }
+  else if ((value & ((1 << 10) - 1)) == 0)
+  {
+    value >>= 10;
+    c = 'k';
+  }
+  ::ConvertUInt32ToString(value, s);
+  int p = MyStringLen(s);
+  s[p++] = c;
+  s[p++] = '\0';
+}
+
+static void MyStrCat(char *d, const char *s)
+{
+  MyStringCopy(d + MyStringLen(d), s);
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID,  PROPVARIANT *value)
+{
+  NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break;
+    case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;
+    case kpidMethod:
+      if (_stream)
+      {
+        char s[64];
+        s[0] = '\0';
+        if (_header.FilterID != 0)
+          MyStrCat(s, "BCJ ");
+        MyStrCat(s, "LZMA:");
+        DictSizeToString(_header.GetDicSize(), s + MyStringLen(s));
+        prop = s;
+      }
+      break;
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *)
+{
+  RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_startPosition));
+  
+  const UInt32 kBufSize = 1 + 5 + 8 + 1;
+  Byte buf[kBufSize];
+  
+  RINOK(ReadStream_FALSE(inStream, buf, kBufSize));
+  
+  if (!_header.Parse(buf, _lzma86))
+    return S_FALSE;
+  const Byte *start = buf + GetHeaderSize();
+  if (start[0] != 0)
+    return S_FALSE;
+  
+  UInt64 endPos;
+  RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos));
+  _packSize = endPos - _startPosition;
+  _packSizeDefined = true;
+  
+  _stream = inStream;
+  _seqStream = inStream;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
+{
+  Close();
+  _seqStream = stream;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _packSizeDefined = false;
+  _stream.Release();
+  _seqStream.Release();
+   return S_OK;
+}
+
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  if (numItems == 0)
+    return S_OK;
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
+    return E_INVALIDARG;
+
+  if (_stream)
+    extractCallback->SetTotal(_packSize);
+    
+  
+  CMyComPtr<ISequentialOutStream> realOutStream;
+  Int32 askMode = testMode ?
+      NExtract::NAskMode::kTest :
+      NExtract::NAskMode::kExtract;
+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
+  if (!testMode && !realOutStream)
+    return S_OK;
+  
+  extractCallback->PrepareOperation(askMode);
+
+  CDummyOutStream *outStreamSpec = new CDummyOutStream;
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+  outStreamSpec->SetStream(realOutStream);
+  outStreamSpec->Init();
+  realOutStream.Release();
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, true);
+
+  if (_stream)
+  {
+    RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));
+  }
+
+  CDecoder decoder;
+  HRESULT result = decoder.Create(
+      EXTERNAL_CODECS_VARS
+      _lzma86, _seqStream);
+  RINOK(result);
+ 
+  Int32 opRes = NExtract::NOperationResult::kOK;
+  bool firstItem = true;
+
+  for (;;)
+  {
+    lps->OutSize = outStreamSpec->GetSize();
+    lps->InSize = _packSize = decoder.GetInputProcessedSize();
+    _packSizeDefined = true;
+    RINOK(lps->SetCur());
+
+    CHeader st;
+
+    const UInt32 kBufSize = 1 + 5 + 8;
+    Byte buf[kBufSize];
+    const UInt32 headerSize = GetHeaderSize();
+    UInt32 processed;
+    RINOK(decoder.ReadInput(buf, headerSize, &processed));
+    if (processed != headerSize)
+      break;
+  
+    if (!st.Parse(buf, _lzma86))
+      break;
+    firstItem = false;
+
+    result = decoder.Code(st, outStream, progress);
+    if (result == E_NOTIMPL)
+    {
+      opRes = NExtract::NOperationResult::kUnSupportedMethod;
+      break;
+    }
+    if (result == S_FALSE)
+    {
+      opRes = NExtract::NOperationResult::kDataError;
+      break;
+    }
+    RINOK(result);
+  }
+  if (firstItem)
+    return E_FAIL;
+  outStream.Release();
+  return extractCallback->SetOperationResult(opRes);
+  COM_TRY_END
+}
+
+IMPL_ISetCompressCodecsInfo
+
+static IInArchive *CreateArc() { return new CHandler(false); }
+static IInArchive *CreateArc86() { return new CHandler(true); }
+
+namespace NLzmaAr {
+  
+static CArcInfo g_ArcInfo =
+  { L"lzma", L"lzma", 0, 0xA, { 0 }, 0, true, CreateArc, NULL };
+REGISTER_ARC(Lzma)
+
+}
+
+namespace NLzma86Ar {
+
+static CArcInfo g_ArcInfo =
+  { L"lzma86", L"lzma86", 0, 0xB, { 0 }, 0, true, CreateArc86, NULL };
+REGISTER_ARC(Lzma86)
+
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/MachoHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/MachoHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/MachoHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/MachoHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,500 @@
+// MachoHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/Buffer.h"
+#include "Common/ComTry.h"
+
+#include "Windows/PropVariantUtils.h"
+
+#include "../Common/LimitedStreams.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+
+static UInt32 Get32(const Byte *p, int be) { if (be) return GetBe32(p); return GetUi32(p); }
+static UInt64 Get64(const Byte *p, int be) { if (be) return GetBe64(p); return GetUi64(p); }
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NMacho {
+
+#define MACH_ARCH_ABI64 (1 << 24)
+#define MACH_MACHINE_386 7
+#define MACH_MACHINE_ARM 12
+#define MACH_MACHINE_SPARC 14
+#define MACH_MACHINE_PPC 18
+
+#define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC)
+#define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386)
+
+#define MACH_CMD_SEGMENT_32 1
+#define MACH_CMD_SEGMENT_64 0x19
+
+#define MACH_SECT_TYPE_MASK 0x000000FF
+#define MACH_SECT_ATTR_MASK 0xFFFFFF00
+
+#define MACH_SECT_ATTR_ZEROFILL 1
+
+static const char *g_SectTypes[] =
+{
+  "REGULAR",
+  "ZEROFILL",
+  "CSTRINGS",
+  "4BYTE_LITERALS",
+  "8BYTE_LITERALS",
+  "LITERAL_POINTERS",
+  "NON_LAZY_SYMBOL_POINTERS",
+  "LAZY_SYMBOL_POINTERS",
+  "SYMBOL_STUBS",
+  "MOD_INIT_FUNC_POINTERS",
+  "MOD_TERM_FUNC_POINTERS",
+  "COALESCED",
+  "GB_ZEROFILL",
+  "INTERPOSING",
+  "16BYTE_LITERALS"
+};
+
+static const char *g_FileTypes[] =
+{
+  "0",
+  "OBJECT",
+  "EXECUTE",
+  "FVMLIB",
+  "CORE",
+  "PRELOAD",
+  "DYLIB",
+  "DYLINKER",
+  "BUNDLE",
+  "DYLIB_STUB",
+  "DSYM"
+};
+
+static const CUInt32PCharPair g_Flags[] =
+{
+  { 31, "PURE_INSTRUCTIONS" },
+  { 30, "NO_TOC" },
+  { 29, "STRIP_STATIC_SYMS" },
+  { 28, "NO_DEAD_STRIP" },
+  { 27, "LIVE_SUPPORT" },
+  { 26, "SELF_MODIFYING_CODE" },
+  { 25, "DEBUG" },
+  { 10, "SOME_INSTRUCTIONS" },
+  {  9, "EXT_RELOC" },
+  {  8, "LOC_RELOC" }
+};
+
+static const CUInt32PCharPair g_MachinePairs[] =
+{
+  { MACH_MACHINE_386, "x86" },
+  { MACH_MACHINE_ARM, "ARM" },
+  { MACH_MACHINE_SPARC, "SPARC" },
+  { MACH_MACHINE_PPC, "PowerPC" },
+  { MACH_MACHINE_PPC64, "PowerPC 64-bit" },
+  { MACH_MACHINE_AMD64, "x64" }
+};
+
+static const int kNameSize = 16;
+
+struct CSegment
+{
+  char Name[kNameSize];
+};
+
+struct CSection
+{
+  char Name[kNameSize];
+  char SegName[kNameSize];
+  UInt64 Va;
+  UInt64 Pa;
+  UInt64 VSize;
+  UInt64 PSize;
+
+  UInt32 Flags;
+  int SegmentIndex;
+
+  bool IsDummy;
+
+  CSection(): IsDummy(false) {}
+  // UInt64 GetPackSize() const { return Flags == MACH_SECT_ATTR_ZEROFILL ? 0 : Size; }
+  UInt64 GetPackSize() const { return PSize; }
+};
+
+
+class CHandler:
+  public IInArchive,
+  public CMyUnknownImp
+{
+  CMyComPtr<IInStream> _inStream;
+  CObjectVector<CSegment> _segments;
+  CObjectVector<CSection> _sections;
+  bool _mode64;
+  bool _be;
+  UInt32 _machine;
+  UInt32 _type;
+  UInt32 _headersSize;
+  UInt64 _totalSize;
+  HRESULT Open2(ISequentialInStream *stream);
+  bool Parse(const Byte *buf, UInt32 size);
+public:
+  MY_UNKNOWN_IMP1(IInArchive)
+  INTERFACE_IInArchive(;)
+};
+
+bool CHandler::Parse(const Byte *buf, UInt32 size)
+{
+  bool mode64 = _mode64;
+  bool be = _be;
+
+  const Byte *bufStart = buf;
+  bool reduceCommands = false;
+  if (size < 512)
+    return false;
+
+  _machine = Get32(buf + 4, be);
+  _type = Get32(buf + 0xC, be);
+
+  UInt32 numCommands = Get32(buf + 0x10, be);
+  UInt32 commandsSize = Get32(buf + 0x14, be);
+  if (commandsSize > size)
+    return false;
+
+  if (commandsSize > (1 << 24) || numCommands > (1 << 18))
+    return false;
+
+  if (numCommands > 16)
+  {
+    reduceCommands = true;
+    numCommands = 16;
+  }
+
+  _headersSize = 0;
+
+  buf += 0x1C;
+  size -= 0x1C;
+
+  if (mode64)
+  {
+    buf += 4;
+    size -= 4;
+  }
+
+  _totalSize = (UInt32)(buf - bufStart);
+  if (commandsSize < size)
+    size = commandsSize;
+
+  for (UInt32 cmdIndex = 0; cmdIndex < numCommands; cmdIndex++)
+  {
+    if (size < 8)
+      return false;
+    UInt32 cmd = Get32(buf, be);
+    UInt32 cmdSize = Get32(buf + 4, be);
+    if (size < cmdSize)
+      return false;
+    if (cmd == MACH_CMD_SEGMENT_32 || cmd == MACH_CMD_SEGMENT_64)
+    {
+      UInt32 offs = (cmd == MACH_CMD_SEGMENT_64) ? 0x48 : 0x38;
+      if (cmdSize < offs)
+        break;
+
+      UInt64 vmAddr, vmSize, phAddr, phSize;
+
+      {
+        if (cmd == MACH_CMD_SEGMENT_64)
+        {
+          vmAddr = Get64(buf + 0x18, be);
+          vmSize = Get64(buf + 0x20, be);
+          phAddr = Get64(buf + 0x28, be);
+          phSize = Get64(buf + 0x30, be);
+        }
+        else
+        {
+          vmAddr = Get32(buf + 0x18, be);
+          vmSize = Get32(buf + 0x1C, be);
+          phAddr = Get32(buf + 0x20, be);
+          phSize = Get32(buf + 0x24, be);
+        }
+        {
+          UInt64 totalSize = phAddr + phSize;
+          if (totalSize > _totalSize)
+            _totalSize = totalSize;
+        }
+      }
+      
+      CSegment seg;
+      memcpy(seg.Name, buf + 8, kNameSize);
+      _segments.Add(seg);
+
+      UInt32 numSections = Get32(buf + offs - 8, be);
+      if (numSections > (1 << 8))
+        return false;
+
+      if (numSections == 0)
+      {
+        CSection section;
+        section.IsDummy = true;
+        section.SegmentIndex = _segments.Size() - 1;
+          section.Va = vmAddr;
+          section.PSize = phSize;
+          section.VSize = vmSize;
+          section.Pa = phAddr;
+          section.Flags = 0;
+        _sections.Add(section);
+      }
+      else do
+      {
+        CSection section;
+        UInt32 headerSize = (cmd == MACH_CMD_SEGMENT_64) ? 0x50 : 0x44;
+        const Byte *p = buf + offs;
+        if (cmdSize - offs < headerSize)
+          break;
+        if (cmd == MACH_CMD_SEGMENT_64)
+        {
+          section.Va = Get64(p + 0x20, be);
+          section.VSize = Get64(p + 0x28, be);
+          section.Pa = Get32(p + 0x30, be);
+          section.Flags = Get32(p + 0x40, be);
+        }
+        else
+        {
+          section.Va = Get32(p + 0x20, be);
+          section.VSize = Get32(p + 0x24, be);
+          section.Pa = Get32(p + 0x28, be);
+          section.Flags = Get32(p + 0x38, be);
+        }
+        if (section.Flags == MACH_SECT_ATTR_ZEROFILL)
+          section.PSize = 0;
+        else
+          section.PSize = section.VSize;
+        memcpy(section.Name, p, kNameSize);
+        memcpy(section.SegName, p + kNameSize, kNameSize);
+        section.SegmentIndex = _segments.Size() - 1;
+        _sections.Add(section);
+        offs += headerSize;
+      }
+      while (--numSections);
+
+      if (offs != cmdSize)
+        return false;
+    }
+    buf += cmdSize;
+    size -= cmdSize;
+  }
+  _headersSize = (UInt32)(buf - bufStart);
+  return reduceCommands || (size == 0);
+}
+
+static STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidCpu, VT_BSTR},
+  { NULL, kpidBit64, VT_BOOL},
+  { NULL, kpidBigEndian, VT_BOOL},
+  { NULL, kpidCharacts, VT_BSTR},
+  { NULL, kpidPhySize, VT_UI8},
+  { NULL, kpidHeadersSize, VT_UI4}
+};
+
+static STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidCharacts, VT_BSTR},
+  { NULL, kpidOffset, VT_UI8},
+  { NULL, kpidVa, VT_UI8}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidCpu:  PAIR_TO_PROP(g_MachinePairs, _machine, prop); break;
+    case kpidCharacts:  TYPE_TO_PROP(g_FileTypes, _type, prop); break;
+    case kpidPhySize:  prop = _totalSize; break;
+    case kpidHeadersSize:  prop = _headersSize; break;
+    case kpidBit64:  if (_mode64) prop = _mode64; break;
+    case kpidBigEndian:  if (_be) prop = _be; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+static AString GetName(const char *name)
+{
+  char res[kNameSize + 1];
+  memcpy(res, name, kNameSize);
+  res[kNameSize] = 0;
+  return res;
+}
+
+static AString SectFlagsToString(UInt32 flags)
+{
+  AString res = TypeToString(g_SectTypes, sizeof(g_SectTypes) / sizeof(g_SectTypes[0]),
+      flags & MACH_SECT_TYPE_MASK);
+  AString s = FlagsToString(g_Flags, sizeof(g_Flags) / sizeof(g_Flags[0]),
+      flags & MACH_SECT_ATTR_MASK);
+  if (!s.IsEmpty())
+  {
+    res += ' ';
+    res += s;
+  }
+  return res;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NCOM::CPropVariant prop;
+  const CSection &item = _sections[index];
+  switch(propID)
+  {
+    case kpidPath:
+    {
+      AString s = GetName(_segments[item.SegmentIndex].Name);
+      if (!item.IsDummy)
+        s += GetName(item.Name);
+      StringToProp(s, prop);
+      break;
+    }
+    case kpidSize:  /* prop = (UInt64)item.VSize; break; */
+    case kpidPackSize:  prop = (UInt64)item.GetPackSize(); break;
+    case kpidCharacts:  if (!item.IsDummy) StringToProp(SectFlagsToString(item.Flags), prop); break;
+    case kpidOffset:  prop = item.Pa; break;
+    case kpidVa:  prop = item.Va; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+HRESULT CHandler::Open2(ISequentialInStream *stream)
+{
+  const UInt32 kBufSize = 1 << 18;
+  const UInt32 kSigSize = 4;
+
+  CByteBuffer buffer;
+  buffer.SetCapacity(kBufSize);
+  Byte *buf = buffer;
+
+  size_t processed = kSigSize;
+  RINOK(ReadStream_FALSE(stream, buf, processed));
+  UInt32 sig = GetUi32(buf);
+  bool be, mode64;
+  switch(sig)
+  {
+    case 0xCEFAEDFE:  be = true; mode64 = false; break;
+    case 0xCFFAEDFE:  be = true; mode64 = true; break;
+    case 0xFEEDFACE:  be = false; mode64 = false; break;
+    case 0xFEEDFACF:  be = false; mode64 = true; break;
+    default: return S_FALSE;
+  }
+  processed = kBufSize - kSigSize;
+  RINOK(ReadStream(stream, buf + kSigSize, &processed));
+  _mode64 = mode64;
+  _be = be;
+  return Parse(buf, (UInt32)processed + kSigSize) ? S_OK : S_FALSE;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *inStream,
+    const UInt64 * /* maxCheckStartPosition */,
+    IArchiveOpenCallback * /* openArchiveCallback */)
+{
+  COM_TRY_BEGIN
+  Close();
+  RINOK(Open2(inStream));
+  _inStream = inStream;
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _inStream.Release();
+  _sections.Clear();
+  _segments.Clear();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _sections.Size();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _sections.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt64 totalSize = 0;
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+    totalSize += _sections[allFilesMode ? i : indices[i]].GetPackSize();
+  extractCallback->SetTotal(totalSize);
+
+  UInt64 currentTotalSize = 0;
+  UInt64 currentItemSize;
+  
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);
+  streamSpec->SetStream(_inStream);
+
+  for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
+  {
+    lps->InSize = lps->OutSize = currentTotalSize;
+    RINOK(lps->SetCur());
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    UInt32 index = allFilesMode ? i : indices[i];
+    const CSection &item = _sections[index];
+    currentItemSize = item.GetPackSize();
+
+    CMyComPtr<ISequentialOutStream> outStream;
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));
+    if (!testMode && !outStream)
+      continue;
+    
+    RINOK(extractCallback->PrepareOperation(askMode));
+    RINOK(_inStream->Seek(item.Pa, STREAM_SEEK_SET, NULL));
+    streamSpec->Init(currentItemSize);
+    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
+    outStream.Release();
+    RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ?
+        NExtract::NOperationResult::kOK:
+        NExtract::NOperationResult::kDataError));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"MachO", L"", 0, 0xDF, { 0 }, 0, false, CreateArc, 0 };
+
+REGISTER_ARC(Macho)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/MbrHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/MbrHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/MbrHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/MbrHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,507 @@
+// MbrHandler.cpp
+
+#include "StdAfx.h"
+
+// #define SHOW_DEBUG_INFO
+
+#ifdef SHOW_DEBUG_INFO
+#include <stdio.h>
+#endif
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/Buffer.h"
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+#include "Common/MyString.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../Common/LimitedStreams.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+
+#ifdef SHOW_DEBUG_INFO
+#define PRF(x) x
+#else
+#define PRF(x)
+#endif
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NMbr {
+
+struct CChs
+{
+  Byte Head;
+  Byte SectCyl;
+  Byte Cyl8;
+  
+  UInt32 GetSector() const { return SectCyl & 0x3F; }
+  UInt32 GetCyl() const { return ((UInt32)SectCyl >> 6 << 8) | Cyl8; }
+  void ToString(NCOM::CPropVariant &prop) const;
+
+  void Parse(const Byte *p)
+  {
+    Head = p[0];
+    SectCyl = p[1];
+    Cyl8 = p[2];
+  }
+  bool Check() const { return GetSector() > 0; }
+};
+
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+
+static int CompareChs(const CChs &c1, const CChs &c2)
+{
+  RINOZ(MyCompare(c1.GetCyl(), c2.GetCyl()));
+  RINOZ(MyCompare(c1.Head, c2.Head));
+  return MyCompare(c1.GetSector(), c2.GetSector());
+}
+
+static void AddUIntToString(UInt32 val, AString &res)
+{
+  char s[16];
+  ConvertUInt32ToString(val, s);
+  res += s;
+}
+
+void CChs::ToString(NCOM::CPropVariant &prop) const
+{
+  AString s;
+  AddUIntToString(GetCyl(), s);
+  s += '-';
+  AddUIntToString(Head, s);
+  s += '-';
+  AddUIntToString(GetSector(), s);
+  prop = s;
+}
+
+struct CPartition
+{
+  Byte Status;
+  CChs BeginChs;
+  Byte Type;
+  CChs EndChs;
+  UInt32 Lba;
+  UInt32 NumBlocks;
+
+  CPartition() { memset (this, 0, sizeof(*this)); }
+  
+  bool IsEmpty() const { return Type == 0; }
+  bool IsExtended() const { return Type == 5 || Type == 0xF; }
+  UInt32 GetLimit() const { return Lba + NumBlocks; }
+  // bool IsActive() const { return Status == 0x80; }
+  UInt64 GetPos() const { return (UInt64)Lba * 512; }
+  UInt64 GetSize() const { return (UInt64)NumBlocks * 512; }
+
+  bool CheckLbaLimits() const { return (UInt32)0xFFFFFFFF - Lba >= NumBlocks; }
+  bool Parse(const Byte *p)
+  {
+    Status = p[0];
+    BeginChs.Parse(p + 1);
+    Type = p[4];
+    EndChs.Parse(p + 5);
+    Lba = GetUi32(p + 8);
+    NumBlocks = GetUi32(p + 12);
+    if (Type == 0)
+      return true;
+    if (Status != 0 && Status != 0x80)
+      return false;
+    return
+       BeginChs.Check() &&
+       EndChs.Check() &&
+       CompareChs(BeginChs, EndChs) <= 0 &&
+       NumBlocks > 0 &&
+       CheckLbaLimits();
+  }
+
+  #ifdef SHOW_DEBUG_INFO
+  void Print() const
+  {
+    NCOM::CPropVariant prop, prop2;
+    BeginChs.ToString(prop);
+    EndChs.ToString(prop2);
+    printf("   %2x %2x %8X %8X %12S %12S", (int)Status, (int)Type, Lba, NumBlocks, prop.bstrVal, prop2.bstrVal);
+  }
+  #endif
+};
+
+struct CPartType
+{
+  UInt32 Id;
+  const char *Ext;
+  const char *Name;
+};
+
+static const char *kFat = "fat";
+
+static const CPartType kPartTypes[] =
+{
+  { 0x01, kFat, "FAT12" },
+  { 0x04, kFat, "FAT16 DOS 3.0+" },
+  { 0x05, 0, "Extended" },
+  { 0x06, kFat, "FAT16 DOS 3.31+" },
+  { 0x07, "ntfs", "NTFS" },
+  { 0x0B, kFat, "FAT32" },
+  { 0x0C, kFat, "FAT32-LBA" },
+  { 0x0E, kFat, "FAT16-LBA" },
+  { 0x0F, 0, "Extended-LBA" },
+  { 0x11, kFat, "FAT12-Hidden" },
+  { 0x14, kFat, "FAT16-Hidden < 32 MB" },
+  { 0x16, kFat, "FAT16-Hidden >= 32 MB" },
+  { 0x1B, kFat, "FAT32-Hidden" },
+  { 0x1C, kFat, "FAT32-LBA-Hidden" },
+  { 0x1E, kFat, "FAT16-LBA-WIN95-Hidden" },
+  { 0x82, 0, "Solaris x86 / Linux swap" },
+  { 0x83, 0, "Linux" },
+  { 0xBE, 0, "Solaris 8 boot" },
+  { 0xBF, 0, "New Solaris x86" },
+  { 0xC2, 0, "Linux-Hidden" },
+  { 0xC3, 0, "Linux swap-Hidden" },
+  { 0xEE, 0, "EFI-MBR" },
+  { 0xEE, 0, "EFI" }
+};
+
+static int FindPartType(UInt32 type)
+{
+  for (int i = 0; i < sizeof(kPartTypes) / sizeof(kPartTypes[0]); i++)
+    if (kPartTypes[i].Id == type)
+      return i;
+  return -1;
+}
+
+struct CItem
+{
+  bool IsReal;
+  bool IsPrim;
+  UInt64 Size;
+  CPartition Part;
+};
+
+class CHandler:
+  public IInArchive,
+  public IInArchiveGetStream,
+  public CMyUnknownImp
+{
+  CMyComPtr<IInStream> _stream;
+  CObjectVector<CItem> _items;
+  UInt64 _totalSize;
+  CByteBuffer _buffer;
+
+  HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level);
+public:
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+  INTERFACE_IInArchive(;)
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+};
+
+HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, int level)
+{
+  if (level >= 128 || _items.Size() >= 128)
+    return S_FALSE;
+
+  const int kNumHeaderParts = 4;
+  CPartition parts[kNumHeaderParts];
+
+  {
+    const UInt32 kSectorSize = 512;
+    _buffer.SetCapacity(kSectorSize);
+    Byte *buf = _buffer;
+    UInt64 newPos = (UInt64)lba << 9;
+    if (newPos + 512 > _totalSize)
+      return S_FALSE;
+    RINOK(stream->Seek(newPos, STREAM_SEEK_SET, NULL));
+    RINOK(ReadStream_FALSE(stream, buf, kSectorSize));
+    
+    if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)
+      return S_FALSE;
+    
+    for (int i = 0; i < kNumHeaderParts; i++)
+      if (!parts[i].Parse(buf + 0x1BE + 16 * i))
+        return S_FALSE;
+  }
+
+  PRF(printf("\n# %8X", lba));
+
+  UInt32 limLba = lba + 1;
+  if (limLba == 0)
+    return S_FALSE;
+
+  for (int i = 0; i < kNumHeaderParts; i++)
+  {
+    CPartition &part = parts[i];
+    
+    if (part.IsEmpty())
+      continue;
+    PRF(printf("\n   %2d ", (int)level));
+    #ifdef SHOW_DEBUG_INFO
+    part.Print();
+    #endif
+    
+    int numItems = _items.Size();
+    UInt32 newLba = lba + part.Lba;
+    
+    if (part.IsExtended())
+    {
+      // if (part.Type == 5) // Check it!
+      newLba = baseLba + part.Lba;
+      if (newLba < limLba)
+        return S_FALSE;
+      HRESULT res = ReadTables(stream, level < 1 ? newLba : baseLba, newLba, level + 1);
+      if (res != S_FALSE && res != S_OK)
+        return res;
+    }
+    if (newLba < limLba)
+      return S_FALSE;
+    part.Lba = newLba;
+    if (!part.CheckLbaLimits())
+      return S_FALSE;
+
+    CItem n;
+    n.Part = part;
+    bool addItem = false;
+    if (numItems == _items.Size())
+    {
+      n.IsPrim = (level == 0);
+      n.IsReal = true;
+      addItem = true;
+    }
+    else
+    {
+      const CItem &back = _items.Back();
+      UInt32 backLimit = back.Part.GetLimit();
+      UInt32 partLimit = part.GetLimit();
+      if (backLimit < partLimit)
+      {
+        n.IsReal = false;
+        n.Part.Lba = backLimit;
+        n.Part.NumBlocks = partLimit - backLimit;
+        addItem = true;
+      }
+    }
+    if (addItem)
+    {
+      if (n.Part.GetLimit() < limLba)
+        return S_FALSE;
+      limLba = n.Part.GetLimit();
+      n.Size = n.Part.GetSize();
+      _items.Add(n);
+    }
+  }
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+    const UInt64 * /* maxCheckStartPosition */,
+    IArchiveOpenCallback * /* openArchiveCallback */)
+{
+  COM_TRY_BEGIN
+  Close();
+  RINOK(stream->Seek(0, STREAM_SEEK_END, &_totalSize));
+  RINOK(ReadTables(stream, 0, 0, 0));
+  if (_items.IsEmpty())
+    return S_FALSE;
+  UInt32 lbaLimit = _items.Back().Part.GetLimit();
+  UInt64 lim = (UInt64)lbaLimit << 9;
+  if (lim < _totalSize)
+  {
+    CItem n;
+    n.Part.Lba = lbaLimit;
+    n.Size = _totalSize - lim;
+    n.IsReal = false;
+    _items.Add(n);
+  }
+  _stream = stream;
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _items.Clear();
+  _stream.Release();
+  return S_OK;
+}
+
+enum
+{
+  kpidPrimary = kpidUserDefined,
+  kpidBegChs,
+  kpidEndChs
+};
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidFileSystem, VT_BSTR},
+  { NULL, kpidOffset, VT_UI8},
+  { L"Primary", kpidPrimary, VT_BOOL},
+  { L"Begin CHS", kpidBegChs, VT_BSTR},
+  { L"End CHS", kpidEndChs, VT_BSTR}
+};
+
+IMP_IInArchive_Props_WITH_NAME
+IMP_IInArchive_ArcProps_NO_Table
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidMainSubfile:
+    {
+      int mainIndex = -1;
+      for (int i = 0; i < _items.Size(); i++)
+        if (_items[i].IsReal)
+        {
+          if (mainIndex >= 0)
+          {
+            mainIndex = -1;
+            break;
+          }
+          mainIndex = i;
+        }
+      if (mainIndex >= 0)
+        prop = (UInt32)mainIndex;
+      break;
+    }
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _items.Size();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NCOM::CPropVariant prop;
+
+  const CItem &item = _items[index];
+  const CPartition &part = item.Part;
+  switch(propID)
+  {
+    case kpidPath:
+    {
+      AString s;
+      AddUIntToString(index, s);
+      if (item.IsReal)
+      {
+        int typeIndex = FindPartType(part.Type);
+        s += '.';
+        const char *ext = "img";
+        if (typeIndex >= 0 && kPartTypes[typeIndex].Ext != 0)
+          ext = kPartTypes[typeIndex].Ext;
+        s += ext;
+      }
+      prop = s;
+      break;
+    }
+    case kpidFileSystem:
+      if (item.IsReal)
+      {
+        char s[32];
+        ConvertUInt32ToString(part.Type, s);
+        const char *res = s;
+        int typeIndex = FindPartType(part.Type);
+        if (typeIndex >= 0 && kPartTypes[typeIndex].Name)
+          res = kPartTypes[typeIndex].Name;
+        prop = res;
+      }
+      break;
+    case kpidSize: prop = item.Size; break;;
+    case kpidPackSize: prop = item.Size; break;
+    case kpidOffset: prop = part.GetPos(); break;
+    case kpidPrimary: if (item.IsReal) prop = item.IsPrim; break;
+    case kpidBegChs: if (item.IsReal) part.BeginChs.ToString(prop); break;
+    case kpidEndChs: if (item.IsReal) part.EndChs.ToString(prop); break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _items.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt64 totalSize = 0;
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+    totalSize += _items[allFilesMode ? i : indices[i]].Size;
+  extractCallback->SetTotal(totalSize);
+
+  totalSize = 0;
+  
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);
+  streamSpec->SetStream(_stream);
+
+  for (i = 0; i < numItems; i++)
+  {
+    lps->InSize = totalSize;
+    lps->OutSize = totalSize;
+    RINOK(lps->SetCur());
+    CMyComPtr<ISequentialOutStream> outStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    Int32 index = allFilesMode ? i : indices[i];
+    const CItem &item = _items[index];
+    const CPartition &part = item.Part;
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));
+    totalSize += item.Size;
+    if (!testMode && !outStream)
+      continue;
+    RINOK(extractCallback->PrepareOperation(askMode));
+
+    RINOK(_stream->Seek(part.GetPos(), STREAM_SEEK_SET, NULL));
+    streamSpec->Init(item.Size);
+    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
+    outStream.Release();
+    RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == item.Size ?
+        NExtract::NOperationResult::kOK:
+        NExtract::NOperationResult::kDataError));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+  COM_TRY_BEGIN
+  const CItem &item = _items[index];
+  return CreateLimitedInStream(_stream, item.Part.GetPos(), item.Size, stream);
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"MBR", L"mbr", 0, 0xDB, { 1, 1, 0 }, 3, false, CreateArc, 0 };
+
+REGISTER_ARC(Mbr)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/MslzHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/MslzHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/MslzHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/MslzHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,257 @@
+// MslzHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/ComTry.h"
+#include "Common/MyString.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../Common/InBuffer.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "Common/DummyOutStream.h"
+
+namespace NArchive {
+namespace NMslz {
+
+class CHandler:
+  public IInArchive,
+  public CMyUnknownImp
+{
+  CMyComPtr<IInStream> _stream;
+  UInt32 _size;
+  UInt64 _packSize;
+  UString _name;
+public:
+  MY_UNKNOWN_IMP1(IInArchive)
+  INTERFACE_IInArchive(;)
+};
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_NO
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = 1;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidPath: if (!_name.IsEmpty()) prop = _name; break;
+    case kpidSize: prop = _size; break;
+    case kpidPackSize: prop = _packSize; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+static const unsigned kSignatureSize = 9;
+static const unsigned kHeaderSize = kSignatureSize + 1 + 4;
+#define MSLZ_SIGNATURE { 0x53, 0x5A, 0x44, 0x44, 0x88, 0xF0, 0x27, 0x33, 0x41 }
+// old signature: 53 5A 20 88 F0 27 33
+static const Byte signature[kSignatureSize] = MSLZ_SIGNATURE;
+
+static const wchar_t *g_Exts[] =
+{
+  L"dll",
+  L"exe",
+  L"kmd",
+  L"sys"
+};
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */,
+    IArchiveOpenCallback *callback)
+{
+  COM_TRY_BEGIN
+  {
+    Close();
+    Byte buffer[kHeaderSize];
+    RINOK(ReadStream_FALSE(stream, buffer, kHeaderSize));
+    if (memcmp(buffer, signature, kSignatureSize) != 0)
+      return S_FALSE;
+    _size = GetUi32(buffer + 10);
+    if (_size > 0xFFFFFFE0)
+      return S_FALSE;
+    RINOK(stream->Seek(0, STREAM_SEEK_END, &_packSize));
+
+    if (callback)
+    {
+      CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
+      callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
+      if (openVolumeCallback)
+      {
+        NWindows::NCOM::CPropVariant prop;
+        if (openVolumeCallback->GetProperty(kpidName, &prop) == S_OK && prop.vt == VT_BSTR)
+        {
+          UString baseName = prop.bstrVal;
+          if (!baseName.IsEmpty() && baseName.Back() == L'_')
+          {
+            baseName.DeleteBack();
+            Byte replaceByte = buffer[kSignatureSize];
+            if (replaceByte == 0)
+            {
+              for (int i = 0; i < sizeof(g_Exts) / sizeof(g_Exts[0]); i++)
+              {
+                UString s = g_Exts[i];
+                int len = s.Length();
+                Byte b = (Byte)s.Back();
+                s.DeleteBack();
+                if (baseName.Length() >= len &&
+                    baseName[baseName.Length() - len] == '.' &&
+                    s.CompareNoCase(baseName.Right(len - 1)) == 0)
+                {
+                  replaceByte = b;
+                  break;
+                }
+              }
+            }
+            if (replaceByte >= 0x20 && replaceByte < 0x80)
+              _name = baseName + (wchar_t)replaceByte;
+          }
+        }
+      }
+    }
+    _stream = stream;
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _stream.Release();
+  _name.Empty();
+  return S_OK;
+}
+
+// MslzDec is modified LZSS algorithm of Haruhiko Okumura:
+//   maxLen = 18; Okumura
+//   maxLen = 16; MS
+
+#define PROGRESS_AND_WRITE \
+  if ((dest & kMask) == 0) { RINOK(WriteStream(outStream, buf, kBufSize)); \
+    if ((dest & ((1 << 20) - 1)) == 0) \
+    { UInt64 inSize = inStream.GetProcessedSize(); UInt64 outSize = dest; \
+      RINOK(progress->SetRatioInfo(&inSize, &outSize)); }}
+
+static HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UInt32 unpackSize, ICompressProgressInfo *progress)
+{
+  const unsigned kBufSize = (1 << 12);
+  const unsigned kMask = kBufSize - 1;
+  Byte buf[kBufSize];
+  UInt32 dest = 0;
+  memset(buf, ' ', kBufSize);
+  while (dest < unpackSize)
+  {
+    Byte b;
+    if (!inStream.ReadByte(b))
+      return S_FALSE;
+    for (unsigned mask = (unsigned)b | 0x100; mask > 1 && dest < unpackSize; mask >>= 1)
+    {
+      if (!inStream.ReadByte(b))
+        return S_FALSE;
+      if (mask & 1)
+      {
+        buf[dest++ & kMask] = b;
+        PROGRESS_AND_WRITE
+      }
+      else
+      {
+        Byte b1;
+        if (!inStream.ReadByte(b1))
+          return S_FALSE;
+        const unsigned kMaxLen = 16; // 18 in Okumura's code.
+        unsigned src = (((((unsigned)b1 & 0xF0) << 4) | b) + kMaxLen) & kMask;
+        unsigned len = (b1 & 0xF) + 3;
+        if (len > kMaxLen || dest + len > unpackSize)
+          return S_FALSE;
+        do
+        {
+          buf[dest++ & kMask] = buf[src++ & kMask];
+          PROGRESS_AND_WRITE
+        }
+        while (--len != 0);
+      }
+    }
+  }
+  return WriteStream(outStream, buf, dest & kMask);
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  if (numItems == 0)
+    return S_OK;
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
+    return E_INVALIDARG;
+
+  extractCallback->SetTotal(_size);
+
+  CMyComPtr<ISequentialOutStream> realOutStream;
+  Int32 askMode = testMode ?
+      NExtract::NAskMode::kTest :
+      NExtract::NAskMode::kExtract;
+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
+  if (!testMode && !realOutStream)
+    return S_OK;
+
+  extractCallback->PrepareOperation(askMode);
+
+  CDummyOutStream *outStreamSpec = new CDummyOutStream;
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+  outStreamSpec->SetStream(realOutStream);
+  outStreamSpec->Init();
+  realOutStream.Release();
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+  
+  RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
+  CInBuffer s;
+  if (!s.Create(1 << 20))
+    return E_OUTOFMEMORY;
+  s.SetStream(_stream);
+  s.Init();
+  Byte buffer[kHeaderSize];
+  Int32 opRes = NExtract::NOperationResult::kDataError;
+  if (s.ReadBytes(buffer, kHeaderSize) == kHeaderSize)
+  {
+    HRESULT result = MslzDec(s, outStream, _size, progress);
+    if (result == S_OK)
+      opRes = NExtract::NOperationResult::kOK;
+    else if (result != S_FALSE)
+      return result;
+  }
+  outStream.Release();
+  return extractCallback->SetOperationResult(opRes);
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"MsLZ", L"", 0, 0xD5, MSLZ_SIGNATURE, kSignatureSize, false, CreateArc, 0 };
+
+REGISTER_ARC(Mslz)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/MubHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/MubHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/MubHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/MubHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,266 @@
+// MubHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/ComTry.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../Common/LimitedStreams.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+
+#define Get32(p) GetBe32(p)
+
+namespace NArchive {
+namespace NMub {
+
+struct CItem
+{
+  UInt32 Type;
+  UInt32 SubType;
+  UInt64 Offset;
+  UInt64 Size;
+  UInt32 Align;
+  bool IsTail;
+};
+
+const UInt32 kNumFilesMax = 10;
+
+class CHandler:
+  public IInArchive,
+  public IInArchiveGetStream,
+  public CMyUnknownImp
+{
+  UInt64 _startPos;
+  CMyComPtr<IInStream> _stream;
+  UInt32 _numItems;
+  CItem _items[kNumFilesMax + 1];
+  HRESULT Open2(IInStream *stream);
+public:
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+  INTERFACE_IInArchive(;)
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+};
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidSize, VT_UI8}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_NO
+
+#define MACH_ARCH_ABI64  0x1000000
+#define MACH_MACHINE_386   7
+#define MACH_MACHINE_ARM   12
+#define MACH_MACHINE_SPARC 14
+#define MACH_MACHINE_PPC   18
+
+#define MACH_MACHINE_PPC64 (MACH_MACHINE_PPC | MACH_ARCH_ABI64)
+#define MACH_MACHINE_AMD64 (MACH_MACHINE_386 | MACH_ARCH_ABI64)
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  NWindows::NCOM::CPropVariant prop;
+  const CItem &item = _items[index];
+  switch(propID)
+  {
+    case kpidExtension:
+    {
+      const wchar_t *ext;
+      if (item.IsTail)
+        ext = L"tail";
+      else
+      {
+        switch(item.Type)
+        {
+          case MACH_MACHINE_386:   ext = L"86";    break;
+          case MACH_MACHINE_ARM:   ext = L"arm";   break;
+          case MACH_MACHINE_SPARC: ext = L"sparc"; break;
+          case MACH_MACHINE_PPC:   ext = L"ppc";   break;
+          case MACH_MACHINE_PPC64: ext = L"ppc64"; break;
+          case MACH_MACHINE_AMD64: ext = L"x64";   break;
+          default: ext = L"unknown"; break;
+        }
+      }
+      prop = ext;
+      break;
+    }
+    case kpidSize:
+    case kpidPackSize:
+      prop = (UInt64)item.Size;
+      break;
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+#define MACH_TYPE_ABI64 (1 << 24)
+#define MACH_SUBTYPE_ABI64 (1 << 31)
+
+HRESULT CHandler::Open2(IInStream *stream)
+{
+  RINOK(stream->Seek(0, STREAM_SEEK_SET, &_startPos));
+
+  const UInt32 kHeaderSize = 8;
+  const UInt32 kRecordSize = 5 * 4;
+  const UInt32 kBufSize = kHeaderSize + kNumFilesMax * kRecordSize;
+  Byte buf[kBufSize];
+  size_t processed = kBufSize;
+  RINOK(ReadStream(stream, buf, &processed));
+  if (processed < kHeaderSize)
+    return S_FALSE;
+  UInt32 num = Get32(buf + 4);
+  if (Get32(buf) != 0xCAFEBABE || num > kNumFilesMax || processed < kHeaderSize + num * kRecordSize)
+    return S_FALSE;
+  UInt64 endPosMax = kHeaderSize;
+  for (UInt32 i = 0; i < num; i++)
+  {
+    const Byte *p = buf + kHeaderSize + i * kRecordSize;
+    CItem &sb = _items[i];
+    sb.IsTail = false;
+    sb.Type = Get32(p);
+    sb.SubType = Get32(p + 4);
+    sb.Offset = Get32(p + 8);
+    sb.Size = Get32(p + 12);
+    sb.Align = Get32(p + 16);
+
+    if ((sb.Type & ~MACH_TYPE_ABI64) >= 0x100 ||
+        (sb.SubType & ~MACH_SUBTYPE_ABI64) >= 0x100 ||
+        sb.Align > 31)
+      return S_FALSE;
+
+    UInt64 endPos = (UInt64)sb.Offset + sb.Size;
+    if (endPos > endPosMax)
+      endPosMax = endPos;
+  }
+  UInt64 fileSize;
+  RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));
+  fileSize -= _startPos;
+  _numItems = num;
+  if (fileSize > endPosMax)
+  {
+    CItem &sb = _items[_numItems++];
+    sb.IsTail = true;
+    sb.Type = 0;
+    sb.SubType = 0;
+    sb.Offset = endPosMax;
+    sb.Size = fileSize - endPosMax;
+    sb.Align = 0;
+  }
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *inStream,
+    const UInt64 * /* maxCheckStartPosition */,
+    IArchiveOpenCallback * /* openArchiveCallback */)
+{
+  COM_TRY_BEGIN
+  Close();
+  try
+  {
+    if (Open2(inStream) != S_OK)
+      return S_FALSE;
+    _stream = inStream;
+  }
+  catch(...) { return S_FALSE; }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _stream.Release();
+  _numItems = 0;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _numItems;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _numItems;
+  if (numItems == 0)
+    return S_OK;
+  UInt64 totalSize = 0;
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+    totalSize += _items[allFilesMode ? i : indices[i]].Size;
+  extractCallback->SetTotal(totalSize);
+
+  UInt64 currentTotalSize = 0;
+  
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);
+  streamSpec->SetStream(_stream);
+
+  for (i = 0; i < numItems; i++)
+  {
+    lps->InSize = lps->OutSize = currentTotalSize;
+    RINOK(lps->SetCur());
+    CMyComPtr<ISequentialOutStream> realOutStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    UInt32 index = allFilesMode ? i : indices[i];
+    const CItem &item = _items[index];
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+    currentTotalSize += item.Size;
+    
+    if (!testMode && !realOutStream)
+      continue;
+    RINOK(extractCallback->PrepareOperation(askMode));
+    if (testMode)
+    {
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+      continue;
+    }
+    RINOK(_stream->Seek(_startPos + item.Offset, STREAM_SEEK_SET, NULL));
+    streamSpec->Init(item.Size);
+    RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
+    realOutStream.Release();
+    RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?
+        NExtract::NOperationResult::kOK:
+        NExtract::NOperationResult::kDataError));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+  COM_TRY_BEGIN
+  const CItem &item = _items[index];
+  return CreateLimitedInStream(_stream, _startPos + item.Offset, item.Size, stream);
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"Mub", L"", 0, 0xE2, { 0xCA, 0xFE, 0xBA, 0xBE, 0, 0, 0 }, 7, false, CreateArc, 0 };
+
+REGISTER_ARC(Mub)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisDecode.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisDecode.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisDecode.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisDecode.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,130 @@
+// NsisDecode.cpp
+
+#include "StdAfx.h"
+
+#include "NsisDecode.h"
+
+#include "../../Common/StreamUtils.h"
+
+#include "../../Common/MethodId.h"
+
+#include "../../Compress/BZip2Decoder.h"
+#include "../../Compress/DeflateDecoder.h"
+#include "../../Compress/LzmaDecoder.h"
+
+namespace NArchive {
+namespace NNsis {
+
+static const CMethodId k_BCJ_X86 = 0x03030103;
+
+HRESULT CDecoder::Init(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter)
+{
+  useFilter = false;
+  CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
+
+  if (_decoderInStream)
+    if (method != _method)
+      Release();
+  _method = method;
+  if (!_codecInStream)
+  {
+    switch (method)
+    {
+      // case NMethodType::kCopy: return E_NOTIMPL;
+      case NMethodType::kDeflate: _codecInStream = new NCompress::NDeflate::NDecoder::CNsisCOMCoder(); break;
+      case NMethodType::kBZip2: _codecInStream = new NCompress::NBZip2::CNsisDecoder(); break;
+      case NMethodType::kLZMA: _codecInStream = new NCompress::NLzma::CDecoder(); break;
+      default: return E_NOTIMPL;
+    }
+  }
+
+  if (thereIsFilterFlag)
+  {
+    UInt32 processedSize;
+    BYTE flag;
+    RINOK(inStream->Read(&flag, 1, &processedSize));
+    if (processedSize != 1)
+      return E_FAIL;
+    if (flag > 1)
+      return E_NOTIMPL;
+    useFilter = (flag != 0);
+  }
+  
+  if (useFilter)
+  {
+    if (!_filterInStream)
+    {
+      CMyComPtr<ICompressCoder> coder;
+      RINOK(CreateCoder(
+          EXTERNAL_CODECS_LOC_VARS
+          k_BCJ_X86, coder, false));
+      if (!coder)
+        return E_NOTIMPL;
+      coder.QueryInterface(IID_ISequentialInStream, &_filterInStream);
+      if (!_filterInStream)
+        return E_NOTIMPL;
+    }
+    CMyComPtr<ICompressSetInStream> setInStream;
+    _filterInStream.QueryInterface(IID_ICompressSetInStream, &setInStream);
+    if (!setInStream)
+      return E_NOTIMPL;
+    RINOK(setInStream->SetInStream(_codecInStream));
+    _decoderInStream = _filterInStream;
+  }
+  else
+    _decoderInStream = _codecInStream;
+
+  if (method == NMethodType::kLZMA)
+  {
+    CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
+    _codecInStream.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
+    if (setDecoderProperties)
+    {
+      static const UInt32 kPropertiesSize = 5;
+      BYTE properties[kPropertiesSize];
+      UInt32 processedSize;
+      RINOK(inStream->Read(properties, kPropertiesSize, &processedSize));
+      if (processedSize != kPropertiesSize)
+        return E_FAIL;
+      RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, kPropertiesSize));
+    }
+  }
+
+  {
+    CMyComPtr<ICompressSetInStream> setInStream;
+    _codecInStream.QueryInterface(IID_ICompressSetInStream, &setInStream);
+    if (!setInStream)
+      return E_NOTIMPL;
+    RINOK(setInStream->SetInStream(inStream));
+  }
+
+  {
+    CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
+    _codecInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);
+    if (!setOutStreamSize)
+      return E_NOTIMPL;
+    RINOK(setOutStreamSize->SetOutStreamSize(NULL));
+  }
+
+  if (useFilter)
+  {
+    /*
+    CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
+    _filterInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);
+    if (!setOutStreamSize)
+      return E_NOTIMPL;
+    RINOK(setOutStreamSize->SetOutStreamSize(NULL));
+    */
+  }
+
+  return S_OK;
+}
+
+HRESULT CDecoder::Read(void *data, size_t *processedSize)
+{
+  return ReadStream(_decoderInStream, data, processedSize);;
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisDecode.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisDecode.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisDecode.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisDecode.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,47 @@
+// NsisDecode.h
+
+#ifndef __NSIS_DECODE_H
+#define __NSIS_DECODE_H
+
+#include "../../IStream.h"
+
+#include "../../Common/CreateCoder.h"
+
+namespace NArchive {
+namespace NNsis {
+
+namespace NMethodType
+{
+  enum EEnum
+  {
+    kCopy,
+    kDeflate,
+    kBZip2,
+    kLZMA
+  };
+}
+
+class CDecoder
+{
+  NMethodType::EEnum _method;
+
+  CMyComPtr<ISequentialInStream> _filterInStream;
+  CMyComPtr<ISequentialInStream> _codecInStream;
+  CMyComPtr<ISequentialInStream> _decoderInStream;
+
+public:
+  void Release()
+  {
+    _filterInStream.Release();
+    _codecInStream.Release();
+    _decoderInStream.Release();
+  }
+  HRESULT Init(
+      DECL_EXTERNAL_CODECS_LOC_VARS
+      IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter);
+  HRESULT Read(void *data, size_t *processedSize);
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,510 @@
+// NSisHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/CpuArch.h"
+
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../../Common/StreamUtils.h"
+
+#include "../Common/ItemNameUtils.h"
+
+#include "NsisHandler.h"
+
+#define Get32(p) GetUi32(p)
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NNsis {
+
+static const char *kBcjMethod = "BCJ";
+static const char *kUnknownMethod = "Unknown";
+
+static const char *kMethods[] =
+{
+  "Copy",
+  "Deflate",
+  "BZip2",
+  "LZMA"
+};
+
+static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);
+
+static STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMTime, VT_FILETIME},
+  { NULL, kpidMethod, VT_BSTR},
+  { NULL, kpidSolid, VT_BOOL}
+};
+
+static STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidMethod, VT_BSTR},
+  { NULL, kpidSolid, VT_BOOL}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidMethod:
+    {
+      UInt32 dict = 1;
+      bool filter = false;
+      for (int i = 0; i < _archive.Items.Size(); i++)
+      {
+        const CItem &item = _archive.Items[i];
+        filter |= item.UseFilter;
+        if (item.DictionarySize > dict)
+          dict = item.DictionarySize;
+      }
+      prop = GetMethod(filter, dict);
+      break;
+    }
+    case kpidSolid: prop = _archive.IsSolid; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * maxCheckStartPosition, IArchiveOpenCallback * /* openArchiveCallback */)
+{
+  COM_TRY_BEGIN
+  Close();
+  {
+    if (_archive.Open(
+        EXTERNAL_CODECS_VARS
+        stream, maxCheckStartPosition) != S_OK)
+      return S_FALSE;
+    _inStream = stream;
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _archive.Clear();
+  _archive.Release();
+  _inStream.Release();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _archive.Items.Size()
+  #ifdef NSIS_SCRIPT
+    + 1
+  #endif
+  ;
+  return S_OK;
+}
+
+static AString UInt32ToString(UInt32 value)
+{
+  char buffer[16];
+  ConvertUInt32ToString(value, buffer);
+  return buffer;
+}
+
+static AString GetStringForSizeValue(UInt32 value)
+{
+  for (int i = 31; i >= 0; i--)
+    if (((UInt32)1 << i) == value)
+      return UInt32ToString(i);
+  char c = 'b';
+  if (value % (1 << 20) == 0)
+  {
+    value >>= 20;
+    c = 'm';
+  }
+  else if (value % (1 << 10) == 0)
+  {
+    value >>= 10;
+    c = 'k';
+  }
+  return UInt32ToString(value) + c;
+}
+
+AString CHandler::GetMethod(bool useItemFilter, UInt32 dictionary) const
+{
+  NMethodType::EEnum methodIndex = _archive.Method;
+  AString method;
+  if (_archive.IsSolid && _archive.UseFilter || !_archive.IsSolid && useItemFilter)
+  {
+    method += kBcjMethod;
+    method += ' ';
+  }
+  method += (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod;
+  if (methodIndex == NMethodType::kLZMA)
+  {
+    method += ':';
+    method += GetStringForSizeValue(_archive.IsSolid ? _archive.DictionarySize: dictionary);
+  }
+  return method;
+}
+
+bool CHandler::GetUncompressedSize(int index, UInt32 &size)
+{
+  size = 0;
+  const CItem &item = _archive.Items[index];
+  if (item.SizeIsDefined)
+     size = item.Size;
+  else if (_archive.IsSolid && item.EstimatedSizeIsDefined)
+     size  = item.EstimatedSize;
+  else
+    return false;
+  return true;
+}
+
+bool CHandler::GetCompressedSize(int index, UInt32 &size)
+{
+  size = 0;
+  const CItem &item = _archive.Items[index];
+  if (item.CompressedSizeIsDefined)
+    size = item.CompressedSize;
+  else
+  {
+    if (_archive.IsSolid)
+    {
+      if (index == 0)
+        size = _archive.FirstHeader.GetDataSize();
+      else
+        return false;
+    }
+    else
+    {
+      if (!item.IsCompressed)
+        size = item.Size;
+      else
+        return false;
+    }
+  }
+  return true;
+}
+
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  #ifdef NSIS_SCRIPT
+  if (index >= (UInt32)_archive.Items.Size())
+  {
+    switch(propID)
+    {
+      case kpidPath:  prop = L"[NSIS].nsi"; break;
+      case kpidSize:
+      case kpidPackSize:  prop = (UInt64)_archive.Script.Length(); break;
+      case kpidSolid:  prop = false; break;
+    }
+  }
+  else
+  #endif
+  {
+    const CItem &item = _archive.Items[index];
+    switch(propID)
+    {
+      case kpidPath:
+      {
+        UString s = NItemName::WinNameToOSName(item.GetReducedName(_archive.IsUnicode));
+        if (!s.IsEmpty())
+          prop = (const wchar_t *)s;
+        break;
+      }
+      case kpidSize:
+      {
+        UInt32 size;
+        if (GetUncompressedSize(index, size))
+          prop = (UInt64)size;
+        break;
+      }
+      case kpidPackSize:
+      {
+        UInt32 size;
+        if (GetCompressedSize(index, size))
+          prop = (UInt64)size;
+        break;
+      }
+      case kpidMTime:
+      {
+        if (item.MTime.dwHighDateTime > 0x01000000 &&
+            item.MTime.dwHighDateTime < 0xFF000000)
+          prop = item.MTime;
+        break;
+      }
+      case kpidMethod:  prop = GetMethod(item.UseFilter, item.DictionarySize); break;
+      case kpidSolid:  prop = _archive.IsSolid; break;
+    }
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    GetNumberOfItems(&numItems);
+  if (numItems == 0)
+    return S_OK;
+  UInt64 totalSize = 0;
+
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+  {
+    UInt32 index = (allFilesMode ? i : indices[i]);
+    #ifdef NSIS_SCRIPT
+    if (index >= (UInt32)_archive.Items.Size())
+      totalSize += _archive.Script.Length();
+    else
+    #endif
+    {
+      UInt32 size;
+      if (_archive.IsSolid)
+      {
+        GetUncompressedSize(index, size);
+        UInt64 pos = _archive.GetPosOfSolidItem(index);
+        if (pos > totalSize)
+          totalSize = pos + size;
+      }
+      else
+      {
+        GetCompressedSize(index, size);
+        totalSize += size;
+      }
+    }
+  }
+  extractCallback->SetTotal(totalSize);
+
+  UInt64 currentTotalSize = 0;
+  UInt32 currentItemSize = 0;
+
+  UInt64 streamPos = 0;
+  if (_archive.IsSolid)
+  {
+    RINOK(_inStream->Seek(_archive.StreamOffset, STREAM_SEEK_SET, NULL));
+    bool useFilter;
+    RINOK(_archive.Decoder.Init(
+        EXTERNAL_CODECS_VARS
+        _inStream, _archive.Method, _archive.FilterFlag, useFilter));
+  }
+
+  CByteBuffer byteBuf;
+  const UInt32 kBufferLength = 1 << 16;
+  byteBuf.SetCapacity(kBufferLength);
+  Byte *buffer = byteBuf;
+
+  CByteBuffer tempBuf;
+
+  bool dataError = false;
+  for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
+  {
+    currentItemSize = 0;
+    RINOK(extractCallback->SetCompleted(&currentTotalSize));
+    CMyComPtr<ISequentialOutStream> realOutStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    UInt32 index = allFilesMode ? i : indices[i];
+
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+    #ifdef NSIS_SCRIPT
+    if (index >= (UInt32)_archive.Items.Size())
+    {
+      currentItemSize = _archive.Script.Length();
+      if (!testMode && !realOutStream)
+        continue;
+      RINOK(extractCallback->PrepareOperation(askMode));
+      if (!testMode)
+        RINOK(WriteStream(realOutStream, (const char *)_archive.Script, (UInt32)_archive.Script.Length()));
+    }
+    else
+    #endif
+    {
+      const CItem &item = _archive.Items[index];
+      
+      if (_archive.IsSolid)
+        GetUncompressedSize(index, currentItemSize);
+      else
+        GetCompressedSize(index, currentItemSize);
+      
+      if (!testMode && !realOutStream)
+        continue;
+      
+      RINOK(extractCallback->PrepareOperation(askMode));
+      
+      if (!dataError)
+      {
+        bool needDecompress = false;
+        bool sizeIsKnown = false;
+        UInt32 fullSize = 0;
+
+        bool writeToTemp = false;
+        bool readFromTemp = false;
+
+        if (_archive.IsSolid)
+        {
+          UInt64 pos = _archive.GetPosOfSolidItem(index);
+          while (streamPos < pos)
+          {
+            size_t processedSize = (UInt32)MyMin(pos - streamPos, (UInt64)kBufferLength);
+            HRESULT res = _archive.Decoder.Read(buffer, &processedSize);
+            if (res != S_OK)
+            {
+              if (res != S_FALSE)
+                return res;
+              dataError = true;
+              break;
+            }
+            if (processedSize == 0)
+            {
+              dataError = true;
+              break;
+            }
+            streamPos += processedSize;
+          }
+          if (streamPos == pos)
+          {
+            Byte buffer2[4];
+            size_t processedSize = 4;
+            RINOK(_archive.Decoder.Read(buffer2, &processedSize));
+            if (processedSize != 4)
+              return E_FAIL;
+            streamPos += processedSize;
+            fullSize = Get32(buffer2);
+            sizeIsKnown = true;
+            needDecompress = true;
+
+            if (!testMode && i + 1 < numItems)
+            {
+              UInt64 nextPos = _archive.GetPosOfSolidItem(allFilesMode ? i : indices[i + 1]);
+              if (nextPos < streamPos + fullSize)
+              {
+                tempBuf.Free();
+                tempBuf.SetCapacity(fullSize);
+                writeToTemp = true;
+              }
+            }
+          }
+          else
+            readFromTemp = true;
+        }
+        else
+        {
+          RINOK(_inStream->Seek(_archive.GetPosOfNonSolidItem(index) + 4, STREAM_SEEK_SET, NULL));
+          if (item.IsCompressed)
+          {
+            needDecompress = true;
+            bool useFilter;
+            RINOK(_archive.Decoder.Init(
+                EXTERNAL_CODECS_VARS
+                _inStream, _archive.Method, _archive.FilterFlag, useFilter));
+            // fullSize = Get32(buffer); // It's bug !!!
+            // Test it: what is exact fullSize?
+            fullSize =  0xFFFFFFFF;
+          }
+          else
+            fullSize = item.Size;
+        }
+        if (!dataError)
+        {
+          if (needDecompress)
+          {
+            UInt64 offset = 0;
+            while (!sizeIsKnown || fullSize > 0)
+            {
+              UInt32 curSize = kBufferLength;
+              if (sizeIsKnown && curSize > fullSize)
+                curSize = fullSize;
+              size_t processedSize = curSize;
+              HRESULT res = _archive.Decoder.Read(buffer, &processedSize);
+              if (res != S_OK)
+              {
+                if (res != S_FALSE)
+                  return res;
+                dataError = true;
+                break;
+              }
+              if (processedSize == 0)
+              {
+                if (sizeIsKnown)
+                  dataError = true;
+                break;
+              }
+
+              if (writeToTemp)
+                memcpy((Byte *)tempBuf + (size_t)offset, buffer, processedSize);
+              
+              fullSize -= (UInt32)processedSize;
+              streamPos += processedSize;
+              offset += processedSize;
+              
+              UInt64 completed;
+              if (_archive.IsSolid)
+                completed = currentTotalSize + offset;
+              else
+                completed = streamPos;
+              RINOK(extractCallback->SetCompleted(&completed));
+              if (!testMode)
+                RINOK(WriteStream(realOutStream, buffer, processedSize));
+            }
+          }
+          else
+          {
+            if (readFromTemp)
+            {
+              if (!testMode)
+                RINOK(WriteStream(realOutStream, tempBuf, tempBuf.GetCapacity()));
+            }
+            else
+            while (fullSize > 0)
+            {
+              UInt32 curSize = MyMin(fullSize, kBufferLength);
+              UInt32 processedSize;
+              RINOK(_inStream->Read(buffer, curSize, &processedSize));
+              if (processedSize == 0)
+              {
+                dataError = true;
+                break;
+              }
+              fullSize -= processedSize;
+              streamPos += processedSize;
+              if (!testMode)
+                RINOK(WriteStream(realOutStream, buffer, processedSize));
+            }
+          }
+        }
+      }
+    }
+    realOutStream.Release();
+    RINOK(extractCallback->SetOperationResult(dataError ?
+        NExtract::NOperationResult::kDataError :
+        NExtract::NOperationResult::kOK));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+IMPL_ISetCompressCodecsInfo
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisHandler.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisHandler.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisHandler.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisHandler.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,43 @@
+// NSisHandler.h
+
+#ifndef __NSIS_HANDLER_H
+#define __NSIS_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+
+#include "NsisIn.h"
+
+#include "../../Common/CreateCoder.h"
+
+namespace NArchive {
+namespace NNsis {
+
+class CHandler:
+  public IInArchive,
+  PUBLIC_ISetCompressCodecsInfo
+  public CMyUnknownImp
+{
+  CMyComPtr<IInStream> _inStream;
+  CInArchive _archive;
+
+  DECL_EXTERNAL_CODECS_VARS
+
+  bool GetUncompressedSize(int index, UInt32 &size);
+  bool GetCompressedSize(int index, UInt32 &size);
+
+  AString GetMethod(bool useItemFilter, UInt32 dictionary) const;
+public:
+  MY_QUERYINTERFACE_BEGIN2(IInArchive)
+  QUERY_ENTRY_ISetCompressCodecsInfo
+  MY_QUERYINTERFACE_END
+  MY_ADDREF_RELEASE
+
+  INTERFACE_IInArchive(;)
+
+  DECL_ISetCompressCodecsInfo
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisIn.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisIn.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisIn.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisIn.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,1461 @@
+// NsisIn.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/CpuArch.h"
+
+#include "Common/IntToString.h"
+
+#include "../../Common/StreamUtils.h"
+
+#include "NsisIn.h"
+
+#define Get32(p) GetUi32(p)
+
+namespace NArchive {
+namespace NNsis {
+
+Byte kSignature[kSignatureSize] = NSIS_SIGNATURE;
+
+#ifdef NSIS_SCRIPT
+static const char *kCrLf = "\x0D\x0A";
+#endif
+
+#define NS_UN_SKIP_CODE  0xE000
+#define NS_UN_VAR_CODE   0xE001
+#define NS_UN_SHELL_CODE 0xE002
+#define NS_UN_LANG_CODE  0xE003
+#define NS_UN_CODES_START NS_UN_SKIP_CODE
+#define NS_UN_CODES_END   NS_UN_LANG_CODE
+
+Byte CInArchive::ReadByte()
+{
+  if (_posInData >= _size)
+    throw 1;
+  return _data[_posInData++];
+}
+
+UInt32 CInArchive::ReadUInt32()
+{
+  UInt32 value = 0;
+  for (int i = 0; i < 4; i++)
+    value |= ((UInt32)(ReadByte()) << (8 * i));
+  return value;
+}
+
+void CInArchive::ReadBlockHeader(CBlockHeader &bh)
+{
+  bh.Offset = ReadUInt32();
+  bh.Num = ReadUInt32();
+}
+
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+
+static int CompareItems(void *const *p1, void *const *p2, void * /* param */)
+{
+  const CItem &i1 = **(CItem **)p1;
+  const CItem &i2 = **(CItem **)p2;
+  RINOZ(MyCompare(i1.Pos, i2.Pos));
+  if (i1.IsUnicode)
+  {
+    RINOZ(i1.PrefixU.Compare(i2.PrefixU));
+    RINOZ(i1.NameU.Compare(i2.NameU));
+  }
+  else
+  {
+    RINOZ(i1.PrefixA.Compare(i2.PrefixA));
+    RINOZ(i1.NameA.Compare(i2.NameA));
+  }
+  return 0;
+}
+
+static AString UIntToString(UInt32 v)
+{
+  char sz[32];
+  ConvertUInt64ToString(v, sz);
+  return sz;
+}
+
+static AString IntToString(Int32 v)
+{
+  char sz[32];
+  ConvertInt64ToString(v, sz);
+  return sz;
+}
+
+AString CInArchive::ReadStringA(UInt32 pos) const
+{
+  AString s;
+  if (pos >= _size)
+    return IntToString((Int32)pos);
+  UInt32 offset = GetOffset() + _stringsPos + pos;
+  for (;;)
+  {
+    if (offset >= _size)
+      break; // throw 1;
+    char c = _data[offset++];
+    if (c == 0)
+      break;
+    s += c;
+  }
+  return s;
+}
+
+UString CInArchive::ReadStringU(UInt32 pos) const
+{
+  UString s;
+  UInt32 offset = GetOffset() + _stringsPos + (pos * 2);
+  for (;;)
+  {
+    if (offset >= _size || offset + 1 >= _size)
+      return s; // throw 1;
+    char c0 = _data[offset++];
+    char c1 = _data[offset++];
+    wchar_t c = (c0 | ((wchar_t)c1 << 8));
+    if (c == 0)
+      break;
+    s += c;
+  }
+  return s;
+}
+
+/*
+static AString ParsePrefix(const AString &prefix)
+{
+  AString res = prefix;
+  if (prefix.Length() >= 3)
+  {
+    if ((Byte)prefix[0] == 0xFD && (Byte)prefix[1] == 0x95 && (Byte)prefix[2] == 0x80)
+      res = "$INSTDIR" + prefix.Mid(3);
+    else if ((Byte)prefix[0] == 0xFD && (Byte)prefix[1] == 0x96 && (Byte)prefix[2] == 0x80)
+      res = "$OUTDIR" + prefix.Mid(3);
+  }
+  return res;
+}
+*/
+
+#define SYSREGKEY "Software\\Microsoft\\Windows\\CurrentVersion"
+
+/*
+#  define CSIDL_PROGRAMS 0x2
+#  define CSIDL_PRINTERS 0x4
+#  define CSIDL_PERSONAL 0x5
+#  define CSIDL_FAVORITES 0x6
+#  define CSIDL_STARTUP 0x7
+#  define CSIDL_RECENT 0x8
+#  define CSIDL_SENDTO 0x9
+#  define CSIDL_STARTMENU 0xB
+#  define CSIDL_MYMUSIC 0xD
+#  define CSIDL_MYVIDEO 0xE
+
+#  define CSIDL_DESKTOPDIRECTORY 0x10
+#  define CSIDL_NETHOOD 0x13
+#  define CSIDL_FONTS 0x14
+#  define CSIDL_TEMPLATES 0x15
+#  define CSIDL_COMMON_STARTMENU 0x16
+#  define CSIDL_COMMON_PROGRAMS 0x17
+#  define CSIDL_COMMON_STARTUP 0x18
+#  define CSIDL_COMMON_DESKTOPDIRECTORY 0x19
+#  define CSIDL_APPDATA 0x1A
+#  define CSIDL_PRINTHOOD 0x1B
+#  define CSIDL_LOCAL_APPDATA 0x1C
+#  define CSIDL_ALTSTARTUP 0x1D
+#  define CSIDL_COMMON_ALTSTARTUP 0x1E
+#  define CSIDL_COMMON_FAVORITES 0x1F
+
+#  define CSIDL_INTERNET_CACHE 0x20
+#  define CSIDL_COOKIES 0x21
+#  define CSIDL_HISTORY 0x22
+#  define CSIDL_COMMON_APPDATA 0x23
+#  define CSIDL_WINDOWS 0x24
+#  define CSIDL_SYSTEM 0x25
+#  define CSIDL_PROGRAM_FILES 0x26
+#  define CSIDL_MYPICTURES 0x27
+#  define CSIDL_PROFILE 0x28
+#  define CSIDL_PROGRAM_FILES_COMMON 0x2B
+#  define CSIDL_COMMON_TEMPLATES 0x2D
+#  define CSIDL_COMMON_DOCUMENTS 0x2E
+#  define CSIDL_COMMON_ADMINTOOLS 0x2F
+
+#  define CSIDL_ADMINTOOLS 0x30
+#  define CSIDL_COMMON_MUSIC 0x35
+#  define CSIDL_COMMON_PICTURES 0x36
+#  define CSIDL_COMMON_VIDEO 0x37
+#  define CSIDL_RESOURCES 0x38
+#  define CSIDL_RESOURCES_LOCALIZED 0x39
+#  define CSIDL_CDBURN_AREA 0x3B
+*/
+
+struct CCommandPair
+{
+  int NumParams;
+  const char *Name;
+};
+
+enum
+{
+  // 0
+  EW_INVALID_OPCODE,    // zero is invalid. useful for catching errors. (otherwise an all zeroes instruction
+                        // does nothing, which is easily ignored but means something is wrong.
+  EW_RET,               // return from function call
+  EW_NOP,               // Nop/Jump, do nothing: 1, [?new address+1:advance one]
+  EW_ABORT,             // Abort: 1 [status]
+  EW_QUIT,              // Quit: 0
+  EW_CALL,              // Call: 1 [new address+1]
+  EW_UPDATETEXT,        // Update status text: 2 [update str, ui_st_updateflag=?ui_st_updateflag:this]
+  EW_SLEEP,             // Sleep: 1 [sleep time in milliseconds]
+  EW_BRINGTOFRONT,      // BringToFront: 0
+  EW_CHDETAILSVIEW,     // SetDetailsView: 2 [listaction,buttonaction]
+  
+  // 10
+  EW_SETFILEATTRIBUTES, // SetFileAttributes: 2 [filename, attributes]
+  EW_CREATEDIR,         // Create directory: 2, [path, ?update$INSTDIR]
+  EW_IFFILEEXISTS,      // IfFileExists: 3, [file name, jump amount if exists, jump amount if not exists]
+  EW_SETFLAG,           // Sets a flag: 2 [id, data]
+  EW_IFFLAG,            // If a flag: 4 [on, off, id, new value mask]
+  EW_GETFLAG,           // Gets a flag: 2 [output, id]
+  EW_RENAME,            // Rename: 3 [old, new, rebootok]
+  EW_GETFULLPATHNAME,   // GetFullPathName: 2 [output, input, ?lfn:sfn]
+  EW_SEARCHPATH,        // SearchPath: 2 [output, filename]
+  EW_GETTEMPFILENAME,   // GetTempFileName: 2 [output, base_dir]
+  
+  // 20
+  EW_EXTRACTFILE,       // File to extract: 6 [overwriteflag, output filename, compressed filedata, filedatetimelow, filedatetimehigh, allow ignore]
+                        //  overwriteflag: 0x1 = no. 0x0=force, 0x2=try, 0x3=if date is newer
+  EW_DELETEFILE,        // Delete File: 2, [filename, rebootok]
+  EW_MESSAGEBOX,        // MessageBox: 5,[MB_flags,text,retv1:retv2,moveonretv1:moveonretv2]
+  EW_RMDIR,             // RMDir: 2 [path, recursiveflag]
+  EW_STRLEN,            // StrLen: 2 [output, input]
+  EW_ASSIGNVAR,         // Assign: 4 [variable (0-9) to assign, string to assign, maxlen, startpos]
+  EW_STRCMP,            // StrCmp: 5 [str1, str2, jump_if_equal, jump_if_not_equal, case-sensitive?]
+  EW_READENVSTR,        // ReadEnvStr/ExpandEnvStrings: 3 [output, string_with_env_variables, IsRead]
+  EW_INTCMP,            // IntCmp: 6 [val1, val2, equal, val1<val2, val1>val2, unsigned?]
+  EW_INTOP,             // IntOp: 4 [output, input1, input2, op] where op: 0=add, 1=sub, 2=mul, 3=div, 4=bor, 5=band, 6=bxor, 7=bnot input1, 8=lnot input1, 9=lor, 10=land], 11=1%2
+  
+  // 30
+  EW_INTFMT,            // IntFmt: [output, format, input]
+  EW_PUSHPOP,           // Push/Pop/Exchange: 3 [variable/string, ?pop:push, ?exch]
+  EW_FINDWINDOW,        // FindWindow: 5, [outputvar, window class,window name, window_parent, window_after]
+  EW_SENDMESSAGE,       // SendMessage: 6 [output, hwnd, msg, wparam, lparam, [wparamstring?1:0 | lparamstring?2:0 | timeout<<2]
+  EW_ISWINDOW,          // IsWindow: 3 [hwnd, jump_if_window, jump_if_notwindow]
+  EW_GETDLGITEM,        // GetDlgItem:        3: [outputvar, dialog, item_id]
+  EW_SETCTLCOLORS,      // SerCtlColors:      3: [hwnd, pointer to struct colors]
+  EW_SETBRANDINGIMAGE,  // SetBrandingImage:  1: [Bitmap file]
+  EW_CREATEFONT,        // CreateFont:        5: [handle output, face name, height, weight, flags]
+  EW_SHOWWINDOW,        // ShowWindow:        2: [hwnd, show state]
+  
+  // 40
+  EW_SHELLEXEC,         // ShellExecute program: 4, [shell action, complete commandline, parameters, showwindow]
+  EW_EXECUTE,           // Execute program: 3,[complete command line,waitflag,>=0?output errorcode]
+  EW_GETFILETIME,       // GetFileTime; 3 [file highout lowout]
+  EW_GETDLLVERSION,     // GetDLLVersion: 3 [file highout lowout]
+  EW_REGISTERDLL,       // Register DLL: 3,[DLL file name, string ptr of function to call, text to put in display (<0 if none/pass parms), 1 - no unload, 0 - unload]
+  EW_CREATESHORTCUT,    // Make Shortcut: 5, [link file, target file, parameters, icon file, iconindex|show mode<<8|hotkey<<16]
+  EW_COPYFILES,         // CopyFiles: 3 [source mask, destination location, flags]
+  EW_REBOOT,            // Reboot: 0
+  EW_WRITEINI,          // Write INI String: 4, [Section, Name, Value, INI File]
+  EW_READINISTR,        // ReadINIStr: 4 [output, section, name, ini_file]
+  
+  // 50
+  EW_DELREG,            // DeleteRegValue/DeleteRegKey: 4, [root key(int), KeyName, ValueName, delkeyonlyifempty]. ValueName is -1 if delete key
+  EW_WRITEREG,          // Write Registry value: 5, [RootKey(int),KeyName,ItemName,ItemData,typelen]
+                        //  typelen=1 for str, 2 for dword, 3 for binary, 0 for expanded str
+  EW_READREGSTR,        // ReadRegStr: 5 [output, rootkey(int), keyname, itemname, ==1?int::str]
+  EW_REGENUM,           // RegEnum: 5 [output, rootkey, keyname, index, ?key:value]
+  EW_FCLOSE,            // FileClose: 1 [handle]
+  EW_FOPEN,             // FileOpen: 4  [name, openmode, createmode, outputhandle]
+  EW_FPUTS,             // FileWrite: 3 [handle, string, ?int:string]
+  EW_FGETS,             // FileRead: 4  [handle, output, maxlen, ?getchar:gets]
+  EW_FSEEK,             // FileSeek: 4  [handle, offset, mode, >=0?positionoutput]
+  EW_FINDCLOSE,         // FindClose: 1 [handle]
+  
+  // 60
+  EW_FINDNEXT,          // FindNext: 2  [output, handle]
+  EW_FINDFIRST,         // FindFirst: 2 [filespec, output, handleoutput]
+  EW_WRITEUNINSTALLER,  // WriteUninstaller: 3 [name, offset, icon_size]
+  EW_LOG,               // LogText: 2 [0, text] / LogSet: [1, logstate]
+  EW_SECTIONSET,        // SectionSetText:    3: [idx, 0, text]
+                        // SectionGetText:    3: [idx, 1, output]
+                        // SectionSetFlags:   3: [idx, 2, flags]
+                        // SectionGetFlags:   3: [idx, 3, output]
+  EW_INSTTYPESET,       // InstTypeSetFlags:  3: [idx, 0, flags]
+                        // InstTypeGetFlags:  3: [idx, 1, output]
+  // instructions not actually implemented in exehead, but used in compiler.
+  EW_GETLABELADDR,      // both of these get converted to EW_ASSIGNVAR
+  EW_GETFUNCTIONADDR,
+
+  EW_LOCKWINDOW
+};
+
+#ifdef NSIS_SCRIPT
+static CCommandPair kCommandPairs[] =
+{
+  { 0, "Invalid" },
+  { 0, "Return" },
+  { 1, "Goto" },
+  { 0, "Abort" },
+  { 0, "Quit" },
+  { 1, "Call" },
+  { 2, "UpdateSatusText" },
+  { 1, "Sleep" },
+  { 0, "BringToFront" },
+  { 2, "SetDetailsView" },
+
+  { 2, "SetFileAttributes" },
+  { 2, "SetOutPath" },
+  { 3, "IfFileExists" },
+  { 2, "SetFlag" },
+  { 4, "IfFlag" },
+  { 2, "GetFlag" },
+  { 3, "Rename" },
+  { 2, "GetFullPathName" },
+  { 2, "SearchPath" },
+  { 2, "GetTempFileName" },
+
+  { 6, "File" },
+  { 2, "Delete" },
+  { 5, "MessageBox" },
+  { 2, "RMDir" },
+  { 2, "StrLen" },
+  { 4, "StrCpy" },
+  { 5, "StrCmp" },
+  { 3, "ReadEnvStr" },
+  { 6, "IntCmp" },
+  { 4, "IntOp" },
+
+  { 3, "IntFmt" },
+  { 3, "PushPop" },
+  { 5, "FindWindow" },
+  { 6, "SendMessage" },
+  { 3, "IsWindow" },
+  { 3, "GetDlgItem" },
+  { 3, "SerCtlColors" },
+  { 1, "SetBrandingImage" },
+  { 5, "CreateFont" },
+  { 2, "ShowWindow" },
+
+  { 4, "ShellExecute" },
+  { 3, "Execute" },
+  { 3, "GetFileTime" },
+  { 3, "GetDLLVersion" },
+  { 3, "RegisterDLL" },
+  { 5, "CreateShortCut" },
+  { 3, "CopyFiles" },
+  { 0, "Reboot" },
+  { 4, "WriteINIStr" },
+  { 4, "ReadINIStr" },
+
+  { 4, "DelReg" },
+  { 5, "WriteReg" },
+  { 5, "ReadRegStr" },
+  { 5, "RegEnum" },
+  { 1, "FileClose" },
+  { 4, "FileOpen" },
+  { 3, "FileWrite" },
+  { 4, "FileRead" },
+  { 4, "FileSeek" },
+  { 1, "FindClose" },
+
+  { 2, "FindNext" },
+  { 2, "FindFirst" },
+  { 3, "WriteUninstaller" },
+  { 2, "LogText" },
+  { 3, "Section?etText" },
+  { 3, "InstType?etFlags" },
+  { 6, "GetLabelAddr" },
+  { 2, "GetFunctionAddress" },
+  { 6, "LockWindow" }
+};
+
+#endif
+
+static const char *kShellStrings[] =
+{
+  "",
+  "",
+
+  "SMPROGRAMS",
+  "",
+  "PRINTERS",
+  "DOCUMENTS",
+  "FAVORITES",
+  "SMSTARTUP",
+  "RECENT",
+  "SENDTO",
+  "",
+  "STARTMENU",
+  "",
+  "MUSIC",
+  "VIDEO",
+  "",
+
+  "DESKTOP",
+  "",
+  "",
+  "NETHOOD",
+  "FONTS",
+  "TEMPLATES",
+  "COMMONSTARTMENU",
+  "COMMONFILES",
+  "COMMON_STARTUP",
+  "COMMON_DESKTOPDIRECTORY",
+  "QUICKLAUNCH",
+  "PRINTHOOD",
+  "LOCALAPPDATA",
+  "ALTSTARTUP",
+  "ALTSTARTUP",
+  "FAVORITES",
+
+  "INTERNET_CACHE",
+  "COOKIES",
+  "HISTORY",
+  "APPDATA",
+  "WINDIR",
+  "SYSDIR",
+  "PROGRAMFILES",
+  "PICTURES",
+  "PROFILE",
+  "",
+  "",
+  "COMMONFILES",
+  "",
+  "TEMPLATES",
+  "DOCUMENTS",
+  "ADMINTOOLS",
+
+  "ADMINTOOLS",
+  "",
+  "",
+  "",
+  "",
+  "MUSIC",
+  "PICTURES",
+  "VIDEO",
+  "RESOURCES",
+  "RESOURCES_LOCALIZED",
+  "",
+  "CDBURN_AREA"
+};
+
+static const int kNumShellStrings = sizeof(kShellStrings) / sizeof(kShellStrings[0]);
+
+/*
+# define CMDLINE 20 // everything before here doesn't have trailing slash removal
+# define INSTDIR 21
+# define OUTDIR 22
+# define EXEDIR 23
+# define LANGUAGE 24
+# define TEMP   25
+# define PLUGINSDIR 26
+# define HWNDPARENT 27
+# define _CLICK 28
+# define _OUTDIR 29
+*/
+
+static const char *kVarStrings[] =
+{
+  "CMDLINE",
+  "INSTDIR",
+  "OUTDIR",
+  "EXEDIR",
+  "LANGUAGE",
+  "TEMP",
+  "PLUGINSDIR",
+  "EXEPATH", // test it
+  "EXEFILE", // test it
+  "HWNDPARENT",
+  "_CLICK",
+  "_OUTDIR"
+};
+
+static const int kNumVarStrings = sizeof(kVarStrings) / sizeof(kVarStrings[0]);
+
+
+static AString GetVar(UInt32 index)
+{
+  AString res = "$";
+  if (index < 10)
+    res += UIntToString(index);
+  else if (index < 20)
+  {
+    res += "R";
+    res += UIntToString(index - 10);
+  }
+  else if (index < 20 + kNumVarStrings)
+    res += kVarStrings[index - 20];
+  else
+  {
+    res += "[";
+    res += UIntToString(index);
+    res += "]";
+  }
+  return res;
+}
+
+#define NS_SKIP_CODE  252
+#define NS_VAR_CODE   253
+#define NS_SHELL_CODE 254
+#define NS_LANG_CODE  255
+#define NS_CODES_START NS_SKIP_CODE
+
+static AString GetShellString(int index)
+{
+  AString res = "$";
+  if (index < kNumShellStrings)
+  {
+    const char *sz = kShellStrings[index];
+    if (sz[0] != 0)
+      return res + sz;
+  }
+  res += "SHELL[";
+  res += UIntToString(index);
+  res += "]";
+  return res;
+}
+
+// Based on Dave Laundon's simplified process_string
+AString GetNsisString(const AString &s)
+{
+  AString res;
+  for (int i = 0; i < s.Length();)
+  {
+    unsigned char nVarIdx = s[i++];
+    if (nVarIdx > NS_CODES_START && i + 2 <= s.Length())
+    {
+      int nData = s[i++] & 0x7F;
+      unsigned char c1 = s[i++];
+      nData |= (((int)(c1 & 0x7F)) << 7);
+
+      if (nVarIdx == NS_SHELL_CODE)
+        res += GetShellString(c1);
+      else if (nVarIdx == NS_VAR_CODE)
+        res += GetVar(nData);
+      else if (nVarIdx == NS_LANG_CODE)
+        res += "NS_LANG_CODE";
+    }
+    else if (nVarIdx == NS_SKIP_CODE)
+    {
+      if (i < s.Length())
+        res += s[i++];
+    }
+    else // Normal char
+      res += (char)nVarIdx;
+  }
+  return res;
+}
+
+UString GetNsisString(const UString &s)
+{
+  UString res;
+  for (int i = 0; i < s.Length();)
+  {
+    wchar_t nVarIdx = s[i++];
+    if (nVarIdx > NS_UN_CODES_START && nVarIdx <= NS_UN_CODES_END)
+    {
+      if (i == s.Length())
+        break;
+      int nData = s[i++] & 0x7FFF;
+
+      if (nVarIdx == NS_UN_SHELL_CODE)
+        res += GetUnicodeString(GetShellString(nData >> 8));
+      else if (nVarIdx == NS_UN_VAR_CODE)
+        res += GetUnicodeString(GetVar(nData));
+      else if (nVarIdx == NS_UN_LANG_CODE)
+        res += L"NS_LANG_CODE";
+    }
+    else if (nVarIdx == NS_UN_SKIP_CODE)
+    {
+      if (i == s.Length())
+        break;
+      res += s[i++];
+    }
+    else // Normal char
+      res += (char)nVarIdx;
+  }
+  return res;
+}
+
+AString CInArchive::ReadString2A(UInt32 pos) const
+{
+  return GetNsisString(ReadStringA(pos));
+}
+
+UString CInArchive::ReadString2U(UInt32 pos) const
+{
+  return GetNsisString(ReadStringU(pos));
+}
+
+AString CInArchive::ReadString2(UInt32 pos) const
+{
+  if (IsUnicode)
+    return UnicodeStringToMultiByte(ReadString2U(pos));
+  else
+    return ReadString2A(pos);
+}
+
+AString CInArchive::ReadString2Qw(UInt32 pos) const
+{
+  return "\"" + ReadString2(pos) + "\"";
+}
+
+#define DEL_DIR 1
+#define DEL_RECURSE 2
+#define DEL_REBOOT 4
+// #define DEL_SIMPLE 8
+
+static const int kNumEntryParams = 6;
+
+struct CEntry
+{
+  UInt32 Which;
+  UInt32 Params[kNumEntryParams];
+  AString GetParamsString(int numParams);
+  CEntry()
+  {
+    Which = 0;
+    for (UInt32 j = 0; j < kNumEntryParams; j++)
+      Params[j] = 0;
+  }
+};
+
+AString CEntry::GetParamsString(int numParams)
+{
+  AString s;
+  for (int i = 0; i < numParams; i++)
+  {
+    s += " ";
+    UInt32 v = Params[i];
+    if (v > 0xFFF00000)
+      s += IntToString((Int32)Params[i]);
+    else
+      s += UIntToString(Params[i]);
+  }
+  return s;
+}
+
+#ifdef NSIS_SCRIPT
+
+static AString GetRegRootID(UInt32 val)
+{
+  const char *s;
+  switch(val)
+  {
+    case 0:  s = "SHCTX"; break;
+    case 0x80000000:  s = "HKCR"; break;
+    case 0x80000001:  s = "HKCU"; break;
+    case 0x80000002:  s = "HKLM"; break;
+    case 0x80000003:  s = "HKU";  break;
+    case 0x80000004:  s = "HKPD"; break;
+    case 0x80000005:  s = "HKCC"; break;
+    case 0x80000006:  s = "HKDD"; break;
+    case 0x80000050:  s = "HKPT"; break;
+    case 0x80000060:  s = "HKPN"; break;
+    default:
+      return UIntToString(val); break;
+  }
+  return s;
+}
+
+#endif
+
+HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
+{
+  _posInData = bh.Offset + GetOffset();
+  AString prefixA;
+  UString prefixU;
+  for (UInt32 i = 0; i < bh.Num; i++)
+  {
+    CEntry e;
+    e.Which = ReadUInt32();
+    for (UInt32 j = 0; j < kNumEntryParams; j++)
+      e.Params[j] = ReadUInt32();
+    #ifdef NSIS_SCRIPT
+    if (e.Which != EW_PUSHPOP && e.Which < sizeof(kCommandPairs) / sizeof(kCommandPairs[0]))
+    {
+      const CCommandPair &pair = kCommandPairs[e.Which];
+      Script += pair.Name;
+    }
+    #endif
+
+    switch (e.Which)
+    {
+      case EW_CREATEDIR:
+      {
+        if (IsUnicode)
+        {
+          prefixU.Empty();
+          prefixU = ReadString2U(e.Params[0]);
+        }
+        else
+        {
+          prefixA.Empty();
+          prefixA = ReadString2A(e.Params[0]);
+        }
+        #ifdef NSIS_SCRIPT
+        Script += " ";
+        if (IsUnicode)
+          Script += UnicodeStringToMultiByte(prefixU);
+        else
+          Script += prefixA;
+        #endif
+        break;
+      }
+
+      case EW_EXTRACTFILE:
+      {
+        CItem item;
+        item.IsUnicode = IsUnicode;
+        if (IsUnicode)
+        {
+          item.PrefixU = prefixU;
+          item.NameU = ReadString2U(e.Params[1]);
+        }
+        else
+        {
+          item.PrefixA = prefixA;
+          item.NameA = ReadString2A(e.Params[1]);
+        }
+        /* UInt32 overwriteFlag = e.Params[0]; */
+        item.Pos = e.Params[2];
+        item.MTime.dwLowDateTime = e.Params[3];
+        item.MTime.dwHighDateTime = e.Params[4];
+        /* UInt32 allowIgnore = e.Params[5]; */
+        if (Items.Size() > 0)
+        {
+          /*
+          if (item.Pos == Items.Back().Pos)
+            continue;
+          */
+        }
+        Items.Add(item);
+        #ifdef NSIS_SCRIPT
+        Script += " ";
+
+        if (IsUnicode)
+          Script += UnicodeStringToMultiByte(item.NameU);
+        else
+          Script += item.NameA;
+        #endif
+        break;
+      }
+
+
+      #ifdef NSIS_SCRIPT
+      case EW_UPDATETEXT:
+      {
+        Script += " ";
+        Script += ReadString2(e.Params[0]);
+        Script += " ";
+        Script += UIntToString(e.Params[1]);
+        break;
+      }
+      case EW_SETFILEATTRIBUTES:
+      {
+        Script += " ";
+        Script += ReadString2(e.Params[0]);
+        Script += " ";
+        Script += UIntToString(e.Params[1]);
+        break;
+      }
+      case EW_IFFILEEXISTS:
+      {
+        Script += " ";
+        Script += ReadString2(e.Params[0]);
+        Script += " ";
+        Script += UIntToString(e.Params[1]);
+        Script += " ";
+        Script += UIntToString(e.Params[2]);
+        break;
+      }
+      case EW_RENAME:
+      {
+        Script += " ";
+        Script += ReadString2(e.Params[0]);
+        Script += " ";
+        Script += ReadString2(e.Params[1]);
+        Script += " ";
+        Script += UIntToString(e.Params[2]);
+        break;
+      }
+      case EW_GETFULLPATHNAME:
+      {
+        Script += " ";
+        Script += ReadString2(e.Params[0]);
+        Script += " ";
+        Script += ReadString2(e.Params[1]);
+        Script += " ";
+        Script += UIntToString(e.Params[2]);
+        break;
+      }
+      case EW_SEARCHPATH:
+      {
+        Script += " ";
+        Script += ReadString2(e.Params[0]);
+        Script += " ";
+        Script += ReadString2(e.Params[1]);
+        break;
+      }
+      case EW_GETTEMPFILENAME:
+      {
+        AString s;
+        Script += " ";
+        Script += ReadString2(e.Params[0]);
+        Script += " ";
+        Script += ReadString2(e.Params[1]);
+        break;
+      }
+
+      case EW_DELETEFILE:
+      {
+        UInt64 flag = e.Params[1];
+        if (flag != 0)
+        {
+          Script += " ";
+          if (flag == DEL_REBOOT)
+            Script += "/REBOOTOK";
+          else
+            Script += UIntToString(e.Params[1]);
+        }
+        Script += " ";
+        Script += ReadString2(e.Params[0]);
+        break;
+      }
+      case EW_RMDIR:
+      {
+        UInt64 flag = e.Params[1];
+        if (flag != 0)
+        {
+          if ((flag & DEL_REBOOT) != 0)
+            Script += " /REBOOTOK";
+          if ((flag & DEL_RECURSE) != 0)
+            Script += " /r";
+        }
+        Script += " ";
+        Script += ReadString2(e.Params[0]);
+        break;
+      }
+      case EW_STRLEN:
+      {
+        Script += " ";
+        Script += GetVar(e.Params[0]);;
+        Script += " ";
+        Script += ReadString2Qw(e.Params[1]);
+        break;
+      }
+      case EW_ASSIGNVAR:
+      {
+        Script += " ";
+        Script += GetVar(e.Params[0]);;
+        Script += " ";
+        Script += ReadString2Qw(e.Params[1]);
+        AString maxLen, startOffset;
+        if (e.Params[2] != 0)
+          maxLen = ReadString2(e.Params[2]);
+        if (e.Params[3] != 0)
+          startOffset = ReadString2(e.Params[3]);
+        if (!maxLen.IsEmpty() || !startOffset.IsEmpty())
+        {
+          Script += " ";
+          if (maxLen.IsEmpty())
+            Script += "\"\"";
+          else
+            Script += maxLen;
+          if (!startOffset.IsEmpty())
+          {
+            Script += " ";
+            Script += startOffset;
+          }
+        }
+        break;
+      }
+      case EW_STRCMP:
+      {
+        Script += " ";
+
+        Script += " ";
+        Script += ReadString2Qw(e.Params[0]);
+        
+        Script += " ";
+        Script += ReadString2Qw(e.Params[1]);
+
+        for (int j = 2; j < 5; j++)
+        {
+          Script += " ";
+          Script += UIntToString(e.Params[j]);
+        }
+        break;
+      }
+      case EW_INTCMP:
+      {
+        if (e.Params[5] != 0)
+          Script += "U";
+
+        Script += " ";
+        Script += ReadString2(e.Params[0]);
+        Script += " ";
+        Script += ReadString2(e.Params[1]);
+
+        for (int i = 2; i < 5; i++)
+        {
+          Script += " ";
+          Script += UIntToString(e.Params[i]);
+        }
+        break;
+      }
+      case EW_INTOP:
+      {
+        Script += " ";
+        Script += GetVar(e.Params[0]);
+        Script += " ";
+        int numOps = 2;
+        AString op;
+        switch (e.Params[3])
+        {
+          case 0: op = '+'; break;
+          case 1: op = '-'; break;
+          case 2: op = '*'; break;
+          case 3: op = '/'; break;
+          case 4: op = '|'; break;
+          case 5: op = '&'; break;
+          case 6: op = '^'; break;
+          case 7: op = '~'; numOps = 1; break;
+          case 8: op = '!'; numOps = 1; break;
+          case 9: op = "||"; break;
+          case 10: op = "&&"; break;
+          case 11: op = '%'; break;
+          default: op = UIntToString(e.Params[3]);
+        }
+        AString p1 = ReadString2(e.Params[1]);
+        if (numOps == 1)
+        {
+          Script += op;
+          Script += p1;
+        }
+        else
+        {
+          Script += p1;
+          Script += " ";
+          Script += op;
+          Script += " ";
+          Script += ReadString2(e.Params[2]);
+        }
+        break;
+      }
+
+      case EW_PUSHPOP:
+      {
+        int isPop = (e.Params[1] != 0);
+        if (isPop)
+        {
+          Script += "Pop";
+          Script += " ";
+          Script += GetVar(e.Params[0]);;
+        }
+        else
+        {
+          int isExch = (e.Params[2] != 0);
+          if (isExch)
+          {
+            Script += "Exch";
+          }
+          else
+          {
+            Script += "Push";
+            Script += " ";
+            Script += ReadString2(e.Params[0]);
+          }
+        }
+        break;
+      }
+
+      case EW_SENDMESSAGE:
+      {
+        // SendMessage: 6 [output, hwnd, msg, wparam, lparam, [wparamstring?1:0 | lparamstring?2:0 | timeout<<2]
+        Script += " ";
+        // Script += ReadString2(e.Params[0]);
+        // Script += " ";
+        Script += ReadString2(e.Params[1]);
+        Script += " ";
+        Script += ReadString2(e.Params[2]);
+        
+        Script += " ";
+        UInt32 spec = e.Params[5];
+        // if (spec & 1)
+          Script += IntToString(e.Params[3]);
+        // else
+        //   Script += ReadString2(e.Params[3]);
+        
+        Script += " ";
+        // if (spec & 2)
+          Script += IntToString(e.Params[4]);
+        // else
+        //   Script += ReadString2(e.Params[4]);
+
+        if ((Int32)e.Params[0] >= 0)
+        {
+          Script += " ";
+          Script += GetVar(e.Params[1]);
+        }
+
+        spec >>= 2;
+        if (spec != 0)
+        {
+          Script += " /TIMEOUT=";
+          Script += IntToString(spec);
+        }
+        break;
+      }
+
+      case EW_GETDLGITEM:
+      {
+        Script += " ";
+        Script += GetVar(e.Params[0]);;
+        Script += " ";
+        Script += ReadString2(e.Params[1]);
+        Script += " ";
+        Script += ReadString2(e.Params[2]);
+        break;
+     }
+
+
+      case EW_REGISTERDLL:
+      {
+        Script += " ";
+        Script += ReadString2(e.Params[0]);
+        Script += " ";
+        Script += ReadString2(e.Params[1]);
+        Script += " ";
+        Script += UIntToString(e.Params[2]);
+        break;
+      }
+
+      case EW_CREATESHORTCUT:
+      {
+        AString s;
+
+        Script += " ";
+        Script += ReadString2Qw(e.Params[0]);
+
+        Script += " ";
+        Script += ReadString2Qw(e.Params[1]);
+
+        for (int j = 2; j < 5; j++)
+        {
+          Script += " ";
+          Script += UIntToString(e.Params[j]);
+        }
+        break;
+      }
+
+      /*
+      case EW_DELREG:
+      {
+        AString keyName, valueName;
+        keyName = ReadString2(e.Params[1]);
+        bool isValue = (e.Params[2] != -1);
+        if (isValue)
+        {
+          valueName = ReadString2(e.Params[2]);
+          Script += "Key";
+        }
+        else
+          Script += "Value";
+        Script += " ";
+        Script += UIntToString(e.Params[0]);
+        Script += " ";
+        Script += keyName;
+        if (isValue)
+        {
+          Script += " ";
+          Script += valueName;
+        }
+        Script += " ";
+        Script += UIntToString(e.Params[3]);
+        break;
+      }
+      */
+
+      case EW_WRITEREG:
+      {
+        AString s;
+        switch(e.Params[4])
+        {
+          case 1:  s = "Str"; break;
+          case 2:  s = "ExpandStr"; break;
+          case 3:  s = "Bin"; break;
+          case 4:  s = "DWORD"; break;
+          default: s = "?" + UIntToString(e.Params[4]); break;
+        }
+        Script += s;
+        Script += " ";
+        Script += GetRegRootID(e.Params[0]);
+        Script += " ";
+
+        AString keyName, valueName;
+        keyName = ReadString2Qw(e.Params[1]);
+        Script += keyName;
+        Script += " ";
+        
+        valueName = ReadString2Qw(e.Params[2]);
+        Script += valueName;
+        Script += " ";
+
+        valueName = ReadString2Qw(e.Params[3]);
+        Script += valueName;
+        Script += " ";
+
+        break;
+      }
+
+      case EW_WRITEUNINSTALLER:
+      {
+        Script += " ";
+        Script += ReadString2(e.Params[0]);
+        for (int j = 1; j < 3; j++)
+        {
+          Script += " ";
+          Script += UIntToString(e.Params[j]);
+        }
+        break;
+      }
+
+      default:
+      {
+        int numParams = kNumEntryParams;
+        if (e.Which < sizeof(kCommandPairs) / sizeof(kCommandPairs[0]))
+        {
+          const CCommandPair &pair = kCommandPairs[e.Which];
+          // Script += pair.Name;
+          numParams = pair.NumParams;
+        }
+        else
+        {
+          Script += "Unknown";
+          Script += UIntToString(e.Which);
+        }
+        Script += e.GetParamsString(numParams);
+      }
+      #endif
+    }
+    #ifdef NSIS_SCRIPT
+    Script += kCrLf;
+    #endif
+  }
+
+  {
+    Items.Sort(CompareItems, 0);
+    int i;
+    // if (IsSolid)
+    for (i = 0; i + 1 < Items.Size();)
+    {
+      bool sameName = IsUnicode ?
+        (Items[i].NameU == Items[i + 1].NameU) :
+        (Items[i].NameA == Items[i + 1].NameA);
+      if (Items[i].Pos == Items[i + 1].Pos && sameName)
+        Items.Delete(i + 1);
+      else
+        i++;
+    }
+    for (i = 0; i < Items.Size(); i++)
+    {
+      CItem &item = Items[i];
+      UInt32 curPos = item.Pos + 4;
+      for (int nextIndex = i + 1; nextIndex < Items.Size(); nextIndex++)
+      {
+        UInt32 nextPos = Items[nextIndex].Pos;
+        if (curPos <= nextPos)
+        {
+          item.EstimatedSizeIsDefined = true;
+          item.EstimatedSize = nextPos - curPos;
+          break;
+        }
+      }
+    }
+    if (!IsSolid)
+    {
+      for (i = 0; i < Items.Size(); i++)
+      {
+        CItem &item = Items[i];
+        RINOK(_stream->Seek(GetPosOfNonSolidItem(i), STREAM_SEEK_SET, NULL));
+        const UInt32 kSigSize = 4 + 1 + 5;
+        BYTE sig[kSigSize];
+        size_t processedSize = kSigSize;
+        RINOK(ReadStream(_stream, sig, &processedSize));
+        if (processedSize < 4)
+          return S_FALSE;
+        UInt32 size = Get32(sig);
+        if ((size & 0x80000000) != 0)
+        {
+          item.IsCompressed = true;
+          // is compressed;
+          size &= ~0x80000000;
+          if (Method == NMethodType::kLZMA)
+          {
+            if (processedSize < 9)
+              return S_FALSE;
+            if (FilterFlag)
+              item.UseFilter = (sig[4] != 0);
+            item.DictionarySize = Get32(sig + 5 + (FilterFlag ? 1 : 0));
+          }
+        }
+        else
+        {
+          item.IsCompressed = false;
+          item.Size = size;
+          item.SizeIsDefined = true;
+        }
+        item.CompressedSize = size;
+        item.CompressedSizeIsDefined = true;
+      }
+    }
+  }
+  return S_OK;
+}
+
+HRESULT CInArchive::Parse()
+{
+  // UInt32 offset = ReadUInt32();
+  // ???? offset == FirstHeader.HeaderLength
+  /* UInt32 ehFlags = */ ReadUInt32();
+  CBlockHeader bhPages, bhSections, bhEntries, bhStrings, bhLangTables, bhCtlColors, bhData;
+  // CBlockHeader bgFont;
+  ReadBlockHeader(bhPages);
+  ReadBlockHeader(bhSections);
+  ReadBlockHeader(bhEntries);
+  ReadBlockHeader(bhStrings);
+  ReadBlockHeader(bhLangTables);
+  ReadBlockHeader(bhCtlColors);
+  // ReadBlockHeader(bgFont);
+  ReadBlockHeader(bhData);
+
+  _stringsPos = bhStrings.Offset;
+  UInt32 pos = GetOffset() + _stringsPos;
+  int numZeros0 = 0;
+  int numZeros1 = 0;
+  int i;
+  const int kBlockSize = 256;
+  for (i = 0; i < kBlockSize; i++)
+  {
+    if (pos >= _size || pos + 1 >= _size)
+      break;
+    char c0 = _data[pos++];
+    char c1 = _data[pos++];
+    wchar_t c = (c0 | ((wchar_t)c1 << 8));
+
+    if (c >= NS_UN_CODES_START && c < NS_UN_CODES_END)
+    {
+      if (pos >= _size || pos + 1 >= _size)
+        break;
+      pos += 2;
+      numZeros1++;
+    }
+    else
+    {
+      if (c0 == 0 && c1 != 0)
+        numZeros0++;
+      if (c1 == 0)
+        numZeros1++;
+    }
+    // printf("\nnumZeros0 = %2x %2x", _data[pos + 0],  _data[pos + 1]);
+  }
+  IsUnicode = (numZeros1 > numZeros0 * 3 + kBlockSize / 16);
+  // printf("\nnumZeros0 = %3d    numZeros1 = %3d", numZeros0,  numZeros1);
+  return ReadEntries(bhEntries);
+}
+
+static bool IsLZMA(const Byte *p, UInt32 &dictionary)
+{
+  dictionary = Get32(p + 1);
+  return (p[0] == 0x5D && p[1] == 0x00 && p[2] == 0x00 && p[5] == 0x00);
+}
+
+static bool IsLZMA(const Byte *p, UInt32 &dictionary, bool &thereIsFlag)
+{
+  if (IsLZMA(p, dictionary))
+  {
+    thereIsFlag = false;
+    return true;
+  }
+  if (IsLZMA(p + 1, dictionary))
+  {
+    thereIsFlag = true;
+    return true;
+  }
+  return false;
+}
+
+static bool IsBZip2(const Byte *p)
+{
+  return (p[0] == 0x31 && p[1] < 14);
+}
+
+HRESULT CInArchive::Open2(
+      DECL_EXTERNAL_CODECS_LOC_VARS2
+      )
+{
+  RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &StreamOffset));
+
+  const UInt32 kSigSize = 4 + 1 + 5 + 1; // size, flag, lzma props, lzma first byte
+  BYTE sig[kSigSize];
+  RINOK(ReadStream_FALSE(_stream, sig, kSigSize));
+  UInt64 position;
+  RINOK(_stream->Seek(StreamOffset, STREAM_SEEK_SET, &position));
+
+  _headerIsCompressed = true;
+  IsSolid = true;
+  FilterFlag = false;
+  DictionarySize = 1;
+
+  UInt32 compressedHeaderSize = Get32(sig);
+  
+  if (compressedHeaderSize == FirstHeader.HeaderLength)
+  {
+    _headerIsCompressed = false;
+    IsSolid = false;
+    Method = NMethodType::kCopy;
+  }
+  else if (IsLZMA(sig, DictionarySize, FilterFlag))
+  {
+    Method = NMethodType::kLZMA;
+  }
+  else if (IsLZMA(sig + 4, DictionarySize, FilterFlag))
+  {
+    IsSolid = false;
+    Method = NMethodType::kLZMA;
+  }
+  else if (sig[3] == 0x80)
+  {
+    IsSolid = false;
+    if (IsBZip2(sig + 4))
+      Method = NMethodType::kBZip2;
+    else
+      Method = NMethodType::kDeflate;
+  }
+  else if (IsBZip2(sig))
+  {
+    Method = NMethodType::kBZip2;
+  }
+  else
+  {
+    Method = NMethodType::kDeflate;
+  }
+
+  _posInData = 0;
+  if (!IsSolid)
+  {
+    _headerIsCompressed = ((compressedHeaderSize & 0x80000000) != 0);
+    if (_headerIsCompressed)
+      compressedHeaderSize &= ~0x80000000;
+    _nonSolidStartOffset = compressedHeaderSize;
+    RINOK(_stream->Seek(StreamOffset + 4, STREAM_SEEK_SET, NULL));
+  }
+  UInt32 unpackSize = FirstHeader.HeaderLength;
+  if (_headerIsCompressed)
+  {
+    // unpackSize = (1 << 23);
+    _data.SetCapacity(unpackSize);
+    RINOK(Decoder.Init(
+        EXTERNAL_CODECS_LOC_VARS
+        _stream, Method, FilterFlag, UseFilter));
+    size_t processedSize = unpackSize;
+    RINOK(Decoder.Read(_data, &processedSize));
+    if (processedSize != unpackSize)
+      return S_FALSE;
+    _size = processedSize;
+    if (IsSolid)
+    {
+      UInt32 size2 = ReadUInt32();
+      if (size2 < _size)
+        _size = size2;
+    }
+  }
+  else
+  {
+    _data.SetCapacity(unpackSize);
+    _size = (size_t)unpackSize;
+    RINOK(ReadStream_FALSE(_stream, (Byte *)_data, unpackSize));
+  }
+  return Parse();
+}
+
+/*
+NsisExe =
+{
+  ExeStub
+  Archive  // must start from 512 * N
+  #ifndef NSIS_CONFIG_CRC_ANAL
+  {
+    Some additional data
+  }
+}
+
+Archive
+{
+  FirstHeader
+  Data
+  #ifdef NSIS_CONFIG_CRC_SUPPORT && FirstHeader.ThereIsCrc()
+  {
+    CRC
+  }
+}
+
+FirstHeader
+{
+  UInt32 Flags;
+  Byte Signature[16];
+  // points to the header+sections+entries+stringtable in the datablock
+  UInt32 HeaderLength;
+  UInt32 ArchiveSize;
+}
+*/
+
+HRESULT CInArchive::Open(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    IInStream *inStream, const UInt64 *maxCheckStartPosition)
+{
+  Clear();
+  RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
+  UInt64 maxSize = ((maxCheckStartPosition != 0) ? *maxCheckStartPosition : 0);
+  const UInt32 kStep = 512;
+  Byte buffer[kStep];
+  
+  UInt64 position = 0;
+  for (; position <= maxSize; position += kStep)
+  {
+    RINOK(ReadStream_FALSE(inStream, buffer, kStep));
+    if (memcmp(buffer + 4, kSignature, kSignatureSize) == 0)
+      break;
+  }
+  if (position > maxSize)
+    return S_FALSE;
+  const UInt32 kStartHeaderSize = 4 * 7;
+  RINOK(inStream->Seek(0, STREAM_SEEK_END, &_archiveSize));
+  RINOK(inStream->Seek(position + kStartHeaderSize, STREAM_SEEK_SET, 0));
+  FirstHeader.Flags = Get32(buffer);
+  FirstHeader.HeaderLength = Get32(buffer + kSignatureSize + 4);
+  FirstHeader.ArchiveSize = Get32(buffer + kSignatureSize + 8);
+  if (_archiveSize - position < FirstHeader.ArchiveSize)
+    return S_FALSE;
+
+  try
+  {
+    _stream = inStream;
+    HRESULT res = Open2(EXTERNAL_CODECS_LOC_VARS2);
+    if (res != S_OK)
+      Clear();
+    _stream.Release();
+    return res;
+  }
+  catch(...) { Clear(); return S_FALSE; }
+}
+
+void CInArchive::Clear()
+{
+  #ifdef NSIS_SCRIPT
+  Script.Empty();
+  #endif
+  Items.Clear();
+  _stream.Release();
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisIn.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisIn.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisIn.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisIn.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,181 @@
+// NsisIn.h
+
+#ifndef __ARCHIVE_NSIS_IN_H
+#define __ARCHIVE_NSIS_IN_H
+
+#include "Common/Buffer.h"
+#include "Common/MyCom.h"
+#include "Common/StringConvert.h"
+
+#include "NsisDecode.h"
+
+// #define NSIS_SCRIPT
+
+namespace NArchive {
+namespace NNsis {
+
+const int kSignatureSize = 16;
+#define NSIS_SIGNATURE { 0xEF, 0xBE, 0xAD, 0xDE, 0x4E, 0x75, 0x6C, 0x6C, 0x73, 0x6F, 0x66, 0x74, 0x49, 0x6E, 0x73, 0x74}
+
+extern Byte kSignature[kSignatureSize];
+
+const UInt32 kFlagsMask = 0xF;
+namespace NFlags
+{
+  const UInt32 kUninstall = 1;
+  const UInt32 kSilent = 2;
+  const UInt32 kNoCrc = 4;
+  const UInt32 kForceCrc = 8;
+}
+
+struct CFirstHeader
+{
+  UInt32 Flags;
+  UInt32 HeaderLength;
+ 
+  UInt32 ArchiveSize;
+
+  bool ThereIsCrc() const
+  {
+    if ((Flags & NFlags::kForceCrc ) != 0)
+      return true;
+    return ((Flags & NFlags::kNoCrc) == 0);
+  }
+
+  UInt32 GetDataSize() const { return ArchiveSize - (ThereIsCrc() ? 4 : 0); }
+};
+
+
+struct CBlockHeader
+{
+  UInt32 Offset;
+  UInt32 Num;
+};
+
+struct CItem
+{
+  AString PrefixA;
+  UString PrefixU;
+  AString NameA;
+  UString NameU;
+  FILETIME MTime;
+  bool IsUnicode;
+  bool UseFilter;
+  bool IsCompressed;
+  bool SizeIsDefined;
+  bool CompressedSizeIsDefined;
+  bool EstimatedSizeIsDefined;
+  UInt32 Pos;
+  UInt32 Size;
+  UInt32 CompressedSize;
+  UInt32 EstimatedSize;
+  UInt32 DictionarySize;
+  
+  CItem(): IsUnicode(false), UseFilter(false), IsCompressed(true), SizeIsDefined(false),
+      CompressedSizeIsDefined(false), EstimatedSizeIsDefined(false), Size(0), DictionarySize(1) {}
+
+  bool IsINSTDIR() const
+  {
+    return (PrefixA.Length() >= 3 || PrefixU.Length() >= 3);
+  }
+
+  UString GetReducedName(bool unicode) const
+  {
+    UString s;
+    if (unicode)
+      s = PrefixU;
+    else
+      s = MultiByteToUnicodeString(PrefixA);
+    if (s.Length() > 0)
+      if (s[s.Length() - 1] != L'\\')
+        s += L'\\';
+    if (unicode)
+      s += NameU;
+    else
+      s += MultiByteToUnicodeString(NameA);
+    const int len = 9;
+    if (s.Left(len).CompareNoCase(L"$INSTDIR\\") == 0)
+      s = s.Mid(len);
+    return s;
+  }
+};
+
+class CInArchive
+{
+  UInt64 _archiveSize;
+  CMyComPtr<IInStream> _stream;
+
+  Byte ReadByte();
+  UInt32 ReadUInt32();
+  HRESULT Open2(
+      DECL_EXTERNAL_CODECS_LOC_VARS2
+      );
+  void ReadBlockHeader(CBlockHeader &bh);
+  AString ReadStringA(UInt32 pos) const;
+  UString ReadStringU(UInt32 pos) const;
+  AString ReadString2A(UInt32 pos) const;
+  UString ReadString2U(UInt32 pos) const;
+  AString ReadString2(UInt32 pos) const;
+  AString ReadString2Qw(UInt32 pos) const;
+  HRESULT ReadEntries(const CBlockHeader &bh);
+  HRESULT Parse();
+
+  CByteBuffer _data;
+  UInt64 _size;
+
+  size_t _posInData;
+
+  UInt32 _stringsPos;
+
+
+  bool _headerIsCompressed;
+  UInt32 _nonSolidStartOffset;
+public:
+  HRESULT Open(
+      DECL_EXTERNAL_CODECS_LOC_VARS
+      IInStream *inStream, const UInt64 *maxCheckStartPosition);
+  void Clear();
+
+  UInt64 StreamOffset;
+  CDecoder Decoder;
+  CObjectVector<CItem> Items;
+  CFirstHeader FirstHeader;
+  NMethodType::EEnum Method;
+  UInt32 DictionarySize;
+  bool IsSolid;
+  bool UseFilter;
+  bool FilterFlag;
+  bool IsUnicode;
+
+  #ifdef NSIS_SCRIPT
+  AString Script;
+  #endif
+  UInt32 GetOffset() const { return IsSolid ? 4 : 0; }
+  UInt64 GetDataPos(int index)
+  {
+    const CItem &item = Items[index];
+    return GetOffset() + FirstHeader.HeaderLength + item.Pos;
+  }
+
+  UInt64 GetPosOfSolidItem(int index) const
+  {
+    const CItem &item = Items[index];
+    return 4 + FirstHeader.HeaderLength + item.Pos;
+  }
+  
+  UInt64 GetPosOfNonSolidItem(int index) const
+  {
+    const CItem &item = Items[index];
+    return StreamOffset + _nonSolidStartOffset + 4  + item.Pos;
+  }
+
+  void Release()
+  {
+    Decoder.Release();
+  }
+
+};
+
+}}
+  
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisRegister.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisRegister.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisRegister.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Nsis/NsisRegister.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,13 @@
+// NsisRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterArc.h"
+
+#include "NsisHandler.h"
+static IInArchive *CreateArc() { return new NArchive::NNsis::CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"Nsis", L"", 0, 0x9, NSIS_SIGNATURE, NArchive::NNsis::kSignatureSize, false, CreateArc, 0 };
+
+REGISTER_ARC(Nsis)

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/NtfsHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/NtfsHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/NtfsHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/NtfsHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,1764 @@
+// NtfsHandler.cpp
+
+#include "StdAfx.h"
+
+// #define SHOW_DEBUG_INFO
+// #define SHOW_DEBUG_INFO2
+
+#if defined(SHOW_DEBUG_INFO) || defined(SHOW_DEBUG_INFO2)
+#include <stdio.h>
+#endif
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/Buffer.h"
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+#include "Common/MyCom.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+
+#include "Common/DummyOutStream.h"
+
+#ifdef SHOW_DEBUG_INFO
+#define PRF(x) x
+#else
+#define PRF(x)
+#endif
+
+#ifdef SHOW_DEBUG_INFO2
+#define PRF2(x) x
+#else
+#define PRF2(x)
+#endif
+
+#define Get16(p) GetUi16(p)
+#define Get32(p) GetUi32(p)
+#define Get64(p) GetUi64(p)
+
+#define G16(p, dest) dest = Get16(p);
+#define G32(p, dest) dest = Get32(p);
+#define G64(p, dest) dest = Get64(p);
+
+namespace NArchive {
+namespace Ntfs {
+
+static const UInt32 kNumSysRecs = 16;
+static const UInt32 kRecIndex_Volume = 3;
+static const UInt32 kRecIndex_BadClus = 8;
+
+struct CHeader
+{
+  Byte SectorSizeLog;
+  Byte ClusterSizeLog;
+  // Byte MediaType;
+  UInt32 NumHiddenSectors;
+  UInt64 NumClusters;
+  UInt64 MftCluster;
+  UInt64 SerialNumber;
+  UInt16 SectorsPerTrack;
+  UInt16 NumHeads;
+
+  UInt64 GetPhySize() const { return NumClusters << ClusterSizeLog; }
+  UInt32 ClusterSize() const { return (UInt32)1 << ClusterSizeLog; }
+  bool Parse(const Byte *p);
+};
+
+static int GetLog(UInt32 num)
+{
+  for (int i = 0; i < 31; i++)
+    if (((UInt32)1 << i) == num)
+      return i;
+  return -1;
+}
+
+bool CHeader::Parse(const Byte *p)
+{
+  if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA)
+    return false;
+
+  int codeOffset = 0;
+  switch (p[0])
+  {
+    case 0xE9: codeOffset = 3 + (Int16)Get16(p + 1); break;
+    case 0xEB: if (p[2] != 0x90) return false; codeOffset = 2 + (signed char)p[1]; break;
+    default: return false;
+  }
+  Byte sectorsPerClusterLog;
+
+  if (memcmp(p + 3, "NTFS    ", 8) != 0)
+    return false;
+  {
+    int s = GetLog(Get16(p + 11));
+    if (s < 9 || s > 12)
+      return false;
+    SectorSizeLog = (Byte)s;
+    s = GetLog(p[13]);
+    if (s < 0)
+      return false;
+    sectorsPerClusterLog = (Byte)s;
+    ClusterSizeLog = SectorSizeLog + sectorsPerClusterLog;
+  }
+
+  for (int i = 14; i < 21; i++)
+    if (p[i] != 0)
+      return false;
+
+  // MediaType = p[21];
+  if (Get16(p + 22) != 0) // NumFatSectors
+    return false;
+  G16(p + 24, SectorsPerTrack);
+  G16(p + 26, NumHeads);
+  G32(p + 28, NumHiddenSectors);
+  if (Get32(p + 32) != 0) // NumSectors32
+    return false;
+
+  // DriveNumber = p[0x24];
+  if (p[0x25] != 0) // CurrentHead
+    return false;
+  /*
+  NTFS-HDD:   p[0x26] = 0x80
+  NTFS-FLASH: p[0x26] = 0
+  */
+  if (p[0x26] != 0x80 && p[0x26] != 0) // ExtendedBootSig
+    return false;
+  if (p[0x27] != 0) // reserved
+    return false;
+  UInt64 numSectors = Get64(p + 0x28);
+  NumClusters = numSectors >> sectorsPerClusterLog;
+
+  G64(p + 0x30, MftCluster);
+  // G64(p + 0x38, Mft2Cluster);
+  G64(p + 0x48, SerialNumber);
+  UInt32 numClustersInMftRec;
+  UInt32 numClustersInIndexBlock;
+  G32(p + 0x40, numClustersInMftRec);
+  G32(p + 0x44, numClustersInIndexBlock);
+  return (numClustersInMftRec < 256 && numClustersInIndexBlock < 256);
+}
+
+struct CMftRef
+{
+  UInt64 Val;
+  UInt64 GetIndex() const { return Val & (((UInt64)1 << 48) - 1); }
+  UInt16 GetNumber() const { return (UInt16)(Val >> 48); }
+  bool IsBaseItself() const { return Val == 0; }
+};
+
+#define ATNAME(n) ATTR_TYPE_ ## n
+#define DEF_ATTR_TYPE(v, n) ATNAME(n) = v
+
+enum
+{
+  DEF_ATTR_TYPE(0x00, UNUSED),
+  DEF_ATTR_TYPE(0x10, STANDARD_INFO),
+  DEF_ATTR_TYPE(0x20, ATTRIBUTE_LIST),
+  DEF_ATTR_TYPE(0x30, FILE_NAME),
+  DEF_ATTR_TYPE(0x40, OBJECT_ID),
+  DEF_ATTR_TYPE(0x50, SECURITY_DESCRIPTOR),
+  DEF_ATTR_TYPE(0x60, VOLUME_NAME),
+  DEF_ATTR_TYPE(0x70, VOLUME_INFO),
+  DEF_ATTR_TYPE(0x80, DATA),
+  DEF_ATTR_TYPE(0x90, INDEX_ROOT),
+  DEF_ATTR_TYPE(0xA0, INDEX_ALLOCATION),
+  DEF_ATTR_TYPE(0xB0, BITMAP),
+  DEF_ATTR_TYPE(0xC0, REPARSE_POINT),
+  DEF_ATTR_TYPE(0xD0, EA_INFO),
+  DEF_ATTR_TYPE(0xE0, EA),
+  DEF_ATTR_TYPE(0xF0, PROPERTY_SET),
+  DEF_ATTR_TYPE(0x100, LOGGED_UTILITY_STREAM),
+  DEF_ATTR_TYPE(0x1000, FIRST_USER_DEFINED_ATTRIBUTE)
+};
+
+static const Byte kFileNameType_Posix = 0;
+static const Byte kFileNameType_Win32 = 1;
+static const Byte kFileNameType_Dos = 2;
+static const Byte kFileNameType_Win32Dos = 3;
+
+struct CFileNameAttr
+{
+  CMftRef ParentDirRef;
+  // UInt64 CTime;
+  // UInt64 MTime;
+  // UInt64 ThisRecMTime;
+  // UInt64 ATime;
+  // UInt64 AllocatedSize;
+  // UInt64 DataSize;
+  // UInt16 PackedEaSize;
+  UString Name;
+  UInt32 Attrib;
+  Byte NameType;
+  
+  bool IsDos() const { return NameType == kFileNameType_Dos; }
+  bool Parse(const Byte *p, unsigned size);
+};
+
+static void GetString(const Byte *p, unsigned length, UString &res)
+{
+  wchar_t *s = res.GetBuffer(length);
+  for (unsigned i = 0; i < length; i++)
+    s[i] = Get16(p + i * 2);
+  s[length] = 0;
+  res.ReleaseBuffer();
+}
+
+bool CFileNameAttr::Parse(const Byte *p, unsigned size)
+{
+  if (size < 0x42)
+    return false;
+  G64(p + 0x00, ParentDirRef.Val);
+  // G64(p + 0x08, CTime);
+  // G64(p + 0x10, MTime);
+  // G64(p + 0x18, ThisRecMTime);
+  // G64(p + 0x20, ATime);
+  // G64(p + 0x28, AllocatedSize);
+  // G64(p + 0x30, DataSize);
+  G32(p + 0x38, Attrib);
+  // G16(p + 0x3C, PackedEaSize);
+  NameType = p[0x41];
+  unsigned length = p[0x40];
+  if (0x42 + length > size)
+    return false;
+  GetString(p + 0x42, length, Name);
+  return true;
+}
+
+struct CSiAttr
+{
+  UInt64 CTime;
+  UInt64 MTime;
+  // UInt64 ThisRecMTime;
+  UInt64 ATime;
+  UInt32 Attrib;
+
+  /*
+  UInt32 MaxVersions;
+  UInt32 Version;
+  UInt32 ClassId;
+  UInt32 OwnerId;
+  UInt32 SecurityId;
+  UInt64 QuotaCharged;
+  */
+
+  bool Parse(const Byte *p, unsigned size);
+};
+
+bool CSiAttr::Parse(const Byte *p, unsigned size)
+{
+  if (size < 0x24)
+    return false;
+  G64(p + 0x00, CTime);
+  G64(p + 0x08, MTime);
+  // G64(p + 0x10, ThisRecMTime);
+  G64(p + 0x18, ATime);
+  G32(p + 0x20, Attrib);
+  return true;
+}
+
+static const UInt64 kEmptyExtent = (UInt64)(Int64)-1;
+
+struct CExtent
+{
+  UInt64 Virt;
+  UInt64 Phy;
+
+  bool IsEmpty() const { return Phy == kEmptyExtent; }
+};
+
+struct CVolInfo
+{
+  Byte MajorVer;
+  Byte MinorVer;
+  // UInt16 Flags;
+
+  bool Parse(const Byte *p, unsigned size);
+};
+
+bool CVolInfo::Parse(const Byte *p, unsigned size)
+{
+  if (size < 12)
+    return false;
+  MajorVer = p[8];
+  MinorVer = p[9];
+  // Flags = Get16(p + 10);
+  return true;
+}
+
+struct CAttr
+{
+  UInt32 Type;
+  // UInt32 Length;
+  UString Name;
+  // UInt16 Flags;
+  // UInt16 Instance;
+  CByteBuffer Data;
+  Byte NonResident;
+
+  // Non-Resident
+  Byte CompressionUnit;
+  UInt64 LowVcn;
+  UInt64 HighVcn;
+  UInt64 AllocatedSize;
+  UInt64 Size;
+  UInt64 PackSize;
+  UInt64 InitializedSize;
+
+  // Resident
+  // UInt16 ResidentFlags;
+
+  bool IsCompressionUnitSupported() const { return CompressionUnit == 0 || CompressionUnit == 4; }
+
+  UInt32 Parse(const Byte *p, unsigned size);
+  bool ParseFileName(CFileNameAttr &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); }
+  bool ParseSi(CSiAttr &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); }
+  bool ParseVolInfo(CVolInfo &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); }
+  bool ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, int compressionUnit) const;
+  UInt64 GetSize() const { return NonResident ? Size : Data.GetCapacity(); }
+  UInt64 GetPackSize() const
+  {
+    if (!NonResident)
+      return Data.GetCapacity();
+    if (CompressionUnit != 0)
+      return PackSize;
+    return AllocatedSize;
+  }
+};
+
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+
+static int CompareAttr(void *const *elem1, void *const *elem2, void *)
+{
+  const CAttr &a1 = *(*((const CAttr **)elem1));
+  const CAttr &a2 = *(*((const CAttr **)elem2));
+  RINOZ(MyCompare(a1.Type, a2.Type));
+  RINOZ(MyCompare(a1.Name, a2.Name));
+  return MyCompare(a1.LowVcn, a2.LowVcn);
+}
+
+UInt32 CAttr::Parse(const Byte *p, unsigned size)
+{
+  if (size < 4)
+    return 0;
+  G32(p, Type);
+  if (Type == 0xFFFFFFFF)
+    return 4;
+  if (size < 0x18)
+    return 0;
+  PRF(printf(" T=%2X", Type));
+  
+  UInt32 length = Get32(p + 0x04);
+  PRF(printf(" L=%3d", length));
+  if (length > size)
+    return 0;
+  NonResident = p[0x08];
+  {
+    int nameLength = p[9];
+    UInt32 nameOffset = Get16(p + 0x0A);
+    if (nameLength != 0)
+    {
+      if (nameOffset + nameLength * 2 > length)
+        return 0;
+      GetString(p + nameOffset, nameLength, Name);
+      PRF(printf(" N=%S", Name));
+    }
+  }
+
+  // G16(p + 0x0C, Flags);
+  // G16(p + 0x0E, Instance);
+  // PRF(printf(" F=%4X", Flags));
+  // PRF(printf(" Inst=%d", Instance));
+
+  UInt32 dataSize;
+  UInt32 offs;
+  if (NonResident)
+  {
+    if (length < 0x40)
+      return 0;
+    PRF(printf(" NR"));
+    G64(p + 0x10, LowVcn);
+    G64(p + 0x18, HighVcn);
+    G64(p + 0x28, AllocatedSize);
+    G64(p + 0x30, Size);
+    G64(p + 0x38, InitializedSize);
+    G16(p + 0x20, offs);
+    CompressionUnit = p[0x22];
+
+    PackSize = Size;
+    if (CompressionUnit != 0)
+    {
+      if (length < 0x48)
+        return 0;
+      G64(p + 0x40, PackSize);
+      PRF(printf(" PS=%I64x", PackSize));
+    }
+
+    // PRF(printf("\n"));
+    PRF(printf(" ASize=%4I64d", AllocatedSize));
+    PRF(printf(" Size=%I64d", Size));
+    PRF(printf(" IS=%I64d", InitializedSize));
+    PRF(printf(" Low=%I64d", LowVcn));
+    PRF(printf(" High=%I64d", HighVcn));
+    PRF(printf(" CU=%d", (int)CompressionUnit));
+    dataSize = length - offs;
+  }
+  else
+  {
+    if (length < 0x18)
+      return 0;
+    PRF(printf(" RES"));
+    dataSize = Get32(p + 0x10);
+    PRF(printf(" dataSize=%3d", dataSize));
+    offs = Get16(p + 0x14);
+    // G16(p + 0x16, ResidentFlags);
+    // PRF(printf(" ResFlags=%4X", ResidentFlags));
+  }
+  if (offs > length || dataSize > length || length - dataSize < offs)
+    return 0;
+  Data.SetCapacity(dataSize);
+  memcpy(Data, p + offs, dataSize);
+  #ifdef SHOW_DEBUG_INFO
+  PRF(printf("  : "));
+  for (unsigned i = 0; i < Data.GetCapacity(); i++)
+  {
+    PRF(printf(" %02X", (int)Data[i]));
+  }
+  #endif
+  return length;
+}
+
+bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, int compressionUnit) const
+{
+  const Byte *p = Data;
+  unsigned size = (unsigned)Data.GetCapacity();
+  UInt64 vcn = LowVcn;
+  UInt64 lcn = 0;
+  UInt64 highVcn1 = HighVcn + 1;
+  if (LowVcn != extents.Back().Virt || highVcn1 > (UInt64)1 << 63)
+    return false;
+
+  extents.DeleteBack();
+
+  PRF2(printf("\n# ParseExtents # LowVcn = %4I64X # HighVcn = %4I64X", LowVcn, HighVcn));
+
+  while (size > 0)
+  {
+    Byte b = *p++;
+    size--;
+    if (b == 0)
+      break;
+    UInt32 num = b & 0xF;
+    if (num == 0 || num > 8 || num > size)
+      return false;
+
+    int i;
+    UInt64 vSize = p[num - 1];
+    for (i = (int)num - 2; i >= 0; i--)
+      vSize = (vSize << 8) | p[i];
+    if (vSize == 0)
+      return false;
+    p += num;
+    size -= num;
+    if ((highVcn1 - vcn) < vSize)
+      return false;
+
+    num = (b >> 4) & 0xF;
+    if (num > 8 || num > size)
+      return false;
+    CExtent e;
+    e.Virt = vcn;
+    if (num == 0)
+    {
+      if (compressionUnit == 0)
+        return false;
+      e.Phy = kEmptyExtent;
+    }
+    else
+    {
+      Int64 v = (signed char)p[num - 1];
+      for (i = (int)num - 2; i >= 0; i--)
+        v = (v << 8) | p[i];
+      p += num;
+      size -= num;
+      lcn += v;
+      if (lcn > numClustersMax)
+        return false;
+      e.Phy = lcn;
+    }
+    extents.Add(e);
+    vcn += vSize;
+  }
+  CExtent e;
+  e.Phy = kEmptyExtent;
+  e.Virt = vcn;
+  extents.Add(e);
+  return (highVcn1 == vcn);
+}
+
+static const UInt64 kEmptyTag = (UInt64)(Int64)-1;
+
+static const int kNumCacheChunksLog = 1;
+static const UInt32 kNumCacheChunks = (1 << kNumCacheChunksLog);
+
+class CInStream:
+  public IInStream,
+  public CMyUnknownImp
+{
+  UInt64 _virtPos;
+  UInt64 _physPos;
+  UInt64 _curRem;
+  bool _sparseMode;
+  size_t _compressedPos;
+  
+  UInt64 _tags[kNumCacheChunks];
+  int _chunkSizeLog;
+  CByteBuffer _inBuf;
+  CByteBuffer _outBuf;
+public:
+  CMyComPtr<IInStream> Stream;
+  UInt64 Size;
+  UInt64 InitializedSize;
+  int BlockSizeLog;
+  int CompressionUnit;
+  bool InUse;
+  CRecordVector<CExtent> Extents;
+
+  HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }
+
+  UInt32 GetCuSize() const { return (UInt32)1 << (BlockSizeLog + CompressionUnit); }
+  HRESULT InitAndSeek(int compressionUnit)
+  {
+    CompressionUnit = compressionUnit;
+    if (compressionUnit != 0)
+    {
+      UInt32 cuSize = GetCuSize();
+      _inBuf.SetCapacity(cuSize);
+      _chunkSizeLog = BlockSizeLog + CompressionUnit;
+      _outBuf.SetCapacity(kNumCacheChunks << _chunkSizeLog);
+    }
+    for (int i = 0; i < kNumCacheChunks; i++)
+      _tags[i] = kEmptyTag;
+
+    _sparseMode = false;
+    _curRem = 0;
+    _virtPos = 0;
+    _physPos = 0;
+    const CExtent &e = Extents[0];
+    if (!e.IsEmpty())
+      _physPos = e.Phy << BlockSizeLog;
+    return SeekToPhys();
+  }
+
+  MY_UNKNOWN_IMP1(IInStream)
+
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+};
+
+static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte *src, size_t srcLen)
+{
+  size_t destSize = 0;
+  while (destSize < destLen)
+  {
+    if (srcLen < 2 || (destSize & 0xFFF) != 0)
+      break;
+    UInt32 v = Get16(src);
+    if (v == 0)
+      break;
+    src += 2;
+    srcLen -= 2;
+    UInt32 comprSize = (v & 0xFFF) + 1;
+    if (comprSize > srcLen)
+      break;
+    srcLen -= comprSize;
+    if ((v & 0x8000) == 0)
+    {
+      if (comprSize != (1 << 12))
+        break;
+      memcpy(dest + destSize, src, comprSize);
+      src += comprSize;
+      destSize += comprSize;
+    }
+    else
+    {
+      if (destSize + (1 << 12) > outBufLim || (src[0] & 1) != 0)
+        return 0;
+      int numDistBits = 4;
+      UInt32 sbOffset = 0;
+      UInt32 pos = 0;
+
+      do
+      {
+        comprSize--;
+        for (UInt32 mask = src[pos++] | 0x100; mask > 1 && comprSize > 0; mask >>= 1)
+        {
+          if ((mask & 1) == 0)
+          {
+            if (sbOffset >= (1 << 12))
+              return 0;
+            dest[destSize++] = src[pos++];
+            sbOffset++;
+            comprSize--;
+          }
+          else
+          {
+            if (comprSize < 2)
+              return 0;
+            UInt32 v = Get16(src + pos);
+            pos += 2;
+            comprSize -= 2;
+
+            while (((sbOffset - 1) >> numDistBits) != 0)
+              numDistBits++;
+
+            UInt32 len = (v & (0xFFFF >> numDistBits)) + 3;
+            if (sbOffset + len > (1 << 12))
+              return 0;
+            UInt32 dist = (v >> (16 - numDistBits));
+            if (dist >= sbOffset)
+              return 0;
+            Int32 offs = -1 - dist;
+            Byte *p = dest + destSize;
+            for (UInt32 t = 0; t < len; t++)
+              p[t] = p[t + offs];
+            destSize += len;
+            sbOffset += len;
+          }
+        }
+      }
+      while (comprSize > 0);
+      src += pos;
+    }
+  }
+  return destSize;
+}
+
+STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  if (processedSize != NULL)
+    *processedSize = 0;
+  if (_virtPos >= Size)
+    return (Size == _virtPos) ? S_OK: E_FAIL;
+  if (size == 0)
+    return S_OK;
+  UInt64 rem = Size - _virtPos;
+  if (size > rem)
+    size = (UInt32)rem;
+  if (_virtPos >= InitializedSize)
+  {
+    memset((Byte *)data, 0, size);
+    _virtPos += size;
+    *processedSize = size;
+    return S_OK;
+  }
+  rem = InitializedSize - _virtPos;
+  if (size > rem)
+    size = (UInt32)rem;
+
+  while (_curRem == 0)
+  {
+    UInt64 cacheTag = _virtPos >> _chunkSizeLog;
+    UInt32 cacheIndex = (UInt32)cacheTag & (kNumCacheChunks - 1);
+    if (_tags[cacheIndex] == cacheTag)
+    {
+      UInt32 chunkSize = (UInt32)1 << _chunkSizeLog;
+      UInt32 offset = (UInt32)_virtPos & (chunkSize - 1);
+      UInt32 cur = MyMin(chunkSize - offset, size);
+      memcpy(data, _outBuf + (cacheIndex << _chunkSizeLog) + offset, cur);
+      *processedSize = cur;
+      _virtPos += cur;
+      return S_OK;
+    }
+
+    PRF2(printf("\nVirtPos = %6d", _virtPos));
+    
+    UInt32 comprUnitSize = (UInt32)1 << CompressionUnit;
+    UInt64 virtBlock = _virtPos >> BlockSizeLog;
+    UInt64 virtBlock2 = virtBlock & ~((UInt64)comprUnitSize - 1);
+    
+    int left = 0, right = Extents.Size();
+    for (;;)
+    {
+      int mid = (left + right) / 2;
+      if (mid == left)
+        break;
+      if (virtBlock2 < Extents[mid].Virt)
+        right = mid;
+      else
+        left = mid;
+    }
+    
+    bool isCompressed = false;
+    UInt64 virtBlock2End = virtBlock2 + comprUnitSize;
+    if (CompressionUnit != 0)
+      for (int i = left; i < Extents.Size(); i++)
+      {
+        const CExtent &e = Extents[i];
+        if (e.Virt >= virtBlock2End)
+          break;
+        if (e.IsEmpty())
+        {
+          isCompressed = true;
+          break;
+        }
+      }
+
+    int i;
+    for (i = left; Extents[i + 1].Virt <= virtBlock; i++);
+    
+    _sparseMode = false;
+    if (!isCompressed)
+    {
+      const CExtent &e = Extents[i];
+      UInt64 newPos = (e.Phy << BlockSizeLog) + _virtPos - (e.Virt << BlockSizeLog);
+      if (newPos != _physPos)
+      {
+        _physPos = newPos;
+        RINOK(SeekToPhys());
+      }
+      UInt64 next = Extents[i + 1].Virt;
+      if (next > virtBlock2End)
+        next &= ~((UInt64)comprUnitSize - 1);
+      next <<= BlockSizeLog;
+      if (next > Size)
+        next = Size;
+      _curRem = next - _virtPos;
+      break;
+    }
+    bool thereArePhy = false;
+    for (int i2 = left; i2 < Extents.Size(); i2++)
+    {
+      const CExtent &e = Extents[i2];
+      if (e.Virt >= virtBlock2End)
+        break;
+      if (!e.IsEmpty())
+      {
+        thereArePhy = true;
+        break;
+      }
+    }
+    if (!thereArePhy)
+    {
+      _curRem = (Extents[i + 1].Virt << BlockSizeLog) - _virtPos;
+      _sparseMode = true;
+      break;
+    }
+    
+    size_t offs = 0;
+    UInt64 curVirt = virtBlock2;
+    for (i = left; i < Extents.Size(); i++)
+    {
+      const CExtent &e = Extents[i];
+      if (e.IsEmpty())
+        break;
+      if (e.Virt >= virtBlock2End)
+        return S_FALSE;
+      UInt64 newPos = (e.Phy + (curVirt - e.Virt)) << BlockSizeLog;
+      if (newPos != _physPos)
+      {
+        _physPos = newPos;
+        RINOK(SeekToPhys());
+      }
+      UInt64 numChunks = Extents[i + 1].Virt - curVirt;
+      if (curVirt + numChunks > virtBlock2End)
+        numChunks = virtBlock2End - curVirt;
+      size_t compressed = (size_t)numChunks << BlockSizeLog;
+      RINOK(ReadStream_FALSE(Stream, _inBuf + offs, compressed));
+      curVirt += numChunks;
+      _physPos += compressed;
+      offs += compressed;
+    }
+    size_t destLenMax = GetCuSize();
+    size_t destLen = destLenMax;
+    UInt64 rem = Size - (virtBlock2 << BlockSizeLog);
+    if (destLen > rem)
+      destLen = (size_t)rem;
+
+    Byte *dest = _outBuf + (cacheIndex << _chunkSizeLog);
+    size_t destSizeRes = Lznt1Dec(dest, destLenMax, destLen, _inBuf, offs);
+    _tags[cacheIndex] = cacheTag;
+
+    // some files in Vista have destSize > destLen
+    if (destSizeRes < destLen)
+    {
+      memset(dest, 0, destLenMax);
+      if (InUse)
+        return S_FALSE;
+    }
+  }
+  if (size > _curRem)
+    size = (UInt32)_curRem;
+  HRESULT res = S_OK;
+  if (_sparseMode)
+    memset(data, 0, size);
+  else
+  {
+    res = Stream->Read(data, size, &size);
+    _physPos += size;
+  }
+  if (processedSize != NULL)
+    *processedSize = size;
+  _virtPos += size;
+  _curRem -= size;
+  return res;
+}
+ 
+STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+  UInt64 newVirtPos = offset;
+  switch(seekOrigin)
+  {
+    case STREAM_SEEK_SET: break;
+    case STREAM_SEEK_CUR: newVirtPos += _virtPos; break;
+    case STREAM_SEEK_END: newVirtPos += Size; break;
+    default: return STG_E_INVALIDFUNCTION;
+  }
+  if (_virtPos != newVirtPos)
+    _curRem = 0;
+  _virtPos = newVirtPos;
+  if (newPosition)
+    *newPosition = newVirtPos;
+  return S_OK;
+}
+
+class CByteBufStream:
+  public IInStream,
+  public CMyUnknownImp
+{
+  UInt64 _virtPos;
+public:
+  CByteBuffer Buf;
+  void Init() { _virtPos = 0; }
+ 
+  MY_UNKNOWN_IMP1(IInStream)
+
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+};
+
+STDMETHODIMP CByteBufStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  if (processedSize != NULL)
+    *processedSize = 0;
+  if (_virtPos >= Buf.GetCapacity())
+    return (_virtPos == Buf.GetCapacity()) ? S_OK: E_FAIL;
+  UInt64 rem = Buf.GetCapacity() - _virtPos;
+  if (rem < size)
+    size = (UInt32)rem;
+  memcpy(data, Buf + (size_t)_virtPos, size);
+  if (processedSize != NULL)
+    *processedSize = size;
+  _virtPos += size;
+  return S_OK;
+}
+
+STDMETHODIMP CByteBufStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+  switch(seekOrigin)
+  {
+    case STREAM_SEEK_SET: _virtPos = offset; break;
+    case STREAM_SEEK_CUR: _virtPos += offset; break;
+    case STREAM_SEEK_END: _virtPos = Buf.GetCapacity() + offset; break;
+    default: return STG_E_INVALIDFUNCTION;
+  }
+  if (newPosition)
+    *newPosition = _virtPos;
+  return S_OK;
+}
+
+static HRESULT DataParseExtents(int clusterSizeLog, const CObjectVector<CAttr> &attrs,
+    int attrIndex, int attrIndexLim, UInt64 numPhysClusters, CRecordVector<CExtent> &Extents)
+{
+  CExtent e;
+  e.Virt = 0;
+  e.Phy = kEmptyExtent;
+  Extents.Add(e);
+  const CAttr &attr0 = attrs[attrIndex];
+
+  if (attr0.AllocatedSize < attr0.Size ||
+      (attrs[attrIndexLim - 1].HighVcn + 1) != (attr0.AllocatedSize >> clusterSizeLog) ||
+      (attr0.AllocatedSize & ((1 << clusterSizeLog) - 1)) != 0)
+    return S_FALSE;
+  
+  for (int i = attrIndex; i < attrIndexLim; i++)
+    if (!attrs[i].ParseExtents(Extents, numPhysClusters, attr0.CompressionUnit))
+      return S_FALSE;
+
+  UInt64 packSizeCalc = 0;
+  for (int k = 0; k < Extents.Size(); k++)
+  {
+    CExtent &e = Extents[k];
+    if (!e.IsEmpty())
+      packSizeCalc += (Extents[k + 1].Virt - e.Virt) << clusterSizeLog;
+    PRF2(printf("\nSize = %4I64X", Extents[k + 1].Virt - e.Virt));
+    PRF2(printf("  Pos = %4I64X", e.Phy));
+  }
+  
+  if (attr0.CompressionUnit != 0)
+  {
+    if (packSizeCalc != attr0.PackSize)
+      return S_FALSE;
+  }
+  else
+  {
+    if (packSizeCalc != attr0.AllocatedSize)
+      return S_FALSE;
+  }
+  return S_OK;
+}
+
+struct CDataRef
+{
+  int Start;
+  int Num;
+};
+
+static const UInt32 kMagic_FILE = 0x454c4946;
+static const UInt32 kMagic_BAAD = 0x44414142;
+
+struct CMftRec
+{
+  UInt32 Magic;
+  // UInt64 Lsn;
+  UInt16 SeqNumber;
+  UInt16 Flags;
+  // UInt16 LinkCount;
+  // UInt16 NextAttrInstance;
+  CMftRef BaseMftRef;
+  // UInt32 ThisRecNumber;
+  UInt32 MyNumNameLinks;
+
+  CObjectVector<CAttr> DataAttrs;
+  CObjectVector<CFileNameAttr> FileNames;
+  CRecordVector<CDataRef> DataRefs;
+
+  CSiAttr SiAttr;
+
+  void MoveAttrsFrom(CMftRec &src)
+  {
+    DataAttrs += src.DataAttrs;
+    FileNames += src.FileNames;
+    src.DataAttrs.ClearAndFree();
+    src.FileNames.ClearAndFree();
+  }
+
+  UInt64 GetPackSize() const
+  {
+    UInt64 res = 0;
+    for (int i = 0; i < DataRefs.Size(); i++)
+      res += DataAttrs[DataRefs[i].Start].GetPackSize();
+    return res;
+  }
+
+  bool Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber, CObjectVector<CAttr> *attrs);
+
+  bool IsEmpty() const { return (Magic <= 2); }
+  bool IsFILE() const { return (Magic == kMagic_FILE); }
+  bool IsBAAD() const { return (Magic == kMagic_BAAD); }
+
+  bool InUse() const { return (Flags & 1) != 0; }
+  bool IsDir() const { return (Flags & 2) != 0; }
+
+  void ParseDataNames();
+  HRESULT GetStream(IInStream *mainStream, int dataIndex,
+      int clusterSizeLog, UInt64 numPhysClusters, IInStream **stream) const;
+  int GetNumExtents(int dataIndex, int clusterSizeLog, UInt64 numPhysClusters) const;
+
+  UInt64 GetSize(int dataIndex) const { return DataAttrs[DataRefs[dataIndex].Start].GetSize(); }
+
+  CMftRec(): MyNumNameLinks(0) {}
+};
+
+void CMftRec::ParseDataNames()
+{
+  DataRefs.Clear();
+  DataAttrs.Sort(CompareAttr, 0);
+
+  for (int i = 0; i < DataAttrs.Size();)
+  {
+    CDataRef ref;
+    ref.Start = i;
+    for (i++; i < DataAttrs.Size(); i++)
+      if (DataAttrs[ref.Start].Name != DataAttrs[i].Name)
+        break;
+    ref.Num = i - ref.Start;
+    DataRefs.Add(ref);
+  }
+}
+
+HRESULT CMftRec::GetStream(IInStream *mainStream, int dataIndex,
+    int clusterSizeLog, UInt64 numPhysClusters, IInStream **destStream) const
+{
+  *destStream = 0;
+  CByteBufStream *streamSpec = new CByteBufStream;
+  CMyComPtr<IInStream> streamTemp = streamSpec;
+
+  if (dataIndex < 0)
+    return E_FAIL;
+
+  if (dataIndex < DataRefs.Size())
+  {
+    const CDataRef &ref = DataRefs[dataIndex];
+    int numNonResident = 0;
+    int i;
+    for (i = ref.Start; i < ref.Start + ref.Num; i++)
+      if (DataAttrs[i].NonResident)
+        numNonResident++;
+
+    const CAttr &attr0 = DataAttrs[ref.Start];
+      
+    if (numNonResident != 0 || ref.Num != 1)
+    {
+      if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported())
+        return S_FALSE;
+      CInStream *streamSpec = new CInStream;
+      CMyComPtr<IInStream> streamTemp = streamSpec;
+      RINOK(DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + ref.Num, numPhysClusters, streamSpec->Extents));
+      streamSpec->Size = attr0.Size;
+      streamSpec->InitializedSize = attr0.InitializedSize;
+      streamSpec->Stream = mainStream;
+      streamSpec->BlockSizeLog = clusterSizeLog;
+      streamSpec->InUse = InUse();
+      RINOK(streamSpec->InitAndSeek(attr0.CompressionUnit));
+      *destStream = streamTemp.Detach();
+      return S_OK;
+    }
+    streamSpec->Buf = attr0.Data;
+  }
+  streamSpec->Init();
+  *destStream = streamTemp.Detach();
+  return S_OK;
+}
+
+int CMftRec::GetNumExtents(int dataIndex, int clusterSizeLog, UInt64 numPhysClusters) const
+{
+  if (dataIndex < 0)
+    return 0;
+  {
+    const CDataRef &ref = DataRefs[dataIndex];
+    int numNonResident = 0;
+    int i;
+    for (i = ref.Start; i < ref.Start + ref.Num; i++)
+      if (DataAttrs[i].NonResident)
+        numNonResident++;
+
+    const CAttr &attr0 = DataAttrs[ref.Start];
+      
+    if (numNonResident != 0 || ref.Num != 1)
+    {
+      if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported())
+        return 0; // error;
+      CRecordVector<CExtent> extents;
+      if (DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + ref.Num, numPhysClusters, extents) != S_OK)
+        return 0; // error;
+      return extents.Size() - 1;
+    }
+    // if (attr0.Data.GetCapacity() != 0)
+    //   return 1;
+    return 0;
+  }
+}
+
+bool CMftRec::Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber,
+    CObjectVector<CAttr> *attrs)
+{
+  G32(p, Magic);
+  if (!IsFILE())
+    return IsEmpty() || IsBAAD();
+
+  UInt32 usaOffset;
+  UInt32 numUsaItems;
+  G16(p + 0x04, usaOffset);
+  G16(p + 0x06, numUsaItems);
+  
+  if ((usaOffset & 1) != 0 || usaOffset + numUsaItems * 2 > ((UInt32)1 << sectorSizeLog) - 2 ||
+      numUsaItems == 0 || numUsaItems - 1 != numSectors)
+    return false;
+
+  UInt16 usn = Get16(p + usaOffset);
+  // PRF(printf("\nusn = %d", usn));
+  for (UInt32 i = 1; i < numUsaItems; i++)
+  {
+    void *pp = p + (i << sectorSizeLog)  - 2;
+    if (Get16(pp) != usn)
+      return false;
+    SetUi16(pp, Get16(p + usaOffset + i * 2));
+  }
+
+  // G64(p + 0x08, Lsn);
+  G16(p + 0x10, SeqNumber);
+  // G16(p + 0x12, LinkCount);
+  // PRF(printf(" L=%d", LinkCount));
+  UInt32 attrOffs = Get16(p + 0x14);
+  G16(p + 0x16, Flags);
+  PRF(printf(" F=%4X", Flags));
+
+  UInt32 bytesInUse = Get32(p + 0x18);
+  UInt32 bytesAlloc = Get32(p + 0x1C);
+  G64(p + 0x20, BaseMftRef.Val);
+  if (BaseMftRef.Val != 0)
+  {
+    PRF(printf("  BaseRef=%d", (int)BaseMftRef.Val));
+    // return false; // Check it;
+  }
+  // G16(p + 0x28, NextAttrInstance);
+  if (usaOffset >= 0x30)
+    if (Get32(p + 0x2C) != recNumber) // NTFS 3.1+
+      return false;
+
+  UInt32 limit = numSectors << sectorSizeLog;
+  if (attrOffs >= limit || (attrOffs & 7) != 0 || bytesInUse > limit
+      || bytesAlloc != limit)
+    return false;
+
+
+  for (UInt32 t = attrOffs; t < limit;)
+  {
+    CAttr attr;
+    // PRF(printf("\n  %2d:", Attrs.Size()));
+    PRF(printf("\n"));
+    UInt32 length = attr.Parse(p + t, limit - t);
+    if (length == 0 || limit - t < length)
+      return false;
+    t += length;
+    if (attr.Type == 0xFFFFFFFF)
+      break;
+    switch(attr.Type)
+    {
+      case ATTR_TYPE_FILE_NAME:
+      {
+        CFileNameAttr fna;
+        if (!attr.ParseFileName(fna))
+          return false;
+        FileNames.Add(fna);
+        PRF(printf("  flags = %4x", (int)fna.NameType));
+        PRF(printf("\n  %S", fna.Name));
+        break;
+      }
+      case ATTR_TYPE_STANDARD_INFO:
+        if (!attr.ParseSi(SiAttr))
+          return false;
+        break;
+      case ATTR_TYPE_DATA:
+        DataAttrs.Add(attr);
+        break;
+      default:
+        if (attrs)
+          attrs->Add(attr);
+        break;
+    }
+  }
+
+  return true;
+}
+
+struct CItem
+{
+  int RecIndex;
+  int DataIndex;
+  CMftRef ParentRef;
+  UString Name;
+  UInt32 Attrib;
+
+  bool IsDir() const { return (DataIndex < 0); }
+};
+
+struct CDatabase
+{
+  CHeader Header;
+  CObjectVector<CItem> Items;
+  CObjectVector<CMftRec> Recs;
+  CMyComPtr<IInStream> InStream;
+  IArchiveOpenCallback *OpenCallback;
+
+  CByteBuffer ByteBuf;
+
+  CObjectVector<CAttr> VolAttrs;
+
+  ~CDatabase() { ClearAndClose(); }
+
+  void Clear();
+  void ClearAndClose();
+
+  UString GetItemPath(Int32 index) const;
+  HRESULT Open();
+  HRESULT ReadDir(Int32 parent, UInt32 cluster, int level);
+
+  HRESULT SeekToCluster(UInt64 cluster);
+
+  int FindMtfRec(const CMftRef &ref) const
+  {
+    UInt64 val = ref.GetIndex();
+    int left = 0, right = Items.Size();
+    while (left != right)
+    {
+      int mid = (left + right) / 2;
+      UInt64 midValue = Items[mid].RecIndex;
+      if (val == midValue)
+        return mid;
+      if (val < midValue)
+        right = mid;
+      else
+        left = mid + 1;
+    }
+    return -1;
+  }
+
+};
+
+HRESULT CDatabase::SeekToCluster(UInt64 cluster)
+{
+  return InStream->Seek(cluster << Header.ClusterSizeLog, STREAM_SEEK_SET, NULL);
+}
+
+void CDatabase::Clear()
+{
+  Items.Clear();
+  Recs.Clear();
+}
+
+void CDatabase::ClearAndClose()
+{
+  Clear();
+  InStream.Release();
+}
+
+#define MY_DIR_PREFIX(x) L"[" x L"]" WSTRING_PATH_SEPARATOR
+
+UString CDatabase::GetItemPath(Int32 index) const
+{
+  const CItem *item = &Items[index];
+  UString name = item->Name;
+  for (int j = 0; j < 256; j++)
+  {
+    CMftRef ref = item->ParentRef;
+    index = FindMtfRec(ref);
+    if (ref.GetIndex() == 5)
+      return name;
+    if (index < 0 || Recs[Items[index].RecIndex].SeqNumber != ref.GetNumber())
+      return MY_DIR_PREFIX(L"UNKNOWN") + name;
+    item = &Items[index];
+    name = item->Name + WCHAR_PATH_SEPARATOR + name;
+  }
+  return MY_DIR_PREFIX(L"BAD") + name;
+}
+
+HRESULT CDatabase::Open()
+{
+  Clear();
+  
+  static const UInt32 kHeaderSize = 512;
+  Byte buf[kHeaderSize];
+  RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize));
+  if (!Header.Parse(buf))
+    return S_FALSE;
+  UInt64 fileSize;
+  RINOK(InStream->Seek(0, STREAM_SEEK_END, &fileSize));
+  if (fileSize < Header.GetPhySize())
+    return S_FALSE;
+  
+  SeekToCluster(Header.MftCluster);
+
+  CMftRec mftRec;
+  UInt32 numSectorsInRec;
+  int recSizeLog;
+  CMyComPtr<IInStream> mftStream;
+  {
+    UInt32 blockSize = 1 << 12;
+    ByteBuf.SetCapacity(blockSize);
+    RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize));
+    
+    UInt32 allocSize = Get32(ByteBuf + 0x1C);
+    recSizeLog = GetLog(allocSize);
+    if (recSizeLog < Header.SectorSizeLog)
+      return false;
+    numSectorsInRec = 1 << (recSizeLog - Header.SectorSizeLog);
+    if (!mftRec.Parse(ByteBuf, Header.SectorSizeLog, numSectorsInRec, NULL, 0))
+      return S_FALSE;
+    if (!mftRec.IsFILE())
+      return S_FALSE;
+    mftRec.ParseDataNames();
+    if (mftRec.DataRefs.IsEmpty())
+      return S_FALSE;
+    RINOK(mftRec.GetStream(InStream, 0, Header.ClusterSizeLog, Header.NumClusters, &mftStream));
+    if (!mftStream)
+      return S_FALSE;
+  }
+
+  UInt64 mftSize = mftRec.DataAttrs[0].Size;
+  if ((mftSize >> 4) > Header.GetPhySize())
+    return S_FALSE;
+
+  UInt64 numFiles = mftSize >> recSizeLog;
+  if (numFiles > (1 << 30))
+    return S_FALSE;
+  if (OpenCallback)
+  {
+    RINOK(OpenCallback->SetTotal(&numFiles, &mftSize));
+  }
+  const UInt32 kBufSize = (1 << 15);
+  if (kBufSize < (1 << recSizeLog))
+    return S_FALSE;
+
+  ByteBuf.SetCapacity((size_t)kBufSize);
+  Recs.Reserve((int)numFiles);
+  for (UInt64 pos64 = 0;;)
+  {
+    if (OpenCallback)
+    {
+      UInt64 numFiles = Recs.Size();
+      if ((numFiles & 0x3FF) == 0)
+      {
+        RINOK(OpenCallback->SetCompleted(&numFiles, &pos64));
+      }
+    }
+    UInt32 readSize = kBufSize;
+    UInt64 rem = mftSize - pos64;
+    if (readSize > rem)
+      readSize = (UInt32)rem;
+    if (readSize < ((UInt32)1 << recSizeLog))
+      break;
+    RINOK(ReadStream_FALSE(mftStream, ByteBuf, (size_t)readSize));
+    pos64 += readSize;
+    for (int i = 0; ((UInt32)(i + 1) << recSizeLog) <= readSize; i++)
+    {
+      PRF(printf("\n---------------------"));
+      PRF(printf("\n%5d:", Recs.Size()));
+      Byte *p = ByteBuf + ((UInt32)i << recSizeLog);
+      CMftRec rec;
+      if (!rec.Parse(p, Header.SectorSizeLog, numSectorsInRec, (UInt32)Recs.Size(),
+          (Recs.Size() == kRecIndex_Volume) ? &VolAttrs: NULL))
+        return S_FALSE;
+      Recs.Add(rec);
+    }
+  }
+
+  int i;
+  for (i = 0; i < Recs.Size(); i++)
+  {
+    CMftRec &rec = Recs[i];
+    if (!rec.BaseMftRef.IsBaseItself())
+    {
+      UInt64 refIndex = rec.BaseMftRef.GetIndex();
+      if (refIndex > (UInt32)Recs.Size())
+        return S_FALSE;
+      CMftRec &refRec = Recs[(int)refIndex];
+      bool moveAttrs = (refRec.SeqNumber == rec.BaseMftRef.GetNumber() && refRec.BaseMftRef.IsBaseItself());
+      if (rec.InUse() && refRec.InUse())
+      {
+        if (!moveAttrs)
+          return S_FALSE;
+      }
+      else if (rec.InUse() || refRec.InUse())
+        moveAttrs = false;
+      if (moveAttrs)
+        refRec.MoveAttrsFrom(rec);
+    }
+  }
+
+  for (i = 0; i < Recs.Size(); i++)
+    Recs[i].ParseDataNames();
+  
+  for (i = 0; i < Recs.Size(); i++)
+  {
+    CMftRec &rec = Recs[i];
+    if (!rec.IsFILE() || !rec.BaseMftRef.IsBaseItself())
+      continue;
+    int numNames = 0;
+    // printf("\n%4d: ", i);
+    for (int t = 0; t < rec.FileNames.Size(); t++)
+    {
+      const CFileNameAttr &fna = rec.FileNames[t];
+      // printf("%4d %S  | ", (int)fna.NameType, fna.Name);
+      if (fna.IsDos())
+        continue;
+      int numDatas = rec.DataRefs.Size();
+
+      // For hard linked files we show substreams only for first Name.
+      if (numDatas > 1 && numNames > 0)
+        numDatas = 1;
+      numNames++;
+
+      if (rec.IsDir())
+      {
+        CItem item;
+        item.Name = fna.Name;
+        item.RecIndex = i;
+        item.DataIndex = -1;
+        item.ParentRef = fna.ParentDirRef;
+        item.Attrib = rec.SiAttr.Attrib | 0x10;
+        // item.Attrib = fna.Attrib;
+        Items.Add(item);
+      }
+      for (int di = 0; di < numDatas; di++)
+      {
+        CItem item;
+        item.Name = fna.Name;
+        item.Attrib = rec.SiAttr.Attrib;
+        const UString &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name;
+        if (!subName.IsEmpty())
+        {
+          // $BadClus:$Bad is sparse file for all clusters. So we skip it.
+          if (i == kRecIndex_BadClus && subName == L"$Bad")
+            continue;
+          item.Name += L":";
+          item.Name += subName;
+          item.Attrib = fna.Attrib;
+        }
+        
+        PRF(printf("\n%3d", i));
+        PRF(printf("  attrib=%2x", rec.SiAttr.Attrib));
+        PRF(printf(" %S", item.Name));
+        
+        item.RecIndex = i;
+        item.DataIndex = di;
+        item.ParentRef = fna.ParentDirRef;
+
+        Items.Add(item);
+        rec.MyNumNameLinks++;
+      }
+    }
+    rec.FileNames.ClearAndFree();
+  }
+  
+  return S_OK;
+}
+
+class CHandler:
+  public IInArchive,
+  public IInArchiveGetStream,
+  public CMyUnknownImp,
+  CDatabase
+{
+public:
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+  INTERFACE_IInArchive(;)
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+};
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+  COM_TRY_BEGIN
+  IInStream *stream2;
+  const CItem &item = Items[index];
+  const CMftRec &rec = Recs[item.RecIndex];
+  HRESULT res = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &stream2);
+  *stream = (ISequentialInStream *)stream2;
+  return res;
+  COM_TRY_END
+}
+
+static const STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidIsDir, VT_BOOL},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMTime, VT_FILETIME},
+  { NULL, kpidCTime, VT_FILETIME},
+  { NULL, kpidATime, VT_FILETIME},
+  { NULL, kpidAttrib, VT_UI4},
+  { NULL, kpidLinks, VT_UI4},
+  { NULL, kpidNumBlocks, VT_UI4}
+};
+
+static const STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidVolumeName, VT_BSTR},
+  { NULL, kpidFileSystem, VT_BSTR},
+  { NULL, kpidClusterSize, VT_UI4},
+  { NULL, kpidPhySize, VT_UI8},
+  { NULL, kpidHeadersSize, VT_UI8},
+  { NULL, kpidCTime, VT_FILETIME},
+
+  { NULL, kpidSectorSize, VT_UI4},
+  { NULL, kpidId, VT_UI8}
+  // { NULL, kpidSectorsPerTrack, VT_UI4},
+  // { NULL, kpidNumHeads, VT_UI4},
+  // { NULL, kpidHiddenSectors, VT_UI4}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+static void NtfsTimeToProp(UInt64 t, NWindows::NCOM::CPropVariant &prop)
+{
+  FILETIME ft;
+  ft.dwLowDateTime = (DWORD)t;
+  ft.dwHighDateTime = (DWORD)(t >> 32);
+  prop = ft;
+}
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+
+  const CMftRec *volRec = (Recs.Size() > kRecIndex_Volume ? &Recs[kRecIndex_Volume] : NULL);
+
+  switch(propID)
+  {
+    case kpidClusterSize: prop = Header.ClusterSize(); break;
+    case kpidPhySize: prop = Header.GetPhySize(); break;
+    /*
+    case kpidHeadersSize:
+    {
+      UInt64 val = 0;
+      for (int i = 0; i < kNumSysRecs; i++)
+      {
+        printf("\n%2d: %8I64d ", i, Recs[i].GetPackSize());
+        if (i == 8)
+          i = i
+        val += Recs[i].GetPackSize();
+      }
+      prop = val;
+      break;
+    }
+    */
+    case kpidCTime: if (volRec) NtfsTimeToProp(volRec->SiAttr.CTime, prop); break;break;
+    case kpidVolumeName:
+    {
+      for (int i = 0; i < VolAttrs.Size(); i++)
+      {
+        const CAttr &attr = VolAttrs[i];
+        if (attr.Type == ATTR_TYPE_VOLUME_NAME)
+        {
+          UString name;
+          GetString(attr.Data, (int)attr.Data.GetCapacity() / 2, name);
+          prop = name;
+          break;
+        }
+      }
+      break;
+    }
+    case kpidFileSystem:
+    {
+      AString s = "NTFS";
+      for (int i = 0; i < VolAttrs.Size(); i++)
+      {
+        const CAttr &attr = VolAttrs[i];
+        if (attr.Type == ATTR_TYPE_VOLUME_INFO)
+        {
+          CVolInfo vi;
+          if (attr.ParseVolInfo(vi))
+          {
+            s += ' ';
+            char temp[16];
+            ConvertUInt32ToString(vi.MajorVer, temp);
+            s += temp;
+            s += '.';
+            ConvertUInt32ToString(vi.MinorVer, temp);
+            s += temp;
+          }
+          break;
+        }
+      }
+      prop = s;
+      break;
+    }
+    case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break;
+    case kpidId: prop = Header.SerialNumber; break;
+    // case kpidMediaType: prop = Header.MediaType; break;
+    // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break;
+    // case kpidNumHeads: prop = Header.NumHeads; break;
+    // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  const CItem &item = Items[index];
+  const CMftRec &rec = Recs[item.RecIndex];
+
+  const CAttr *data= NULL;
+  if (item.DataIndex >= 0)
+    data = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];
+
+  switch(propID)
+  {
+    case kpidPath:
+    {
+      UString name = GetItemPath(index);
+      const wchar_t *prefix = NULL;
+      if (!rec.InUse())
+        prefix = MY_DIR_PREFIX(L"DELETED");
+      else if (item.RecIndex < kNumSysRecs)
+        prefix = MY_DIR_PREFIX(L"SYSTEM");
+      if (prefix)
+        name = prefix + name;
+      prop = name;
+      break;
+    }
+
+    case kpidIsDir: prop = item.IsDir(); break;
+    case kpidMTime: NtfsTimeToProp(rec.SiAttr.MTime, prop); break;
+      
+    case kpidCTime: NtfsTimeToProp(rec.SiAttr.CTime, prop); break;
+    case kpidATime: NtfsTimeToProp(rec.SiAttr.ATime, prop); break;
+    case kpidAttrib:
+      prop = item.Attrib;
+      break;
+    case kpidLinks: prop = rec.MyNumNameLinks; break;
+    case kpidSize: if (data) prop = data->GetSize(); break;
+    case kpidPackSize: if (data) prop = data->GetPackSize(); break;
+    case kpidNumBlocks: if (data) prop = (UInt32)rec.GetNumExtents(item.DataIndex, Header.ClusterSizeLog, Header.NumClusters); break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)
+{
+  COM_TRY_BEGIN
+  {
+    OpenCallback = callback;
+    InStream = stream;
+    HRESULT res;
+    try
+    {
+      res = CDatabase::Open();
+      if (res == S_OK)
+        return S_OK;
+    }
+    catch(...)
+    {
+      Close();
+      throw;
+    }
+    Close();
+    return res;
+  }
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  ClearAndClose();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = Items.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt32 i;
+  UInt64 totalSize = 0;
+  for (i = 0; i < numItems; i++)
+  {
+    const CItem &item = Items[allFilesMode ? i : indices[i]];
+    const CMftRec &rec = Recs[item.RecIndex];
+    if (!rec.IsDir())
+      totalSize += rec.GetSize(item.DataIndex);
+  }
+  RINOK(extractCallback->SetTotal(totalSize));
+
+  UInt64 totalPackSize;
+  totalSize = totalPackSize = 0;
+  
+  CByteBuffer buf;
+  UInt32 clusterSize = Header.ClusterSize();
+  buf.SetCapacity(clusterSize);
+
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  CDummyOutStream *outStreamSpec = new CDummyOutStream;
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+
+  for (i = 0; i < numItems; i++)
+  {
+    lps->InSize = totalPackSize;
+    lps->OutSize = totalSize;
+    RINOK(lps->SetCur());
+    CMyComPtr<ISequentialOutStream> realOutStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    Int32 index = allFilesMode ? i : indices[i];
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+    const CItem &item = Items[index];
+    if (item.IsDir())
+    {
+      RINOK(extractCallback->PrepareOperation(askMode));
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+      continue;
+    }
+
+    if (!testMode && !realOutStream)
+      continue;
+    RINOK(extractCallback->PrepareOperation(askMode));
+
+    outStreamSpec->SetStream(realOutStream);
+    realOutStream.Release();
+    outStreamSpec->Init();
+
+    const CMftRec &rec = Recs[item.RecIndex];
+    const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];
+
+    int res = NExtract::NOperationResult::kDataError;
+    {
+      CMyComPtr<IInStream> inStream;
+      HRESULT hres = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &inStream);
+      if (hres == S_FALSE)
+        res = NExtract::NOperationResult::kUnSupportedMethod;
+      else
+      {
+        RINOK(hres);
+        if (inStream)
+        {
+          HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
+          if (hres != S_OK &&  hres != S_FALSE)
+          {
+            RINOK(hres);
+          }
+          if (/* copyCoderSpec->TotalSize == item.GetSize() && */ hres == S_OK)
+            res = NExtract::NOperationResult::kOK;
+        }
+      }
+    }
+    totalPackSize += data.GetPackSize();
+    totalSize += data.GetSize();
+    outStreamSpec->ReleaseStream();
+    RINOK(extractCallback->SetOperationResult(res));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = Items.Size();
+  return S_OK;
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"NTFS", L"ntfs img", 0, 0xD9, { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 }, 9, false, CreateArc, 0 };
+
+REGISTER_ARC(Fat)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/PeHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/PeHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/PeHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/PeHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,1752 @@
+// PeHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/DynamicBuffer.h"
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/PropVariantUtils.h"
+#include "Windows/Time.h"
+
+#include "../Common/LimitedStreams.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamObjects.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+
+#define Get16(p) GetUi16(p)
+#define Get32(p) GetUi32(p)
+#define Get64(p) GetUi64(p)
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NPe {
+
+#define NUM_SCAN_SECTIONS_MAX (1 << 6)
+
+#define PE_SIG 0x00004550
+#define PE_OptHeader_Magic_32 0x10B
+#define PE_OptHeader_Magic_64 0x20B
+
+static AString GetDecString(UInt32 v)
+{
+  char sz[32];
+  ConvertUInt64ToString(v, sz);
+  return sz;
+}
+
+struct CVersion
+{
+  UInt16 Major;
+  UInt16 Minor;
+
+  void Parse(const Byte *buf);
+  AString GetString() const { return GetDecString(Major) + '.' + GetDecString(Minor); }
+};
+
+void CVersion::Parse(const Byte *p)
+{
+  Major = Get16(p);
+  Minor = Get16(p + 2);
+}
+
+static const UInt32 kHeaderSize =  4 + 20;
+
+struct CHeader
+{
+  UInt16 NumSections;
+  UInt32 Time;
+  UInt32 PointerToSymbolTable;
+  UInt32 NumSymbols;
+  UInt16 OptHeaderSize;
+  UInt16 Flags;
+  UInt16 Machine;
+
+  bool Parse(const Byte *buf);
+};
+
+bool CHeader::Parse(const Byte *p)
+{
+  if (Get32(p) != PE_SIG)
+    return false;
+  p += 4;
+  Machine = Get16(p + 0);
+  NumSections = Get16(p + 2);
+  Time = Get32(p + 4);
+  PointerToSymbolTable = Get32(p + 8);
+  NumSymbols = Get32(p + 12);
+  OptHeaderSize = Get16(p + 16);
+  Flags = Get16(p + 18);
+  return true;
+}
+
+struct CDirLink
+{
+  UInt32 Va;
+  UInt32 Size;
+  void Parse(const Byte *p);
+};
+
+void CDirLink::Parse(const Byte *p)
+{
+  Va = Get32(p);
+  Size = Get32(p + 4);
+}
+
+enum
+{
+  kDirLink_Certificate = 4,
+  kDirLink_Debug = 6
+};
+
+struct CDebugEntry
+{
+  UInt32 Flags;
+  UInt32 Time;
+  CVersion Ver;
+  UInt32 Type;
+  UInt32 Size;
+  UInt32 Va;
+  UInt32 Pa;
+  
+  void Parse(const Byte *p);
+};
+
+void CDebugEntry::Parse(const Byte *p)
+{
+  Flags = Get32(p);
+  Time = Get32(p + 4);
+  Ver.Parse(p + 8);
+  Type = Get32(p + 12);
+  Size = Get32(p + 16);
+  Va = Get32(p + 20);
+  Pa = Get32(p + 24);
+}
+
+static const UInt32 kNumDirItemsMax = 16;
+
+struct COptHeader
+{
+  UInt16 Magic;
+  Byte LinkerVerMajor;
+  Byte LinkerVerMinor;
+
+  UInt32 CodeSize;
+  UInt32 InitDataSize;
+  UInt32 UninitDataSize;
+  
+  // UInt32 AddressOfEntryPoint;
+  // UInt32 BaseOfCode;
+  // UInt32 BaseOfData32;
+  UInt64 ImageBase;
+
+  UInt32 SectAlign;
+  UInt32 FileAlign;
+
+  CVersion OsVer;
+  CVersion ImageVer;
+  CVersion SubsysVer;
+  
+  UInt32 ImageSize;
+  UInt32 HeadersSize;
+  UInt32 CheckSum;
+  UInt16 SubSystem;
+  UInt16 DllCharacts;
+
+  UInt64 StackReserve;
+  UInt64 StackCommit;
+  UInt64 HeapReserve;
+  UInt64 HeapCommit;
+
+  UInt32 NumDirItems;
+  CDirLink DirItems[kNumDirItemsMax];
+
+  bool Is64Bit() const { return Magic == PE_OptHeader_Magic_64; }
+  bool Parse(const Byte *p, UInt32 size);
+
+  int GetNumFileAlignBits() const
+  {
+    for (int i = 9; i <= 16; i++)
+      if (((UInt32)1 << i) == FileAlign)
+        return i;
+    return -1;
+  }
+};
+
+bool COptHeader::Parse(const Byte *p, UInt32 size)
+{
+  Magic = Get16(p);
+  switch (Magic)
+  {
+    case PE_OptHeader_Magic_32:
+    case PE_OptHeader_Magic_64:
+      break;
+    default:
+      return false;
+  }
+  LinkerVerMajor = p[2];
+  LinkerVerMinor = p[3];
+  
+  bool hdr64 = Is64Bit();
+  
+  CodeSize = Get32(p + 4);
+  InitDataSize = Get32(p + 8);
+  UninitDataSize = Get32(p + 12);
+
+  // AddressOfEntryPoint = Get32(p + 16);
+  // BaseOfCode = Get32(p + 20);
+  // BaseOfData32 = hdr64 ? 0: Get32(p + 24);
+  ImageBase = hdr64 ? GetUi64(p + 24) : Get32(p + 28);
+
+  SectAlign = Get32(p + 32);
+  FileAlign = Get32(p + 36);
+
+  OsVer.Parse(p + 40);
+  ImageVer.Parse(p + 44);
+  SubsysVer.Parse(p + 48);
+
+  // reserved = Get32(p + 52);
+
+  ImageSize = Get32(p + 56);
+  HeadersSize = Get32(p + 60);
+  CheckSum = Get32(p + 64);
+  SubSystem = Get16(p + 68);
+  DllCharacts = Get16(p + 70);
+
+  if (hdr64)
+  {
+    StackReserve = Get64(p + 72);
+    StackCommit = Get64(p + 80);
+    HeapReserve = Get64(p + 88);
+    HeapCommit = Get64(p + 96);
+  }
+  else
+  {
+    StackReserve = Get32(p + 72);
+    StackCommit = Get32(p + 76);
+    HeapReserve = Get32(p + 80);
+    HeapCommit = Get32(p + 84);
+  }
+  UInt32 pos = (hdr64 ? 108 : 92);
+  NumDirItems = Get32(p + pos);
+  pos += 4;
+  if (pos + 8 * NumDirItems != size)
+    return false;
+  for (UInt32 i = 0; i < NumDirItems && i < kNumDirItemsMax; i++)
+    DirItems[i].Parse(p + pos + i * 8);
+  return true;
+}
+
+static const UInt32 kSectionSize = 40;
+
+struct CSection
+{
+  AString Name;
+
+  UInt32 VSize;
+  UInt32 Va;
+  UInt32 PSize;
+  UInt32 Pa;
+  UInt32 Flags;
+  UInt32 Time;
+  // UInt16 NumRelocs;
+  bool IsDebug;
+  bool IsRealSect;
+  bool IsAdditionalSection;
+
+  CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {}
+  UInt64 GetPackSize() const { return PSize; }
+
+  void UpdateTotalSize(UInt32 &totalSize)
+  {
+    UInt32 t = Pa + PSize;
+    if (t > totalSize)
+      totalSize = t;
+  }
+  void Parse(const Byte *p);
+};
+
+static bool operator <(const CSection &a1, const CSection &a2) { return (a1.Pa < a2.Pa) || ((a1.Pa == a2.Pa) && (a1.PSize < a2.PSize)) ; }
+static bool operator ==(const CSection &a1, const CSection &a2) { return (a1.Pa == a2.Pa) && (a1.PSize == a2.PSize); }
+
+static AString GetName(const Byte *name)
+{
+  const int kNameSize = 8;
+  AString res;
+  char *p = res.GetBuffer(kNameSize);
+  memcpy(p, name, kNameSize);
+  p[kNameSize] = 0;
+  res.ReleaseBuffer();
+  return res;
+}
+
+void CSection::Parse(const Byte *p)
+{
+  Name = GetName(p);
+  VSize = Get32(p + 8);
+  Va = Get32(p + 12);
+  PSize = Get32(p + 16);
+  Pa = Get32(p + 20);
+  // NumRelocs = Get16(p + 32);
+  Flags = Get32(p + 36);
+}
+
+static const CUInt32PCharPair g_HeaderCharacts[] =
+{
+  {  1, "Executable" },
+  { 13, "DLL" },
+  {  8, "32-bit" },
+  {  5, "LargeAddress" },
+  {  0, "NoRelocs" },
+  {  2, "NoLineNums" },
+  {  3, "NoLocalSyms" },
+  {  4, "AggressiveWsTrim" },
+  {  9, "NoDebugInfo" },
+  { 10, "RemovableRun" },
+  { 11, "NetRun" },
+  { 12, "System" },
+  { 14, "UniCPU" },
+  {  7, "Little-Endian" },
+  { 15, "Big-Endian" }
+};
+
+static const CUInt32PCharPair g_DllCharacts[] =
+{
+  {  6, "Relocated" },
+  {  7, "Integrity" },
+  {  8, "NX-Compatible" },
+  {  9, "NoIsolation" },
+  { 10, "NoSEH" },
+  { 11, "NoBind" },
+  { 13, "WDM" },
+  { 15, "TerminalServerAware" }
+};
+
+static const CUInt32PCharPair g_SectFlags[] =
+{
+  {  3, "NoPad" },
+  {  5, "Code" },
+  {  6, "InitializedData" },
+  {  7, "UninitializedData" },
+  {  9, "Comments" },
+  { 11, "Remove" },
+  { 12, "COMDAT" },
+  { 15, "GP" },
+  { 24, "ExtendedRelocations" },
+  { 25, "Discardable" },
+  { 26, "NotCached" },
+  { 27, "NotPaged" },
+  { 28, "Shared" },
+  { 29, "Execute" },
+  { 30, "Read" },
+  { 31, "Write" }
+};
+
+static const CUInt32PCharPair g_MachinePairs[] =
+{
+  { 0x014C, "x86" },
+  { 0x0162, "MIPS-R3000" },
+  { 0x0166, "MIPS-R4000" },
+  { 0x0168, "MIPS-R10000" },
+  { 0x0169, "MIPS-V2" },
+  { 0x0184, "Alpha" },
+  { 0x01A2, "SH3" },
+  { 0x01A3, "SH3-DSP" },
+  { 0x01A4, "SH3E" },
+  { 0x01A6, "SH4" },
+  { 0x01A8, "SH5" },
+  { 0x01C0, "ARM" },
+  { 0x01C2, "ARM-Thumb" },
+  { 0x01F0, "PPC" },
+  { 0x01F1, "PPC-FP" },
+  { 0x0200, "IA-64" },
+  { 0x0284, "Alpha-64" },
+  { 0x0200, "IA-64" },
+  { 0x0366, "MIPSFPU" },
+  { 0x8664, "x64" },
+  { 0x0EBC, "EFI" }
+};
+
+static const CUInt32PCharPair g_SubSystems[] =
+{
+  { 0, "Unknown" },
+  { 1, "Native" },
+  { 2, "Windows GUI" },
+  { 3, "Windows CUI" },
+  { 7, "Posix" },
+  { 9, "Windows CE" },
+  { 10, "EFI" },
+  { 11, "EFI Boot" },
+  { 12, "EFI Runtime" },
+  { 13, "EFI ROM" },
+  { 14, "XBOX" }
+};
+
+static const wchar_t *g_ResTypes[] =
+{
+  NULL,
+  L"CURSOR",
+  L"BITMAP",
+  L"ICON",
+  L"MENU",
+  L"DIALOG",
+  L"STRING",
+  L"FONTDIR",
+  L"FONT",
+  L"ACCELERATOR",
+  L"RCDATA",
+  L"MESSAGETABLE",
+  L"GROUP_CURSOR",
+  NULL,
+  L"GROUP_ICON",
+  NULL,
+  L"VERSION",
+  L"DLGINCLUDE",
+  NULL,
+  L"PLUGPLAY",
+  L"VXD",
+  L"ANICURSOR",
+  L"ANIICON",
+  L"HTML",
+  L"MANIFEST"
+};
+
+const UInt32 kFlag = (UInt32)1 << 31;
+const UInt32 kMask = ~kFlag;
+
+struct CTableItem
+{
+  UInt32 Offset;
+  UInt32 ID;
+};
+
+
+const UInt32 kBmpHeaderSize = 14;
+const UInt32 kIconHeaderSize = 22;
+
+struct CResItem
+{
+  UInt32 Type;
+  UInt32 ID;
+  UInt32 Lang;
+
+  UInt32 Size;
+  UInt32 Offset;
+
+  UInt32 HeaderSize;
+  Byte Header[kIconHeaderSize]; // it must be enough for max size header.
+  bool Enabled;
+
+  bool IsNameEqual(const CResItem &item) const { return Lang == item.Lang; }
+  UInt32 GetSize() const { return Size + HeaderSize; }
+  bool IsBmp() const { return Type == 2; }
+  bool IsIcon() const { return Type == 3; }
+  bool IsString() const { return Type == 6; }
+  bool IsRcData() const { return Type == 10; }
+  bool IsRcDataOrUnknown() const { return IsRcData() || Type > 64; }
+};
+
+struct CStringItem
+{
+  UInt32 Lang;
+  UInt32 Size;
+  CByteDynamicBuffer Buf;
+
+  void AddChar(Byte c);
+  void AddWChar(UInt16 c);
+};
+
+void CStringItem::AddChar(Byte c)
+{
+  Buf.EnsureCapacity(Size + 2);
+  Buf[Size++] = c;
+  Buf[Size++] = 0;
+}
+
+void CStringItem::AddWChar(UInt16 c)
+{
+  if (c == '\n')
+  {
+    AddChar('\\');
+    c = 'n';
+  }
+  Buf.EnsureCapacity(Size + 2);
+  SetUi16(Buf + Size, c);
+  Size += 2;
+}
+
+struct CMixItem
+{
+  int SectionIndex;
+  int ResourceIndex;
+  int StringIndex;
+
+  bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0; };
+};
+
+struct CUsedBitmap
+{
+  CByteBuffer Buf;
+public:
+  void Alloc(size_t size)
+  {
+    size = (size + 7) / 8;
+    Buf.SetCapacity(size);
+    memset(Buf, 0, size);
+  }
+  void Free()
+  {
+    Buf.SetCapacity(0);
+  }
+  bool SetRange(size_t from, int size)
+  {
+    for (int i = 0; i < size; i++)
+    {
+      size_t pos = (from + i) >> 3;
+      Byte mask = (Byte)(1 << ((from + i) & 7));
+      Byte b = Buf[pos];
+      if ((b & mask) != 0)
+        return false;
+      Buf[pos] = b | mask;
+    }
+    return true;
+  }
+};
+ 
+
+class CHandler:
+  public IInArchive,
+  public IInArchiveGetStream,
+  public CMyUnknownImp
+{
+  CMyComPtr<IInStream> _stream;
+  CObjectVector<CSection> _sections;
+  UInt32 _peOffset;
+  CHeader _header;
+  COptHeader _optHeader;
+  UInt32 _totalSize;
+  UInt32 _totalSizeLimited;
+  Int32 _mainSubfile;
+
+  CRecordVector<CResItem> _items;
+  CObjectVector<CStringItem> _strings;
+
+  CByteBuffer _buf;
+  bool _oneLang;
+  UString _resourceFileName;
+  CUsedBitmap _usedRes;
+  bool _parseResources;
+
+  CRecordVector<CMixItem> _mixItems;
+
+  HRESULT LoadDebugSections(IInStream *stream, bool &thereIsSection);
+  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
+  bool Parse(const Byte *buf, UInt32 size);
+
+  void AddResNameToString(UString &s, UInt32 id) const;
+  UString GetLangPrefix(UInt32 lang);
+  HRESULT ReadString(UInt32 offset, UString &dest) const;
+  HRESULT ReadTable(UInt32 offset, CRecordVector<CTableItem> &items);
+  bool ParseStringRes(UInt32 id, UInt32 lang, const Byte *src, UInt32 size);
+  HRESULT OpenResources(int sectIndex, IInStream *stream, IArchiveOpenCallback *callback);
+  void CloseResources();
+
+
+  bool CheckItem(const CSection &sect, const CResItem &item, size_t offset) const
+  {
+    return item.Offset >= sect.Va && offset <= _buf.GetCapacity() && _buf.GetCapacity() - offset >= item.Size;
+  }
+
+public:
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+  INTERFACE_IInArchive(;)
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+};
+
+bool CHandler::Parse(const Byte *buf, UInt32 size)
+{
+  UInt32 i;
+  if (size < 512)
+    return false;
+  _peOffset = Get32(buf + 0x3C);
+  if (_peOffset >= 0x1000 || _peOffset + 512 > size || (_peOffset & 7) != 0)
+    return false;
+
+  UInt32 pos = _peOffset;
+  if (!_header.Parse(buf + pos))
+    return false;
+  if (_header.OptHeaderSize > 512 || _header.NumSections > NUM_SCAN_SECTIONS_MAX)
+    return false;
+  pos += kHeaderSize;
+
+  if (!_optHeader.Parse(buf + pos, _header.OptHeaderSize))
+    return false;
+
+  pos += _header.OptHeaderSize;
+  _totalSize = pos;
+
+  for (i = 0; i < _header.NumSections; i++, pos += kSectionSize)
+  {
+    CSection sect;
+    if (pos + kSectionSize > size)
+      return false;
+    sect.Parse(buf + pos);
+    sect.IsRealSect = true;
+    sect.UpdateTotalSize(_totalSize);
+    _sections.Add(sect);
+  }
+
+  return true;
+}
+
+enum
+{
+  kpidSectAlign = kpidUserDefined,
+  kpidFileAlign,
+  kpidLinkerVer,
+  kpidOsVer,
+  kpidImageVer,
+  kpidSubsysVer,
+  kpidCodeSize,
+  kpidImageSize,
+  kpidInitDataSize,
+  kpidUnInitDataSize,
+  kpidHeadersSizeUnInitDataSize,
+  kpidSubSystem,
+  kpidDllCharacts,
+  kpidStackReserve,
+  kpidStackCommit,
+  kpidHeapReserve,
+  kpidHeapCommit,
+  kpidImageBase
+  // kpidAddressOfEntryPoint,
+  // kpidBaseOfCode,
+  // kpidBaseOfData32,
+};
+
+STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidCpu, VT_BSTR},
+  { NULL, kpidBit64, VT_BOOL},
+  { NULL, kpidCharacts, VT_BSTR},
+  { NULL, kpidCTime, VT_FILETIME},
+  { NULL, kpidPhySize, VT_UI4},
+  { NULL, kpidHeadersSize, VT_UI4},
+  { NULL, kpidChecksum, VT_UI4},
+  { L"Image Size", kpidImageSize, VT_UI4},
+  { L"Section Alignment", kpidSectAlign, VT_UI4},
+  { L"File Alignment", kpidFileAlign, VT_UI4},
+  { L"Code Size", kpidCodeSize, VT_UI4},
+  { L"Initialized Data Size", kpidInitDataSize, VT_UI4},
+  { L"Uninitialized Data Size", kpidUnInitDataSize, VT_UI4},
+  { L"Linker Version", kpidLinkerVer, VT_BSTR},
+  { L"OS Version", kpidOsVer, VT_BSTR},
+  { L"Image Version", kpidImageVer, VT_BSTR},
+  { L"Subsystem Version", kpidSubsysVer, VT_BSTR},
+  { L"Subsystem", kpidSubSystem, VT_BSTR},
+  { L"DLL Characteristics", kpidDllCharacts, VT_BSTR},
+  { L"Stack Reserve", kpidStackReserve, VT_UI8},
+  { L"Stack Commit", kpidStackCommit, VT_UI8},
+  { L"Heap Reserve", kpidHeapReserve, VT_UI8},
+  { L"Heap Commit", kpidHeapCommit, VT_UI8},
+  { L"Image Base", kpidImageBase, VT_UI8}
+  // { L"Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8},
+  // { L"Base Of Code", kpidBaseOfCode, VT_UI8},
+  // { L"Base Of Data", kpidBaseOfData32, VT_UI8},
+};
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidCharacts, VT_BSTR},
+  { NULL, kpidOffset, VT_UI8},
+  { NULL, kpidVa, VT_UI8}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_WITH_NAME
+
+static void VerToProp(const CVersion &v, NCOM::CPropVariant &prop)
+{
+  StringToProp(v.GetString(), prop);
+}
+
+void TimeToProp(UInt32 unixTime, NCOM::CPropVariant &prop)
+{
+  if (unixTime != 0)
+  {
+    FILETIME ft;
+    NTime::UnixTimeToFileTime(unixTime, ft);
+    prop = ft;
+  }
+}
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidSectAlign: prop = _optHeader.SectAlign; break;
+    case kpidFileAlign: prop = _optHeader.FileAlign; break;
+    case kpidLinkerVer:
+    {
+      CVersion v = { _optHeader.LinkerVerMajor, _optHeader.LinkerVerMinor };
+      VerToProp(v, prop);
+      break;
+    }
+  
+    case kpidOsVer: VerToProp(_optHeader.OsVer, prop); break;
+    case kpidImageVer: VerToProp(_optHeader.ImageVer, prop); break;
+    case kpidSubsysVer: VerToProp(_optHeader.SubsysVer, prop); break;
+    case kpidCodeSize: prop = _optHeader.CodeSize; break;
+    case kpidInitDataSize: prop = _optHeader.InitDataSize; break;
+    case kpidUnInitDataSize: prop = _optHeader.UninitDataSize; break;
+    case kpidImageSize: prop = _optHeader.ImageSize; break;
+    case kpidPhySize: prop = _totalSize; break;
+    case kpidHeadersSize: prop = _optHeader.HeadersSize; break;
+    case kpidChecksum: prop = _optHeader.CheckSum; break;
+      
+    case kpidCpu: PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); break;
+    case kpidBit64: if (_optHeader.Is64Bit()) prop = true; break;
+    case kpidSubSystem: PAIR_TO_PROP(g_SubSystems, _optHeader.SubSystem, prop); break;
+
+    case kpidMTime:
+    case kpidCTime: TimeToProp(_header.Time, prop); break;
+    case kpidCharacts: FLAGS_TO_PROP(g_HeaderCharacts, _header.Flags, prop); break;
+    case kpidDllCharacts: FLAGS_TO_PROP(g_DllCharacts, _optHeader.DllCharacts, prop); break;
+    case kpidStackReserve: prop = _optHeader.StackReserve; break;
+    case kpidStackCommit: prop = _optHeader.StackCommit; break;
+    case kpidHeapReserve: prop = _optHeader.HeapReserve; break;
+    case kpidHeapCommit: prop = _optHeader.HeapCommit; break;
+
+    case kpidImageBase: prop = _optHeader.ImageBase; break;
+    // case kpidAddressOfEntryPoint: prop = _optHeader.AddressOfEntryPoint; break;
+    // case kpidBaseOfCode: prop = _optHeader.BaseOfCode; break;
+    // case kpidBaseOfData32: if (!_optHeader.Is64Bit()) prop = _optHeader.BaseOfData32; break;
+
+    case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+void CHandler::AddResNameToString(UString &s, UInt32 id) const
+{
+  if ((id & kFlag) != 0)
+  {
+    UString name;
+    if (ReadString(id & kMask, name) == S_OK)
+    {
+      if (name.IsEmpty())
+        s += L"[]";
+      else
+      {
+        if (name.Length() > 1 && name[0] == '"' && name.Back() == '"')
+          name = name.Mid(1, name.Length() - 2);
+        s += name;
+      }
+      return;
+    }
+  }
+  wchar_t sz[32];
+  ConvertUInt32ToString(id, sz);
+  s += sz;
+}
+
+UString CHandler::GetLangPrefix(UInt32 lang)
+{
+  UString s = _resourceFileName;
+  s += WCHAR_PATH_SEPARATOR;
+  if (!_oneLang)
+  {
+    AddResNameToString(s, lang);
+    s += WCHAR_PATH_SEPARATOR;
+  }
+  return s;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NCOM::CPropVariant prop;
+  const CMixItem &mixItem = _mixItems[index];
+  if (mixItem.StringIndex >= 0)
+  {
+    const CStringItem &item = _strings[mixItem.StringIndex];
+    switch(propID)
+    {
+      case kpidPath: prop = GetLangPrefix(item.Lang) + L"string.txt"; break;
+      case kpidSize:
+      case kpidPackSize:
+        prop = (UInt64)item.Size; break;
+    }
+  }
+  else if (mixItem.ResourceIndex < 0)
+  {
+    const CSection &item = _sections[mixItem.SectionIndex];
+    switch(propID)
+    {
+      case kpidPath: StringToProp(item.Name, prop); break;
+      case kpidSize: prop = (UInt64)item.VSize; break;
+      case kpidPackSize: prop = (UInt64)item.GetPackSize(); break;
+      case kpidOffset: prop = item.Pa; break;
+      case kpidVa: if (item.IsRealSect) prop = item.Va; break;
+      case kpidMTime:
+      case kpidCTime:
+        TimeToProp(item.IsDebug ? item.Time : _header.Time, prop); break;
+      case kpidCharacts: if (item.IsRealSect) FLAGS_TO_PROP(g_SectFlags, item.Flags, prop); break;
+    }
+  }
+  else
+  {
+    const CResItem &item = _items[mixItem.ResourceIndex];
+    switch(propID)
+    {
+      case kpidPath:
+      {
+        UString s = GetLangPrefix(item.Lang);
+        {
+          const wchar_t *p = NULL;
+          if (item.Type < sizeof(g_ResTypes) / sizeof(g_ResTypes[0]))
+            p = g_ResTypes[item.Type];
+          if (p != 0)
+            s += p;
+          else
+            AddResNameToString(s, item.Type);
+        }
+        s += WCHAR_PATH_SEPARATOR;
+        AddResNameToString(s, item.ID);
+        if (item.HeaderSize != 0)
+        {
+          if (item.IsBmp())
+            s += L".bmp";
+          else if (item.IsIcon())
+            s += L".ico";
+        }
+        prop = s;
+        break;
+      }
+      case kpidSize: prop = (UInt64)item.GetSize(); break;
+      case kpidPackSize: prop = (UInt64)item.Size; break;
+    }
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection)
+{
+  thereIsSection = false;
+  const CDirLink &debugLink = _optHeader.DirItems[kDirLink_Debug];
+  if (debugLink.Size == 0)
+    return S_OK;
+  const unsigned kEntrySize = 28;
+  UInt32 numItems = debugLink.Size / kEntrySize;
+  if (numItems * kEntrySize != debugLink.Size || numItems > 16)
+    return S_FALSE;
+  
+  UInt64 pa = 0;
+  int i;
+  for (i = 0; i < _sections.Size(); i++)
+  {
+    const CSection &sect = _sections[i];
+    if (sect.Va < debugLink.Va && debugLink.Va + debugLink.Size <= sect.Va + sect.PSize)
+    {
+      pa = sect.Pa + (debugLink.Va - sect.Va);
+      break;
+    }
+  }
+  if (i == _sections.Size())
+  {
+    return S_OK;
+    // Exe for ARM requires S_OK
+    // return S_FALSE;
+  }
+  
+  CByteBuffer buffer;
+  buffer.SetCapacity(debugLink.Size);
+  Byte *buf = buffer;
+  
+  RINOK(stream->Seek(pa, STREAM_SEEK_SET, NULL));
+  RINOK(ReadStream_FALSE(stream, buf, debugLink.Size));
+
+  for (i = 0; i < (int)numItems; i++)
+  {
+    CDebugEntry de;
+    de.Parse(buf);
+
+    if (de.Size == 0)
+      continue;
+    
+    CSection sect;
+    sect.Name = ".debug" + GetDecString(i);
+    
+    sect.IsDebug = true;
+    sect.Time = de.Time;
+    sect.Va = de.Va;
+    sect.Pa = de.Pa;
+    sect.PSize = sect.VSize = de.Size;
+    UInt32 totalSize = sect.Pa + sect.PSize;
+    if (totalSize > _totalSize)
+    {
+      _totalSize = totalSize;
+      _sections.Add(sect);
+      thereIsSection = true;
+    }
+    buf += kEntrySize;
+  }
+
+  return S_OK;
+}
+
+HRESULT CHandler::ReadString(UInt32 offset, UString &dest) const
+{
+  if ((offset & 1) != 0 || offset >= _buf.GetCapacity())
+    return S_FALSE;
+  size_t rem = _buf.GetCapacity() - offset;
+  if (rem < 2)
+    return S_FALSE;
+  unsigned length = Get16(_buf + offset);
+  if ((rem - 2) / 2 < length)
+    return S_FALSE;
+  dest.Empty();
+  offset += 2;
+  for (unsigned i = 0; i < length; i++)
+    dest += (wchar_t)Get16(_buf + offset + i * 2);
+  return S_OK;
+}
+
+HRESULT CHandler::ReadTable(UInt32 offset, CRecordVector<CTableItem> &items)
+{
+  if ((offset & 3) != 0 || offset >= _buf.GetCapacity())
+    return S_FALSE;
+  size_t rem = _buf.GetCapacity() - offset;
+  if (rem < 16)
+    return S_FALSE;
+  items.Clear();
+  unsigned numNameItems = Get16(_buf + offset + 12);
+  unsigned numIdItems = Get16(_buf + offset + 14);
+  unsigned numItems = numNameItems + numIdItems;
+  if ((rem - 16) / 8 < numItems)
+    return S_FALSE;
+  if (!_usedRes.SetRange(offset, 16 + numItems * 8))
+    return S_FALSE;
+  offset += 16;
+  _oneLang = true;
+  unsigned i;
+  for (i = 0; i < numItems; i++)
+  {
+    CTableItem item;
+    const Byte *buf = _buf + offset;
+    offset += 8;
+    item.ID = Get32(buf + 0);
+    if (((item.ID & kFlag) != 0) != (i < numNameItems))
+      return S_FALSE;
+    item.Offset = Get32(buf + 4);
+    items.Add(item);
+  }
+  return S_OK;
+}
+
+static const UInt32 kFileSizeMax = (UInt32)1 << 30;
+static const int kNumResItemsMax = (UInt32)1 << 23;
+static const int kNumStringLangsMax = 128;
+
+// BITMAPINFOHEADER
+struct CBitmapInfoHeader
+{
+  // UInt32 HeaderSize;
+  UInt32 XSize;
+  Int32 YSize;
+  UInt16 Planes;
+  UInt16 BitCount;
+  UInt32 Compression;
+  UInt32 SizeImage;
+
+  bool Parse(const Byte *p, size_t size);
+};
+
+static const UInt32 kBitmapInfoHeader_Size = 0x28;
+
+bool CBitmapInfoHeader::Parse(const Byte *p, size_t size)
+{
+  if (size < kBitmapInfoHeader_Size || Get32(p) != kBitmapInfoHeader_Size)
+    return false;
+  XSize = Get32(p + 4);
+  YSize = (Int32)Get32(p + 8);
+  Planes = Get16(p + 12);
+  BitCount = Get16(p + 14);
+  Compression = Get32(p + 16);
+  SizeImage = Get32(p + 20);
+  return true;
+}
+
+static UInt32 GetImageSize(UInt32 xSize, UInt32 ySize, UInt32 bitCount)
+{
+  return ((xSize * bitCount + 7) / 8 + 3) / 4 * 4 * ySize;
+}
+  
+static UInt32 SetBitmapHeader(Byte *dest, const Byte *src, UInt32 size)
+{
+  CBitmapInfoHeader h;
+  if (!h.Parse(src, size))
+    return 0;
+  if (h.YSize < 0)
+    h.YSize = -h.YSize;
+  if (h.XSize > (1 << 26) || h.YSize > (1 << 26) || h.Planes != 1 || h.BitCount > 32 ||
+      h.Compression != 0) // BI_RGB
+    return 0;
+  if (h.SizeImage == 0)
+    h.SizeImage = GetImageSize(h.XSize, h.YSize, h.BitCount);
+  UInt32 totalSize = kBmpHeaderSize + size;
+  UInt32 offBits = totalSize - h.SizeImage;
+  // BITMAPFILEHEADER
+  SetUi16(dest, 0x4D42);
+  SetUi32(dest + 2, totalSize);
+  SetUi32(dest + 6, 0);
+  SetUi32(dest + 10, offBits);
+  return kBmpHeaderSize;
+}
+
+static UInt32 SetIconHeader(Byte *dest, const Byte *src, UInt32 size)
+{
+  CBitmapInfoHeader h;
+  if (!h.Parse(src, size))
+    return 0;
+  if (h.YSize < 0)
+    h.YSize = -h.YSize;
+  if (h.XSize > (1 << 26) || h.YSize > (1 << 26) || h.Planes != 1 ||
+      h.Compression != 0) // BI_RGB
+    return 0;
+
+  UInt32 numBitCount = h.BitCount;
+  if (numBitCount != 1 &&
+      numBitCount != 4 &&
+      numBitCount != 8 &&
+      numBitCount != 24 &&
+      numBitCount != 32)
+    return 0;
+
+  if ((h.YSize & 1) != 0)
+    return 0;
+  h.YSize /= 2;
+  if (h.XSize > 0x100 || h.YSize > 0x100)
+    return 0;
+
+  UInt32 imageSize;
+  // imageSize is not correct if AND mask array contains zeros
+  // in this case it is equal image1Size
+
+  // UInt32 imageSize = h.SizeImage;
+  // if (imageSize == 0)
+  // {
+    UInt32 image1Size = GetImageSize(h.XSize, h.YSize, h.BitCount);
+    UInt32 image2Size = GetImageSize(h.XSize, h.YSize, 1);
+    imageSize = image1Size + image2Size;
+  // }
+  UInt32 numColors = 0;
+  if (numBitCount < 16)
+    numColors = 1 << numBitCount;
+
+  SetUi16(dest, 0); // Reserved
+  SetUi16(dest + 2, 1); // RES_ICON
+  SetUi16(dest + 4, 1); // ResCount
+
+  dest[6] = (Byte)h.XSize; // Width
+  dest[7] = (Byte)h.YSize; // Height
+  dest[8] = (Byte)numColors; // ColorCount
+  dest[9] = 0; // Reserved
+  
+  SetUi32(dest + 10, 0); // Reserved1 / Reserved2
+
+  UInt32 numQuadsBytes = numColors * 4;
+  UInt32 BytesInRes = kBitmapInfoHeader_Size + numQuadsBytes + imageSize;
+  SetUi32(dest + 14, BytesInRes);
+  SetUi32(dest + 18, kIconHeaderSize);
+
+  /*
+  Description = DWORDToString(xSize) +
+      kDelimiterChar + DWORDToString(ySize) +
+      kDelimiterChar + DWORDToString(numBitCount);
+  */
+  return kIconHeaderSize;
+}
+
+bool CHandler::ParseStringRes(UInt32 id, UInt32 lang, const Byte *src, UInt32 size)
+{
+  if ((size & 1) != 0)
+    return false;
+
+  int i;
+  for (i = 0; i < _strings.Size(); i++)
+    if (_strings[i].Lang == lang)
+      break;
+  if (i == _strings.Size())
+  {
+    if (_strings.Size() >= kNumStringLangsMax)
+      return false;
+    CStringItem item;
+    item.Size = 0;
+    item.Lang = lang;
+    i = _strings.Add(item);
+  }
+  
+  CStringItem &item = _strings[i];
+  id = (id - 1) << 4;
+  UInt32 pos = 0;
+  for (i = 0; i < 16; i++)
+  {
+    if (size - pos < 2)
+      return false;
+    UInt32 len = Get16(src + pos);
+    pos += 2;
+    if (len != 0)
+    {
+      if (size - pos < len * 2)
+        return false;
+      char temp[32];
+      ConvertUInt32ToString(id  + i, temp);
+      size_t tempLen = strlen(temp);
+      size_t j;
+      for (j = 0; j < tempLen; j++)
+        item.AddChar(temp[j]);
+      item.AddChar('\t');
+      for (j = 0; j < len; j++, pos += 2)
+        item.AddWChar(Get16(src + pos));
+      item.AddChar(0x0D);
+      item.AddChar(0x0A);
+    }
+  }
+  return (size == pos);
+}
+
+HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpenCallback *callback)
+{
+  const CSection &sect = _sections[sectionIndex];
+  size_t fileSize = sect.PSize; // Maybe we need sect.VSize here !!!
+  if (fileSize > kFileSizeMax)
+    return S_FALSE;
+  {
+    UInt64 fileSize64 = fileSize;
+    if (callback)
+      RINOK(callback->SetTotal(NULL, &fileSize64));
+    RINOK(stream->Seek(sect.Pa, STREAM_SEEK_SET, NULL));
+    _buf.SetCapacity(fileSize);
+    for (size_t pos = 0; pos < fileSize;)
+    {
+      UInt64 offset64 = pos;
+      if (callback)
+        RINOK(callback->SetCompleted(NULL, &offset64))
+      size_t rem = MyMin(fileSize - pos, (size_t)(1 << 20));
+      RINOK(ReadStream_FALSE(stream, _buf + pos, rem));
+      pos += rem;
+    }
+  }
+  
+  _usedRes.Alloc(fileSize);
+  CRecordVector<CTableItem> specItems;
+  RINOK(ReadTable(0, specItems));
+
+  _oneLang = true;
+  bool stringsOk = true;
+  size_t maxOffset = 0;
+  for (int i = 0; i < specItems.Size(); i++)
+  {
+    const CTableItem &item1 = specItems[i];
+    if ((item1.Offset & kFlag) == 0)
+      return S_FALSE;
+
+    CRecordVector<CTableItem> specItems2;
+    RINOK(ReadTable(item1.Offset & kMask, specItems2));
+
+    for (int j = 0; j < specItems2.Size(); j++)
+    {
+      const CTableItem &item2 = specItems2[j];
+      if ((item2.Offset & kFlag) == 0)
+        return S_FALSE;
+      
+      CRecordVector<CTableItem> specItems3;
+      RINOK(ReadTable(item2.Offset & kMask, specItems3));
+      
+      CResItem item;
+      item.Type = item1.ID;
+      item.ID = item2.ID;
+      
+      for (int k = 0; k < specItems3.Size(); k++)
+      {
+        if (_items.Size() >= kNumResItemsMax)
+          return S_FALSE;
+        const CTableItem &item3 = specItems3[k];
+        if ((item3.Offset & kFlag) != 0)
+          return S_FALSE;
+        if (item3.Offset >= _buf.GetCapacity() || _buf.GetCapacity() - item3.Offset < 16)
+          return S_FALSE;
+        const Byte *buf = _buf + item3.Offset;
+        item.Lang = item3.ID;
+        item.Offset = Get32(buf + 0);
+        item.Size = Get32(buf + 4);
+        // UInt32 codePage = Get32(buf + 8);
+        if (Get32(buf + 12) != 0)
+          return S_FALSE;
+        if (!_items.IsEmpty() && _oneLang && !item.IsNameEqual(_items.Back()))
+          _oneLang = false;
+
+        item.HeaderSize = 0;
+      
+        size_t offset = item.Offset - sect.Va;
+        if (offset > maxOffset)
+          maxOffset = offset;
+        if (offset + item.Size > maxOffset)
+          maxOffset = offset + item.Size;
+
+        if (CheckItem(sect, item, offset))
+        {
+          const Byte *data = _buf + offset;
+          if (item.IsBmp())
+            item.HeaderSize = SetBitmapHeader(item.Header, data, item.Size);
+          else if (item.IsIcon())
+            item.HeaderSize = SetIconHeader(item.Header, data, item.Size);
+          else if (item.IsString())
+          {
+            if (stringsOk)
+              stringsOk = ParseStringRes(item.ID, item.Lang, data, item.Size);
+          }
+        }
+
+        item.Enabled = true;
+        _items.Add(item);
+      }
+    }
+  }
+  
+  if (stringsOk && !_strings.IsEmpty())
+  {
+    int i;
+    for (i = 0; i < _items.Size(); i++)
+    {
+      CResItem &item = _items[i];
+      if (item.IsString())
+        item.Enabled = false;
+    }
+    for (i = 0; i < _strings.Size(); i++)
+    {
+      if (_strings[i].Size == 0)
+        continue;
+      CMixItem mixItem;
+      mixItem.ResourceIndex = -1;
+      mixItem.StringIndex = i;
+      mixItem.SectionIndex = sectionIndex;
+      _mixItems.Add(mixItem);
+    }
+  }
+
+  _usedRes.Free();
+
+  int numBits = _optHeader.GetNumFileAlignBits();
+  if (numBits >= 0)
+  {
+    UInt32 mask = (1 << numBits) - 1;
+    size_t end = ((maxOffset + mask) & ~mask);
+    if (end < sect.VSize && end <= sect.PSize)
+    {
+      CSection sect2;
+      sect2.Flags = 0;
+
+      // we skip Zeros to start of aligned block
+      size_t i;
+      for (i = maxOffset; i < end; i++)
+        if (_buf[i] != 0)
+          break;
+      if (i == end)
+        maxOffset = end;
+      
+      sect2.Pa = sect.Pa + (UInt32)maxOffset;
+      sect2.Va = sect.Va + (UInt32)maxOffset;
+      sect2.PSize = sect.VSize - (UInt32)maxOffset;
+      sect2.VSize = sect2.PSize;
+      sect2.Name = ".rsrc_1";
+      sect2.Time = 0;
+      sect2.IsAdditionalSection = true;
+      _sections.Add(sect2);
+    }
+  }
+
+  return S_OK;
+}
+
+HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
+{
+  const UInt32 kBufSize = 1 << 18;
+  const UInt32 kSigSize = 2;
+
+  _mainSubfile = -1;
+
+  CByteBuffer buffer;
+  buffer.SetCapacity(kBufSize);
+  Byte *buf = buffer;
+
+  size_t processed = kSigSize;
+  RINOK(ReadStream_FALSE(stream, buf, processed));
+  if (buf[0] != 'M' || buf[1] != 'Z')
+    return S_FALSE;
+  processed = kBufSize - kSigSize;
+  RINOK(ReadStream(stream, buf + kSigSize, &processed));
+  processed += kSigSize;
+  if (!Parse(buf, (UInt32)processed))
+    return S_FALSE;
+  bool thereISDebug;
+  RINOK(LoadDebugSections(stream, thereISDebug));
+
+  const CDirLink &certLink = _optHeader.DirItems[kDirLink_Certificate];
+  if (certLink.Size != 0)
+  {
+    CSection sect;
+    sect.Name = "CERTIFICATE";
+    sect.Va = 0;
+    sect.Pa = certLink.Va;
+    sect.PSize = sect.VSize = certLink.Size;
+    sect.UpdateTotalSize(_totalSize);
+    _sections.Add(sect);
+  }
+
+  if (thereISDebug)
+  {
+    const UInt32 kAlign = 1 << 12;
+    UInt32 alignPos = _totalSize & (kAlign - 1);
+    if (alignPos != 0)
+    {
+      UInt32 size = kAlign - alignPos;
+      RINOK(stream->Seek(_totalSize, STREAM_SEEK_SET, NULL));
+      buffer.Free();
+      buffer.SetCapacity(kAlign);
+      Byte *buf = buffer;
+      size_t processed = size;
+      RINOK(ReadStream(stream, buf, &processed));
+      size_t i;
+      for (i = 0; i < processed; i++)
+      {
+        if (buf[i] != 0)
+          break;
+      }
+      if (processed < size && processed < 100)
+        _totalSize += (UInt32)processed;
+      else if (((_totalSize + i) & 0x1FF) == 0 || processed < size)
+        _totalSize += (UInt32)i;
+    }
+  }
+
+  if (_header.NumSymbols > 0 && _header.PointerToSymbolTable >= 512)
+  {
+    if (_header.NumSymbols >= (1 << 24))
+      return S_FALSE;
+    CSection sect;
+    sect.Name = "COFF_SYMBOLS";
+    UInt32 size = _header.NumSymbols * 18;
+    RINOK(stream->Seek((UInt64)_header.PointerToSymbolTable + size, STREAM_SEEK_SET, NULL));
+    Byte buf[4];
+    RINOK(ReadStream_FALSE(stream, buf, 4));
+    UInt32 size2 = Get32(buf);
+    if (size2 >= (1 << 28))
+      return S_FALSE;
+    size += size2;
+
+    sect.Va = 0;
+    sect.Pa = _header.PointerToSymbolTable;
+    sect.PSize = sect.VSize = size;
+    sect.UpdateTotalSize(_totalSize);
+    _sections.Add(sect);
+  }
+
+  UInt64 fileSize;
+  RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));
+  if (fileSize > _totalSize)
+    return S_FALSE;
+  _totalSizeLimited = (_totalSize < fileSize) ? _totalSize : (UInt32)fileSize;
+
+  {
+    CObjectVector<CSection> sections = _sections;
+    sections.Sort();
+    UInt32 limit = (1 << 12);
+    int num = 0;
+    int numSections = sections.Size();
+    for (int i = 0; i < numSections; i++)
+    {
+      const CSection &s = sections[i];
+      if (s.Pa > limit)
+      {
+        CSection s2;
+        s2.Pa = s2.Va = limit;
+        s2.PSize = s2.VSize = s.Pa - limit;
+        s2.IsAdditionalSection = true;
+        s2.Name = '[';
+        s2.Name += GetDecString(num++);
+        s2.Name += ']';
+        _sections.Add(s2);
+        limit = s.Pa;
+      }
+      UInt32 next = s.Pa + s.PSize;
+      if (next < s.Pa)
+        break;
+      if (next >= limit)
+        limit = next;
+    }
+  }
+
+  _parseResources = true;
+
+  UInt64 mainSize = 0, mainSize2 = 0;
+  int i;
+  for (i = 0; i < _sections.Size(); i++)
+  {
+    const CSection &sect = _sections[i];
+    CMixItem mixItem;
+    mixItem.SectionIndex = i;
+    if (_parseResources && sect.Name == ".rsrc" && _items.IsEmpty())
+    {
+      HRESULT res = OpenResources(i, stream, callback);
+      if (res == S_OK)
+      {
+        _resourceFileName = GetUnicodeString(sect.Name);
+        for (int j = 0; j < _items.Size(); j++)
+        {
+          const CResItem &item = _items[j];
+          if (item.Enabled)
+          {
+            mixItem.ResourceIndex = j;
+            mixItem.StringIndex = -1;
+            if (item.IsRcDataOrUnknown())
+            {
+              if (item.Size >= mainSize)
+              {
+                mainSize2 = mainSize;
+                mainSize = item.Size;
+                _mainSubfile = _mixItems.Size();
+              }
+              else if (item.Size >= mainSize2)
+                mainSize2 = item.Size;
+            }
+            _mixItems.Add(mixItem);
+          }
+        }
+        if (sect.PSize > sect.VSize)
+        {
+          int numBits = _optHeader.GetNumFileAlignBits();
+          if (numBits >= 0)
+          {
+            UInt32 mask = (1 << numBits) - 1;
+            UInt32 end = ((sect.VSize + mask) & ~mask);
+
+            if (sect.PSize > end)
+            {
+              CSection sect2;
+              sect2.Flags = 0;
+              sect2.Pa = sect.Pa + end;
+              sect2.Va = sect.Va + end;
+              sect2.PSize = sect.PSize - end;
+              sect2.VSize = sect2.PSize;
+              sect2.Name = ".rsrc_2";
+              sect2.Time = 0;
+              sect2.IsAdditionalSection = true;
+              _sections.Add(sect2);
+            }
+          }
+        }
+        continue;
+      }
+      if (res != S_FALSE)
+        return res;
+      CloseResources();
+    }
+    mixItem.StringIndex = -1;
+    mixItem.ResourceIndex = -1;
+    if (sect.IsAdditionalSection)
+    {
+      if (sect.PSize >= mainSize)
+      {
+        mainSize2 = mainSize;
+        mainSize = sect.PSize;
+        _mainSubfile = _mixItems.Size();
+      }
+      else
+        mainSize2 = sect.PSize;
+    }
+    _mixItems.Add(mixItem);
+  }
+  
+  if (mainSize2 >= (1 << 20) && mainSize < mainSize2 * 2)
+    _mainSubfile = -1;
+
+  for (i = 0; i < _mixItems.Size(); i++)
+  {
+    const CMixItem &mixItem = _mixItems[i];
+    if (mixItem.StringIndex < 0 && mixItem.ResourceIndex < 0 && _sections[mixItem.SectionIndex].Name == "_winzip_")
+    {
+      _mainSubfile = i;
+      break;
+    }
+  }
+
+  return S_OK;
+}
+
+HRESULT CalcCheckSum(ISequentialInStream *stream, UInt32 size, UInt32 excludePos, UInt32 &res)
+{
+  // size &= ~1;
+  const UInt32 kBufSize = 1 << 23;
+  CByteBuffer buffer;
+  buffer.SetCapacity(kBufSize);
+  Byte *buf = buffer;
+
+  UInt32 sum = 0;
+  UInt32 pos = 0;
+  for (;;)
+  {
+    UInt32 rem = size - pos;
+    if (rem > kBufSize)
+      rem = kBufSize;
+    if (rem == 0)
+      break;
+    size_t processed = rem;
+    RINOK(ReadStream(stream, buf, &processed));
+    
+    /*
+    for (; processed < rem; processed++)
+      buf[processed] = 0;
+    */
+
+    if ((processed & 1) != 0)
+      buf[processed] = 0;
+
+    for (int j = 0; j < 4; j++)
+    {
+      UInt32 p = excludePos + j;
+      if (pos <= p && p < pos + processed)
+        buf[p - pos] = 0;
+    }
+
+    for (size_t i = 0; i < processed; i += 2)
+    {
+      sum += Get16(buf + i);
+      sum = (sum + (sum >> 16)) & 0xFFFF;
+    }
+    pos += (UInt32)processed;
+    if (rem != processed)
+      break;
+  }
+  sum += pos;
+  res = sum;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback)
+{
+  COM_TRY_BEGIN
+  Close();
+  RINOK(Open2(inStream, callback));
+  _stream = inStream;
+  return S_OK;
+  COM_TRY_END
+}
+
+void CHandler::CloseResources()
+{
+  _usedRes.Free();
+  _items.Clear();
+  _strings.Clear();
+  _buf.SetCapacity(0);
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _stream.Release();
+  _sections.Clear();
+  _mixItems.Clear();
+  CloseResources();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _mixItems.Size();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _mixItems.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt64 totalSize = 0;
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+  {
+    const CMixItem &mixItem = _mixItems[allFilesMode ? i : indices[i]];
+    if (mixItem.StringIndex >= 0)
+      totalSize += _strings[mixItem.StringIndex].Size;
+    else if (mixItem.ResourceIndex < 0)
+      totalSize += _sections[mixItem.SectionIndex].GetPackSize();
+    else
+      totalSize += _items[mixItem.ResourceIndex].GetSize();
+  }
+  extractCallback->SetTotal(totalSize);
+
+  UInt64 currentTotalSize = 0;
+  UInt64 currentItemSize;
+  
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  bool checkSumOK = true;
+  if (_optHeader.CheckSum != 0 && (int)numItems == _mixItems.Size())
+  {
+    UInt32 checkSum = 0;
+    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
+    CalcCheckSum(_stream, _totalSizeLimited, _peOffset + kHeaderSize + 64, checkSum);
+    checkSumOK = (checkSum == _optHeader.CheckSum);
+  }
+
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);
+  streamSpec->SetStream(_stream);
+
+  for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
+  {
+    lps->InSize = lps->OutSize = currentTotalSize;
+    RINOK(lps->SetCur());
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    UInt32 index = allFilesMode ? i : indices[i];
+
+    CMyComPtr<ISequentialOutStream> outStream;
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));
+    const CMixItem &mixItem = _mixItems[index];
+
+    const CSection &sect = _sections[mixItem.SectionIndex];
+    bool isOk = true;
+    if (mixItem.StringIndex >= 0)
+    {
+      const CStringItem &item = _strings[mixItem.StringIndex];
+      currentItemSize = item.Size;
+      if (!testMode && !outStream)
+        continue;
+
+      RINOK(extractCallback->PrepareOperation(askMode));
+      if (outStream)
+        RINOK(WriteStream(outStream, item.Buf, item.Size));
+    }
+    else if (mixItem.ResourceIndex < 0)
+    {
+      currentItemSize = sect.GetPackSize();
+      if (!testMode && !outStream)
+        continue;
+      
+      RINOK(extractCallback->PrepareOperation(askMode));
+      RINOK(_stream->Seek(sect.Pa, STREAM_SEEK_SET, NULL));
+      streamSpec->Init(currentItemSize);
+      RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
+      isOk = (copyCoderSpec->TotalSize == currentItemSize);
+    }
+    else
+    {
+      const CResItem &item = _items[mixItem.ResourceIndex];
+      currentItemSize = item.GetSize();
+      if (!testMode && !outStream)
+        continue;
+
+      RINOK(extractCallback->PrepareOperation(askMode));
+      size_t offset = item.Offset - sect.Va;
+      if (!CheckItem(sect, item, offset))
+        isOk = false;
+      else if (outStream)
+      {
+        if (item.HeaderSize != 0)
+          RINOK(WriteStream(outStream, item.Header, item.HeaderSize));
+        RINOK(WriteStream(outStream, _buf + offset, item.Size));
+      }
+    }
+    
+    outStream.Release();
+    RINOK(extractCallback->SetOperationResult(isOk ?
+      checkSumOK ?
+        NExtract::NOperationResult::kOK:
+        NExtract::NOperationResult::kCRCError:
+        NExtract::NOperationResult::kDataError));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+  COM_TRY_BEGIN
+  *stream = 0;
+
+  const CMixItem &mixItem = _mixItems[index];
+  const CSection &sect = _sections[mixItem.SectionIndex];
+  if (mixItem.IsSectionItem())
+    return CreateLimitedInStream(_stream, sect.Pa, sect.PSize, stream);
+
+  CBufInStream *inStreamSpec = new CBufInStream;
+  CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
+  CReferenceBuf *referenceBuf = new CReferenceBuf;
+  CMyComPtr<IUnknown> ref = referenceBuf;
+  if (mixItem.StringIndex >= 0)
+  {
+    const CStringItem &item = _strings[mixItem.StringIndex];
+    referenceBuf->Buf.SetCapacity(item.Size);
+    memcpy(referenceBuf->Buf, item.Buf, item.Size);
+  }
+  else
+  {
+    const CResItem &item = _items[mixItem.ResourceIndex];
+    size_t offset = item.Offset - sect.Va;
+    if (!CheckItem(sect, item, offset))
+      return S_FALSE;
+    if (item.HeaderSize == 0)
+    {
+      CBufInStream *streamSpec = new CBufInStream;
+      CMyComPtr<IInStream> streamTemp2 = streamSpec;
+      streamSpec->Init(_buf + offset, item.Size, (IInArchive *)this);
+      *stream = streamTemp2.Detach();
+      return S_OK;
+    }
+    referenceBuf->Buf.SetCapacity(item.HeaderSize + item.Size);
+    memcpy(referenceBuf->Buf, item.Header, item.HeaderSize);
+    memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size);
+  }
+  inStreamSpec->Init(referenceBuf);
+
+  *stream = streamTemp.Detach();
+  return S_OK;
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"PE", L"exe dll sys", 0, 0xDD, { 'P', 'E', 0, 0 }, 4, false, CreateArc, 0 };
+
+REGISTER_ARC(Pe)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/PpmdHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/PpmdHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/PpmdHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/PpmdHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,456 @@
+/* PpmdHandler.c -- PPMd format handler
+2010-03-10 : Igor Pavlov : Public domain
+This code is based on:
+  PPMd var.H (2001) / var.I (2002): Dmitry Shkarin : Public domain
+  Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+#include "../../../C/Alloc.h"
+#include "../../../C/Ppmd7.h"
+#include "../../../C/Ppmd8.h"
+
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../Common/CWrappers.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NPpmd {
+
+static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); }
+static void SzBigFree(void *, void *address) { BigFree(address); }
+static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
+
+static const UInt32 kBufSize = (1 << 20);
+
+struct CBuf
+{
+  Byte *Buf;
+  
+  CBuf(): Buf(0) {}
+  ~CBuf() { ::MidFree(Buf); }
+  bool Alloc()
+  {
+    if (!Buf)
+      Buf = (Byte *)::MidAlloc(kBufSize);
+    return (Buf != 0);
+  }
+};
+
+static const UInt32 kHeaderSize = 16;
+static const UInt32 kSignature = 0x84ACAF8F;
+static const unsigned kNewHeaderVer = 8;
+
+struct CItem
+{
+  UInt32 Attrib;
+  UInt32 Time;
+  AString Name;
+  
+  unsigned Order;
+  unsigned MemInMB;
+  unsigned Ver;
+  unsigned Restor;
+
+  HRESULT ReadHeader(ISequentialInStream *s, UInt32 &headerSize);
+  bool IsSupported() const { return Ver == 7 || (Ver == 8 && Restor <= 1); }
+};
+
+HRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize)
+{
+  Byte h[kHeaderSize];
+  RINOK(ReadStream_FALSE(s, h, kHeaderSize));
+  if (GetUi32(h) != kSignature)
+    return S_FALSE;
+  Attrib = GetUi32(h + 4);
+  Time = GetUi32(h + 12);
+  
+  unsigned info = GetUi16(h + 8);
+  Order = (info & 0xF) + 1;
+  MemInMB = ((info >> 4) & 0xFF) + 1;
+  Ver = info >> 12;
+ 
+  UInt32 nameLen = GetUi16(h + 10);
+  Restor = nameLen >> 14;
+  if (Restor > 2)
+    return S_FALSE;
+  if (Ver >= kNewHeaderVer)
+    nameLen &= 0x3FFF;
+  if (nameLen > (1 << 9))
+    return S_FALSE;
+  char *name = Name.GetBuffer(nameLen + 1);
+  HRESULT res = ReadStream_FALSE(s, name, nameLen);
+  name[nameLen] = 0;
+  headerSize = kHeaderSize + nameLen;
+  Name.ReleaseBuffer();
+  return res;
+}
+
+class CHandler:
+  public IInArchive,
+  public IArchiveOpenSeq,
+  public CMyUnknownImp
+{
+  CItem _item;
+  UInt32 _headerSize;
+  UInt64 _packSize;
+  bool _packSizeDefined;
+  CMyComPtr<ISequentialInStream> _stream;
+
+public:
+  MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq)
+  INTERFACE_IInArchive(;)
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);
+};
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidMTime, VT_FILETIME},
+  { NULL, kpidAttrib, VT_UI4},
+  { NULL, kpidMethod, VT_BSTR}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_NO_Table
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = 1;
+  return S_OK;
+}
+
+static void UIntToString(AString &s, const char *prefix, unsigned value)
+{
+  s += prefix;
+  char temp[16];
+  ::ConvertUInt32ToString((UInt32)value, temp);
+  s += temp;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID,  PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidPath: prop = MultiByteToUnicodeString(_item.Name, CP_ACP); break;
+    case kpidMTime:
+    {
+      FILETIME utc;
+      if (NTime::DosTimeToFileTime(_item.Time, utc))
+        prop = utc;
+      break;
+    }
+    case kpidAttrib: prop = _item.Attrib; break;
+    case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;
+    case kpidMethod:
+    {
+      AString s = "PPMd";
+      s += (char)('A' + _item.Ver);
+      UIntToString(s, ":o", _item.Order);
+      UIntToString(s, ":mem", _item.MemInMB);
+      s += 'm';
+      if (_item.Ver >= kNewHeaderVer && _item.Restor != 0)
+        UIntToString(s, ":r", _item.Restor);
+      prop = s;
+    }
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *)
+{
+  return OpenSeq(stream);
+}
+
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
+{
+  COM_TRY_BEGIN
+  HRESULT res;
+  try
+  {
+    Close();
+    res = _item.ReadHeader(stream, _headerSize);
+  }
+  catch(...) { res = S_FALSE; }
+  if (res == S_OK)
+    _stream = stream;
+  else
+    Close();
+  return res;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _packSizeDefined = false;
+  _stream.Release();
+  return S_OK;
+}
+
+static const UInt32 kTopValue = (1 << 24);
+static const UInt32 kBot = (1 << 15);
+
+struct CRangeDecoder
+{
+  IPpmd7_RangeDec s;
+  UInt32 Range;
+  UInt32 Code;
+  UInt32 Low;
+  CByteInBufWrap *Stream;
+
+public:
+  bool Init()
+  {
+    Code = 0;
+    Low = 0;
+    Range = 0xFFFFFFFF;
+    for (int i = 0; i < 4; i++)
+      Code = (Code << 8) | Stream->ReadByte();
+    return Code < 0xFFFFFFFF;
+  }
+
+  void Normalize()
+  {
+    while ((Low ^ (Low + Range)) < kTopValue ||
+       Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1))
+    {
+      Code = (Code << 8) | Stream->ReadByte();
+      Range <<= 8;
+      Low <<= 8;
+    }
+  }
+
+  CRangeDecoder();
+};
+
+
+extern "C" {
+
+static UInt32 Range_GetThreshold(void *pp, UInt32 total)
+{
+  CRangeDecoder *p = (CRangeDecoder *)pp;
+  return p->Code / (p->Range /= total);
+}
+
+static void Range_Decode(void *pp, UInt32 start, UInt32 size)
+{
+  CRangeDecoder *p = (CRangeDecoder *)pp;
+  start *= p->Range;
+  p->Low += start;
+  p->Code -= start;
+  p->Range *= size;
+  p->Normalize();
+}
+
+static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
+{
+  CRangeDecoder *p = (CRangeDecoder *)pp;
+  if (p->Code / (p->Range >>= 14) < size0)
+  {
+    Range_Decode(p, 0, size0);
+    return 0;
+  }
+  else
+  {
+    Range_Decode(p, size0, (1 << 14) - size0);
+    return 1;
+  }
+}
+
+}
+
+CRangeDecoder::CRangeDecoder()
+{
+  s.GetThreshold = Range_GetThreshold;
+  s.Decode = Range_Decode;
+  s.DecodeBit = Range_DecodeBit;
+}
+
+struct CPpmdCpp
+{
+  unsigned Ver;
+  CRangeDecoder _rc;
+  CPpmd7 _ppmd7;
+  CPpmd8 _ppmd8;
+  
+  CPpmdCpp(unsigned version)
+  {
+    Ver = version;
+    Ppmd7_Construct(&_ppmd7);
+    Ppmd8_Construct(&_ppmd8);
+  }
+
+  ~CPpmdCpp()
+  {
+    Ppmd7_Free(&_ppmd7, &g_BigAlloc);
+    Ppmd8_Free(&_ppmd8, &g_BigAlloc);
+  }
+
+  bool Alloc(UInt32 memInMB)
+  {
+    memInMB <<= 20;
+    if (Ver == 7)
+      return Ppmd7_Alloc(&_ppmd7, memInMB, &g_BigAlloc) != 0;
+    return Ppmd8_Alloc(&_ppmd8, memInMB, &g_BigAlloc) != 0;
+  }
+
+  void Init(unsigned order, unsigned restor)
+  {
+    if (Ver == 7)
+      Ppmd7_Init(&_ppmd7, order);
+    else
+      Ppmd8_Init(&_ppmd8, order, restor);;
+  }
+    
+  bool InitRc(CByteInBufWrap *inStream)
+  {
+    if (Ver == 7)
+    {
+      _rc.Stream = inStream;
+      return _rc.Init();
+    }
+    else
+    {
+      _ppmd8.Stream.In = &inStream->p;
+      return Ppmd8_RangeDec_Init(&_ppmd8) != 0;
+    }
+  }
+
+  bool IsFinishedOK()
+  {
+    if (Ver == 7)
+      return Ppmd7z_RangeDec_IsFinishedOK(&_rc);
+    return Ppmd8_RangeDec_IsFinishedOK(&_ppmd8);
+  }
+};
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  if (numItems == 0)
+    return S_OK;
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
+    return E_INVALIDARG;
+
+  // extractCallback->SetTotal(_packSize);
+  UInt64 currentTotalPacked = 0;
+  RINOK(extractCallback->SetCompleted(&currentTotalPacked));
+  CMyComPtr<ISequentialOutStream> realOutStream;
+  Int32 askMode = testMode ?
+      NExtract::NAskMode::kTest :
+      NExtract::NAskMode::kExtract;
+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
+  if (!testMode && !realOutStream)
+    return S_OK;
+
+  extractCallback->PrepareOperation(askMode);
+
+  CByteInBufWrap inBuf;
+  if (!inBuf.Alloc(1 << 20))
+    return E_OUTOFMEMORY;
+  inBuf.Stream = _stream;
+
+  CBuf outBuf;
+  if (!outBuf.Alloc())
+    return E_OUTOFMEMORY;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, true);
+
+  CPpmdCpp ppmd(_item.Ver);
+  if (!ppmd.Alloc(_item.MemInMB))
+    return E_OUTOFMEMORY;
+  Int32 opRes = NExtract::NOperationResult::kUnSupportedMethod;
+  if (_item.IsSupported())
+  {
+    opRes = NExtract::NOperationResult::kDataError;
+    ppmd.Init(_item.Order, _item.Restor);
+    inBuf.Init();
+    UInt64 outSize = 0;
+    if (ppmd.InitRc(&inBuf) && !inBuf.Extra && inBuf.Res == S_OK)
+    for (;;)
+    {
+      lps->InSize = _packSize = inBuf.GetProcessed();
+      lps->OutSize = outSize;
+      RINOK(lps->SetCur());
+
+      size_t i;
+      int sym = 0;
+
+      if (ppmd.Ver == 7)
+      {
+        for (i = 0; i < kBufSize; i++)
+        {
+          sym = Ppmd7_DecodeSymbol(&ppmd._ppmd7, &ppmd._rc.s);
+          if (inBuf.Extra || sym < 0)
+            break;
+          outBuf.Buf[i] = (Byte)sym;
+        }
+      }
+      else
+      {
+        for (i = 0; i < kBufSize; i++)
+        {
+          sym = Ppmd8_DecodeSymbol(&ppmd._ppmd8);
+          if (inBuf.Extra || sym < 0)
+            break;
+          outBuf.Buf[i] = (Byte)sym;
+        }
+      }
+
+      outSize += i;
+      _packSize = _headerSize + inBuf.GetProcessed();
+      _packSizeDefined = true;
+      if (realOutStream)
+      {
+        RINOK(WriteStream(realOutStream, outBuf.Buf, i));
+      }
+      if (sym < 0)
+      {
+        if (sym == -1 && ppmd.IsFinishedOK())
+          opRes = NExtract::NOperationResult::kOK;
+        break;
+      }
+    }
+    RINOK(inBuf.Res);
+  }
+  realOutStream.Release();
+  return extractCallback->SetOperationResult(opRes);
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"Ppmd", L"pmd", 0, 0xD, { 0x8F, 0xAF, 0xAC, 0x84 }, 4, false, CreateArc, 0 };
+
+REGISTER_ARC(Ppmd)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,869 @@
+// RarHandler.cpp
+
+#include "StdAfx.h"
+
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/PropVariantUtils.h"
+#include "Windows/Time.h"
+
+#include "../../IPassword.h"
+
+#include "../../Common/CreateCoder.h"
+#include "../../Common/FilterCoder.h"
+#include "../../Common/MethodId.h"
+#include "../../Common/ProgressUtils.h"
+
+#include "../../Compress/CopyCoder.h"
+
+#include "../../Crypto/Rar20Crypto.h"
+#include "../../Crypto/RarAes.h"
+
+#include "../Common/ItemNameUtils.h"
+#include "../Common/OutStreamWithCRC.h"
+
+#include "RarHandler.h"
+
+using namespace NWindows;
+using namespace NTime;
+
+namespace NArchive {
+namespace NRar {
+
+static const wchar_t *kHostOS[] =
+{
+  L"MS DOS",
+  L"OS/2",
+  L"Win32",
+  L"Unix",
+  L"Mac OS",
+  L"BeOS"
+};
+
+static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]);
+
+static const wchar_t *kUnknownOS = L"Unknown";
+
+static const CUInt32PCharPair k_Flags[] =
+{
+  { 0, "Volume" },
+  { 1, "Comment" },
+  { 2, "Lock" },
+  { 3, "Solid" },
+  { 4, "NewVolName" }, // pack_comment in old versuons
+  { 5, "Authenticity" },
+  { 6, "Recovery" },
+  { 7, "BlockEncryption" },
+  { 8, "FirstVolume" },
+  { 9, "EncryptVer" }
+};
+
+static const STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidIsDir, VT_BOOL},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMTime, VT_FILETIME},
+  { NULL, kpidCTime, VT_FILETIME},
+  { NULL, kpidATime, VT_FILETIME},
+  { NULL, kpidAttrib, VT_UI4},
+
+  { NULL, kpidEncrypted, VT_BOOL},
+  { NULL, kpidSolid, VT_BOOL},
+  { NULL, kpidCommented, VT_BOOL},
+  { NULL, kpidSplitBefore, VT_BOOL},
+  { NULL, kpidSplitAfter, VT_BOOL},
+  { NULL, kpidCRC, VT_UI4},
+  { NULL, kpidHostOS, VT_BSTR},
+  { NULL, kpidMethod, VT_BSTR},
+  { NULL, kpidUnpackVer, VT_UI1}
+};
+
+static const STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidCharacts, VT_BSTR},
+  { NULL, kpidSolid, VT_BOOL},
+  { NULL, kpidNumBlocks, VT_UI4},
+  // { NULL, kpidEncrypted, VT_BOOL},
+  { NULL, kpidIsVolume, VT_BOOL},
+  { NULL, kpidNumVolumes, VT_UI4},
+  { NULL, kpidPhySize, VT_UI8}
+  // { NULL, kpidCommented, VT_BOOL}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+UInt64 CHandler::GetPackSize(int refIndex) const
+{
+  const CRefItem &refItem = _refItems[refIndex];
+  UInt64 totalPackSize = 0;
+  for (int i = 0; i < refItem.NumItems; i++)
+    totalPackSize += _items[refItem.ItemIndex + i].PackSize;
+  return totalPackSize;
+}
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidSolid: prop = _archiveInfo.IsSolid(); break;
+    case kpidCharacts: FLAGS_TO_PROP(k_Flags, _archiveInfo.Flags, prop); break;
+    // case kpidEncrypted: prop = _archiveInfo.IsEncrypted(); break; // it's for encrypted names.
+    case kpidIsVolume: prop = _archiveInfo.IsVolume(); break;
+    case kpidNumVolumes: prop = (UInt32)_archives.Size(); break;
+    case kpidOffset: if (_archiveInfo.StartPosition != 0) prop = _archiveInfo.StartPosition; break;
+    // case kpidCommented: prop = _archiveInfo.IsCommented(); break;
+    case kpidNumBlocks:
+    {
+      UInt32 numBlocks = 0;
+      for (int i = 0; i < _refItems.Size(); i++)
+        if (!IsSolid(i))
+          numBlocks++;
+      prop = (UInt32)numBlocks;
+      break;
+    }
+    case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _refItems.Size();
+  return S_OK;
+}
+
+static bool RarTimeToFileTime(const CRarTime &rarTime, FILETIME &result)
+{
+  if (!DosTimeToFileTime(rarTime.DosTime, result))
+    return false;
+  UInt64 value =  (((UInt64)result.dwHighDateTime) << 32) + result.dwLowDateTime;
+  value += (UInt64)rarTime.LowSecond * 10000000;
+  value += ((UInt64)rarTime.SubTime[2] << 16) +
+    ((UInt64)rarTime.SubTime[1] << 8) +
+    ((UInt64)rarTime.SubTime[0]);
+  result.dwLowDateTime = (DWORD)value;
+  result.dwHighDateTime = DWORD(value >> 32);
+  return true;
+}
+
+static void RarTimeToProp(const CRarTime &rarTime, NWindows::NCOM::CPropVariant &prop)
+{
+  FILETIME localFileTime, utcFileTime;
+  if (RarTimeToFileTime(rarTime, localFileTime))
+  {
+    if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))
+      utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
+  }
+  else
+    utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
+  prop = utcFileTime;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID,  PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  const CRefItem &refItem = _refItems[index];
+  const CItemEx &item = _items[refItem.ItemIndex];
+  switch(propID)
+  {
+    case kpidPath:
+    {
+      UString u;
+      if (item.HasUnicodeName() && !item.UnicodeName.IsEmpty())
+        u = item.UnicodeName;
+      else
+        u = MultiByteToUnicodeString(item.Name, CP_OEMCP);
+      prop = (const wchar_t *)NItemName::WinNameToOSName(u);
+      break;
+    }
+    case kpidIsDir: prop = item.IsDir(); break;
+    case kpidSize: prop = item.Size; break;
+    case kpidPackSize: prop = GetPackSize(index); break;
+    case kpidMTime: RarTimeToProp(item.MTime, prop); break;
+    case kpidCTime: if (item.CTimeDefined) RarTimeToProp(item.CTime, prop); break;
+    case kpidATime: if (item.ATimeDefined) RarTimeToProp(item.ATime, prop); break;
+    case kpidAttrib: prop = item.GetWinAttributes(); break;
+    case kpidEncrypted: prop = item.IsEncrypted(); break;
+    case kpidSolid: prop = IsSolid(index); break;
+    case kpidCommented: prop = item.IsCommented(); break;
+    case kpidSplitBefore: prop = item.IsSplitBefore(); break;
+    case kpidSplitAfter: prop = _items[refItem.ItemIndex + refItem.NumItems - 1].IsSplitAfter(); break;
+    case kpidCRC:
+    {
+      const CItemEx &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
+      prop = ((lastItem.IsSplitAfter()) ? item.FileCRC : lastItem.FileCRC);
+      break;
+    }
+    case kpidUnpackVer: prop = item.UnPackVersion; break;
+    case kpidMethod:
+    {
+      UString method;
+      if (item.Method >= Byte('0') && item.Method <= Byte('5'))
+      {
+        method = L"m";
+        wchar_t temp[32];
+        ConvertUInt64ToString(item.Method - Byte('0'), temp);
+        method += temp;
+        if (!item.IsDir())
+        {
+          method += L":";
+          ConvertUInt64ToString(16 + item.GetDictSize(), temp);
+          method += temp;
+        }
+      }
+      else
+      {
+        wchar_t temp[32];
+        ConvertUInt64ToString(item.Method, temp);
+        method += temp;
+      }
+      prop = method;
+      break;
+    }
+    case kpidHostOS: prop = (item.HostOS < kNumHostOSes) ? (kHostOS[item.HostOS]) : kUnknownOS; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+class CVolumeName
+{
+  bool _first;
+  bool _newStyle;
+  UString _unchangedPart;
+  UString _changedPart;
+  UString _afterPart;
+public:
+  CVolumeName(): _newStyle(true) {};
+
+  bool InitName(const UString &name, bool newStyle)
+  {
+    _first = true;
+    _newStyle = newStyle;
+    int dotPos = name.ReverseFind('.');
+    UString basePart = name;
+    if (dotPos >= 0)
+    {
+      UString ext = name.Mid(dotPos + 1);
+      if (ext.CompareNoCase(L"rar") == 0)
+      {
+        _afterPart = name.Mid(dotPos);
+        basePart = name.Left(dotPos);
+      }
+      else if (ext.CompareNoCase(L"exe") == 0)
+      {
+        _afterPart = L".rar";
+        basePart = name.Left(dotPos);
+      }
+      else if (!_newStyle)
+      {
+        if (ext.CompareNoCase(L"000") == 0 ||
+            ext.CompareNoCase(L"001") == 0 ||
+            ext.CompareNoCase(L"r00") == 0 ||
+            ext.CompareNoCase(L"r01") == 0)
+        {
+          _afterPart.Empty();
+          _first = false;
+          _changedPart = ext;
+          _unchangedPart = name.Left(dotPos + 1);
+          return true;
+        }
+      }
+    }
+
+    if (!_newStyle)
+    {
+      _afterPart.Empty();
+      _unchangedPart = basePart + UString(L".");
+      _changedPart = L"r00";
+      return true;
+    }
+
+    int numLetters = 1;
+    if (basePart.Right(numLetters) == L"1" || basePart.Right(numLetters) == L"0")
+    {
+      while (numLetters < basePart.Length())
+      {
+        if (basePart[basePart.Length() - numLetters - 1] != '0')
+          break;
+        numLetters++;
+      }
+    }
+    else
+      return false;
+    _unchangedPart = basePart.Left(basePart.Length() - numLetters);
+    _changedPart = basePart.Right(numLetters);
+    return true;
+  }
+
+  UString GetNextName()
+  {
+    UString newName;
+    if (_newStyle || !_first)
+    {
+      int i;
+      int numLetters = _changedPart.Length();
+      for (i = numLetters - 1; i >= 0; i--)
+      {
+        wchar_t c = _changedPart[i];
+        if (c == L'9')
+        {
+          c = L'0';
+          newName = c + newName;
+          if (i == 0)
+            newName = UString(L'1') + newName;
+          continue;
+        }
+        c++;
+        newName = UString(c) + newName;
+        i--;
+        for (; i >= 0; i--)
+          newName = _changedPart[i] + newName;
+        break;
+      }
+      _changedPart = newName;
+    }
+    _first = false;
+    return _unchangedPart + _changedPart + _afterPart;
+  }
+};
+
+HRESULT CHandler::Open2(IInStream *stream,
+    const UInt64 *maxCheckStartPosition,
+    IArchiveOpenCallback *openCallback)
+{
+  {
+    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
+    CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openCallback;
+    
+    CVolumeName seqName;
+
+    UInt64 totalBytes = 0;
+    UInt64 curBytes = 0;
+
+    if (openCallback)
+    {
+      openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
+      openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
+    }
+
+    for (;;)
+    {
+      CMyComPtr<IInStream> inStream;
+      if (!_archives.IsEmpty())
+      {
+        if (!openVolumeCallback)
+          break;
+        
+        if (_archives.Size() == 1)
+        {
+          if (!_archiveInfo.IsVolume())
+            break;
+          UString baseName;
+          {
+            NCOM::CPropVariant prop;
+            RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
+            if (prop.vt != VT_BSTR)
+              break;
+            baseName = prop.bstrVal;
+          }
+          seqName.InitName(baseName, _archiveInfo.HaveNewVolumeName());
+        }
+
+        UString fullName = seqName.GetNextName();
+        HRESULT result = openVolumeCallback->GetStream(fullName, &inStream);
+        if (result == S_FALSE)
+          break;
+        if (result != S_OK)
+          return result;
+        if (!stream)
+          break;
+      }
+      else
+        inStream = stream;
+
+      UInt64 endPos = 0;
+      RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));
+      RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
+      if (openCallback)
+      {
+        totalBytes += endPos;
+        RINOK(openCallback->SetTotal(NULL, &totalBytes));
+      }
+      
+      NArchive::NRar::CInArchive archive;
+      RINOK(archive.Open(inStream, maxCheckStartPosition));
+
+      if (_archives.IsEmpty())
+        archive.GetArchiveInfo(_archiveInfo);
+     
+      CItemEx item;
+      for (;;)
+      {
+        if (archive.m_Position > endPos)
+        {
+          AddErrorMessage("Unexpected end of archive");
+          break;
+        }
+        bool decryptionError;
+        AString errorMessageLoc;
+        HRESULT result = archive.GetNextItem(item, getTextPassword, decryptionError, errorMessageLoc);
+        if (errorMessageLoc)
+          AddErrorMessage(errorMessageLoc);
+        if (result == S_FALSE)
+        {
+          if (decryptionError && _items.IsEmpty())
+            return S_FALSE;
+          break;
+        }
+        RINOK(result);
+        if (item.IgnoreItem())
+          continue;
+
+        bool needAdd = true;
+        if (item.IsSplitBefore())
+        {
+          if (!_refItems.IsEmpty())
+          {
+            CRefItem &refItem = _refItems.Back();
+            refItem.NumItems++;
+            needAdd = false;
+          }
+        }
+        if (needAdd)
+        {
+          CRefItem refItem;
+          refItem.ItemIndex = _items.Size();
+          refItem.NumItems = 1;
+          refItem.VolumeIndex = _archives.Size();
+          _refItems.Add(refItem);
+        }
+        _items.Add(item);
+        if (openCallback && _items.Size() % 100 == 0)
+        {
+          UInt64 numFiles = _items.Size();
+          UInt64 numBytes = curBytes + item.Position;
+          RINOK(openCallback->SetCompleted(&numFiles, &numBytes));
+        }
+      }
+      curBytes += endPos;
+      _archives.Add(archive);
+    }
+  }
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+    const UInt64 *maxCheckStartPosition,
+    IArchiveOpenCallback *openCallback)
+{
+  COM_TRY_BEGIN
+  Close();
+  try
+  {
+    HRESULT res = Open2(stream, maxCheckStartPosition, openCallback);
+    if (res != S_OK)
+      Close();
+    return res;
+  }
+  catch(const CInArchiveException &) { Close(); return S_FALSE; }
+  catch(...) { Close(); throw; }
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  COM_TRY_BEGIN
+  _errorMessage.Empty();
+  _refItems.Clear();
+  _items.Clear();
+  _archives.Clear();
+  return S_OK;
+  COM_TRY_END
+}
+
+struct CMethodItem
+{
+  Byte RarUnPackVersion;
+  CMyComPtr<ICompressCoder> Coder;
+};
+
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+  UInt64 censoredTotalUnPacked = 0,
+        // censoredTotalPacked = 0,
+        importantTotalUnPacked = 0;
+        // importantTotalPacked = 0;
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _refItems.Size();
+  if (numItems == 0)
+    return S_OK;
+  int lastIndex = 0;
+  CRecordVector<int> importantIndexes;
+  CRecordVector<bool> extractStatuses;
+
+  for (UInt32 t = 0; t < numItems; t++)
+  {
+    int index = allFilesMode ? t : indices[t];
+    const CRefItem &refItem = _refItems[index];
+    const CItemEx &item = _items[refItem.ItemIndex];
+    censoredTotalUnPacked += item.Size;
+    // censoredTotalPacked += item.PackSize;
+    int j;
+    for (j = lastIndex; j <= index; j++)
+      // if (!_items[_refItems[j].ItemIndex].IsSolid())
+      if (!IsSolid(j))
+        lastIndex = j;
+    for (j = lastIndex; j <= index; j++)
+    {
+      const CRefItem &refItem = _refItems[j];
+      const CItemEx &item = _items[refItem.ItemIndex];
+
+      // const CItemEx &item = _items[j];
+
+      importantTotalUnPacked += item.Size;
+      // importantTotalPacked += item.PackSize;
+      importantIndexes.Add(j);
+      extractStatuses.Add(j == index);
+    }
+    lastIndex = index + 1;
+  }
+
+  RINOK(extractCallback->SetTotal(importantTotalUnPacked));
+  UInt64 currentImportantTotalUnPacked = 0;
+  UInt64 currentImportantTotalPacked = 0;
+  UInt64 currentUnPackSize, currentPackSize;
+
+  CObjectVector<CMethodItem> methodItems;
+
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CFilterCoder *filterStreamSpec = new CFilterCoder;
+  CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;
+
+  NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL;
+  CMyComPtr<ICompressFilter> rar20CryptoDecoder;
+  NCrypto::NRar29::CDecoder *rar29CryptoDecoderSpec = NULL;
+  CMyComPtr<ICompressFilter> rar29CryptoDecoder;
+
+  CFolderInStream *folderInStreamSpec = NULL;
+  CMyComPtr<ISequentialInStream> folderInStream;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  bool solidStart = true;
+  for (int i = 0; i < importantIndexes.Size(); i++,
+      currentImportantTotalUnPacked += currentUnPackSize,
+      currentImportantTotalPacked += currentPackSize)
+  {
+    lps->InSize = currentImportantTotalPacked;
+    lps->OutSize = currentImportantTotalUnPacked;
+    RINOK(lps->SetCur());
+    CMyComPtr<ISequentialOutStream> realOutStream;
+
+    Int32 askMode;
+    if (extractStatuses[i])
+      askMode = testMode ?
+          NExtract::NAskMode::kTest :
+          NExtract::NAskMode::kExtract;
+    else
+      askMode = NExtract::NAskMode::kSkip;
+
+    UInt32 index = importantIndexes[i];
+
+    const CRefItem &refItem = _refItems[index];
+    const CItemEx &item = _items[refItem.ItemIndex];
+
+    currentUnPackSize = item.Size;
+
+    currentPackSize = GetPackSize(index);
+
+    if (item.IgnoreItem())
+      continue;
+
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+    if (!IsSolid(index))
+      solidStart = true;
+    if (item.IsDir())
+    {
+      RINOK(extractCallback->PrepareOperation(askMode));
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+      continue;
+    }
+
+    bool mustBeProcessedAnywhere = false;
+    if (i < importantIndexes.Size() - 1)
+    {
+      // const CRefItem &nextRefItem = _refItems[importantIndexes[i + 1]];
+      // const CItemEx &nextItemInfo = _items[nextRefItem.ItemIndex];
+      // mustBeProcessedAnywhere = nextItemInfo.IsSolid();
+      mustBeProcessedAnywhere = IsSolid(importantIndexes[i + 1]);
+    }
+    
+    if (!mustBeProcessedAnywhere && !testMode && !realOutStream)
+      continue;
+    
+    if (!realOutStream && !testMode)
+      askMode = NExtract::NAskMode::kSkip;
+
+    RINOK(extractCallback->PrepareOperation(askMode));
+
+    COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
+    CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+    outStreamSpec->SetStream(realOutStream);
+    outStreamSpec->Init();
+    realOutStream.Release();
+    
+    /*
+    for (int partIndex = 0; partIndex < 1; partIndex++)
+    {
+    CMyComPtr<ISequentialInStream> inStream;
+
+    // item redefinition
+    const CItemEx &item = _items[refItem.ItemIndex + partIndex];
+
+    NArchive::NRar::CInArchive &archive = _archives[refItem.VolumeIndex + partIndex];
+
+    inStream.Attach(archive.CreateLimitedStream(item.GetDataPosition(),
+      item.PackSize));
+    */
+    if (!folderInStream)
+    {
+      folderInStreamSpec = new CFolderInStream;
+      folderInStream = folderInStreamSpec;
+    }
+
+    folderInStreamSpec->Init(&_archives, &_items, refItem);
+
+    UInt64 packSize = currentPackSize;
+
+    // packedPos += item.PackSize;
+    // unpackedPos += 0;
+    
+    CMyComPtr<ISequentialInStream> inStream;
+    if (item.IsEncrypted())
+    {
+      CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
+      if (item.UnPackVersion >= 29)
+      {
+        if (!rar29CryptoDecoder)
+        {
+          rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder;
+          rar29CryptoDecoder = rar29CryptoDecoderSpec;
+          // RINOK(rar29CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar29Decoder));
+        }
+        rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
+        CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;
+        RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
+            &cryptoProperties));
+        RINOK(cryptoProperties->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
+        filterStreamSpec->Filter = rar29CryptoDecoder;
+      }
+      else if (item.UnPackVersion >= 20)
+      {
+        if (!rar20CryptoDecoder)
+        {
+          rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder;
+          rar20CryptoDecoder = rar20CryptoDecoderSpec;
+          // RINOK(rar20CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar20Decoder));
+        }
+        filterStreamSpec->Filter = rar20CryptoDecoder;
+      }
+      else
+      {
+        outStream.Release();
+        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
+        continue;
+      }
+      RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword,
+          &cryptoSetPassword));
+
+      if (!getTextPassword)
+        extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
+      if (getTextPassword)
+      {
+        CMyComBSTR password;
+        RINOK(getTextPassword->CryptoGetTextPassword(&password));
+        if (item.UnPackVersion >= 29)
+        {
+          CByteBuffer buffer;
+          UString unicodePassword(password);
+          const UInt32 sizeInBytes = unicodePassword.Length() * 2;
+          buffer.SetCapacity(sizeInBytes);
+          for (int i = 0; i < unicodePassword.Length(); i++)
+          {
+            wchar_t c = unicodePassword[i];
+            ((Byte *)buffer)[i * 2] = (Byte)c;
+            ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
+          }
+          RINOK(cryptoSetPassword->CryptoSetPassword(
+            (const Byte *)buffer, sizeInBytes));
+        }
+        else
+        {
+          AString oemPassword = UnicodeStringToMultiByte(
+            (const wchar_t *)password, CP_OEMCP);
+          RINOK(cryptoSetPassword->CryptoSetPassword(
+            (const Byte *)(const char *)oemPassword, oemPassword.Length()));
+        }
+      }
+      else
+      {
+        RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
+      }
+      filterStreamSpec->SetInStream(folderInStream);
+      inStream = filterStream;
+    }
+    else
+    {
+      inStream = folderInStream;
+    }
+    CMyComPtr<ICompressCoder> commonCoder;
+    switch(item.Method)
+    {
+      case '0':
+      {
+        commonCoder = copyCoder;
+        break;
+      }
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      {
+        /*
+        if (item.UnPackVersion >= 29)
+        {
+          outStream.Release();
+          RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
+          continue;
+        }
+        */
+        int m;
+        for (m = 0; m < methodItems.Size(); m++)
+          if (methodItems[m].RarUnPackVersion == item.UnPackVersion)
+            break;
+        if (m == methodItems.Size())
+        {
+          CMethodItem mi;
+          mi.RarUnPackVersion = item.UnPackVersion;
+
+          mi.Coder.Release();
+          if (item.UnPackVersion <= 30)
+          {
+            UInt32 methodID = 0x040300;
+            if (item.UnPackVersion < 20)
+              methodID += 1;
+            else if (item.UnPackVersion < 29)
+              methodID += 2;
+            else
+              methodID += 3;
+            RINOK(CreateCoder(EXTERNAL_CODECS_VARS methodID, mi.Coder, false));
+          }
+         
+          if (mi.Coder == 0)
+          {
+            outStream.Release();
+            RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
+            continue;
+          }
+
+          m = methodItems.Add(mi);
+        }
+        CMyComPtr<ICompressCoder> decoder = methodItems[m].Coder;
+
+        CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties;
+        RINOK(decoder.QueryInterface(IID_ICompressSetDecoderProperties2,
+            &compressSetDecoderProperties));
+        
+        Byte isSolid = (Byte)((IsSolid(index) || item.IsSplitBefore()) ? 1: 0);
+        if (solidStart)
+        {
+          isSolid = false;
+          solidStart = false;
+        }
+
+
+        RINOK(compressSetDecoderProperties->SetDecoderProperties2(&isSolid, 1));
+          
+        commonCoder = decoder;
+        break;
+      }
+      default:
+        outStream.Release();
+        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
+        continue;
+    }
+    HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &item.Size, progress);
+    if (item.IsEncrypted())
+      filterStreamSpec->ReleaseInStream();
+    if (result == S_FALSE)
+    {
+      outStream.Release();
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError));
+      continue;
+    }
+    if (result != S_OK)
+      return result;
+
+    /*
+    if (refItem.NumItems == 1 &&
+        !item.IsSplitBefore() && !item.IsSplitAfter())
+    */
+    {
+      const CItemEx &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
+      bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC;
+      outStream.Release();
+      RINOK(extractCallback->SetOperationResult(crcOK ?
+          NExtract::NOperationResult::kOK:
+          NExtract::NOperationResult::kCRCError));
+    }
+    /*
+    else
+    {
+      bool crcOK = true;
+      for (int partIndex = 0; partIndex < refItem.NumItems; partIndex++)
+      {
+        const CItemEx &item = _items[refItem.ItemIndex + partIndex];
+        if (item.FileCRC != folderInStreamSpec->CRCs[partIndex])
+        {
+          crcOK = false;
+          break;
+        }
+      }
+      RINOK(extractCallback->SetOperationResult(crcOK ?
+          NExtract::NOperationResult::kOK:
+          NExtract::NOperationResult::kCRCError));
+    }
+    */
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+IMPL_ISetCompressCodecsInfo
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarHandler.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarHandler.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarHandler.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarHandler.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,66 @@
+// Rar/Handler.h
+
+#ifndef __RAR_HANDLER_H
+#define __RAR_HANDLER_H
+
+#include "../IArchive.h"
+
+#include "../../Common/CreateCoder.h"
+
+#include "RarIn.h"
+#include "RarVolumeInStream.h"
+
+namespace NArchive {
+namespace NRar {
+
+class CHandler:
+  public IInArchive,
+  PUBLIC_ISetCompressCodecsInfo
+  public CMyUnknownImp
+{
+  CRecordVector<CRefItem> _refItems;
+  CObjectVector<CItemEx> _items;
+  CObjectVector<CInArchive> _archives;
+  NArchive::NRar::CInArchiveInfo _archiveInfo;
+  AString _errorMessage;
+
+  DECL_EXTERNAL_CODECS_VARS
+
+  UInt64 GetPackSize(int refIndex) const;
+
+  bool IsSolid(int refIndex)
+  {
+    const CItemEx &item = _items[_refItems[refIndex].ItemIndex];
+    if (item.UnPackVersion < 20)
+    {
+      if (_archiveInfo.IsSolid())
+        return (refIndex > 0);
+      return false;
+    }
+    return item.IsSolid();
+  }
+  void AddErrorMessage(const AString &s)
+  {
+    if (!_errorMessage.IsEmpty())
+      _errorMessage += '\n';
+    _errorMessage += s;
+  }
+
+  HRESULT Open2(IInStream *stream,
+      const UInt64 *maxCheckStartPosition,
+      IArchiveOpenCallback *openCallback);
+
+public:
+  MY_QUERYINTERFACE_BEGIN2(IInArchive)
+  QUERY_ENTRY_ISetCompressCodecsInfo
+  MY_QUERYINTERFACE_END
+  MY_ADDREF_RELEASE
+  
+  INTERFACE_IInArchive(;)
+
+  DECL_ISetCompressCodecsInfo
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarHeader.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarHeader.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarHeader.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarHeader.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,21 @@
+// Archive/Rar/Headers.cpp
+
+#include "StdAfx.h"
+
+#include "RarHeader.h"
+
+namespace NArchive{
+namespace NRar{
+namespace NHeader{
+
+Byte kMarker[kMarkerSize] = {0x52 + 1, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00};
+  
+class CMarkerInitializer
+{
+public:
+  CMarkerInitializer() { kMarker[0]--; };
+};
+
+static CMarkerInitializer markerInitializer;
+
+}}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarHeader.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarHeader.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarHeader.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarHeader.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,205 @@
+// Archive/RarHeader.h
+
+#ifndef __ARCHIVE_RAR_HEADER_H
+#define __ARCHIVE_RAR_HEADER_H
+
+#include "Common/Types.h"
+
+namespace NArchive {
+namespace NRar {
+namespace NHeader {
+
+const int kMarkerSize = 7;
+extern Byte kMarker[kMarkerSize];
+  
+const int kArchiveSolid = 0x1;
+
+namespace NBlockType
+{
+  enum EBlockType
+  {
+    kMarker = 0x72,
+    kArchiveHeader,
+    kFileHeader,
+    kCommentHeader,
+    kOldAuthenticity,
+    kOldSubBlock,
+    kRecoveryRecord,
+    kAuthenticity,
+    kSubBlock,
+    kEndOfArchive
+  };
+}
+
+namespace NArchive
+{
+  const UInt16 kVolume  = 1;
+  const UInt16 kComment = 2;
+  const UInt16 kLock    = 4;
+  const UInt16 kSolid   = 8;
+  const UInt16 kNewVolName = 0x10; // ('volname.partN.rar')
+  const UInt16 kAuthenticity  = 0x20;
+  const UInt16 kRecovery = 0x40;
+  const UInt16 kBlockEncryption  = 0x80;
+  const UInt16 kFirstVolume = 0x100; // (set only by RAR 3.0 and later)
+  const UInt16 kEncryptVer = 0x200; // RAR 3.6 there is EncryptVer Byte in End of MainHeader
+
+  const int kHeaderSizeMin = 7;
+  
+  const int kArchiveHeaderSize = 13;
+
+  const int kBlockHeadersAreEncrypted = 0x80;
+
+}
+
+namespace NFile
+{
+  const int kSplitBefore = 1 << 0;
+  const int kSplitAfter  = 1 << 1;
+  const int kEncrypted   = 1 << 2;
+  const int kComment     = 1 << 3;
+  const int kSolid       = 1 << 4;
+  
+  const int kDictBitStart     = 5;
+  const int kNumDictBits  = 3;
+  const int kDictMask         = (1 << kNumDictBits) - 1;
+  const int kDictDirectoryValue  = 0x7;
+  
+  const int kSize64Bits    = 1 << 8;
+  const int kUnicodeName   = 1 << 9;
+  const int kSalt          = 1 << 10;
+  const int kOldVersion    = 1 << 11;
+  const int kExtTime       = 1 << 12;
+  // const int kExtFlags      = 1 << 13;
+  // const int kSkipIfUnknown = 1 << 14;
+
+  const int kLongBlock    = 1 << 15;
+  
+  /*
+  struct CBlock
+  {
+    // UInt16 HeadCRC;
+    // Byte Type;
+    // UInt16 Flags;
+    // UInt16 HeadSize;
+    UInt32 PackSize;
+    UInt32 UnPackSize;
+    Byte HostOS;
+    UInt32 FileCRC;
+    UInt32 Time;
+    Byte UnPackVersion;
+    Byte Method;
+    UInt16 NameSize;
+    UInt32 Attributes;
+  };
+  */
+
+  /*
+  struct CBlock32
+  {
+    UInt16 HeadCRC;
+    Byte Type;
+    UInt16 Flags;
+    UInt16 HeadSize;
+    UInt32 PackSize;
+    UInt32 UnPackSize;
+    Byte HostOS;
+    UInt32 FileCRC;
+    UInt32 Time;
+    Byte UnPackVersion;
+    Byte Method;
+    UInt16 NameSize;
+    UInt32 Attributes;
+    UInt16 GetRealCRC(const void *aName, UInt32 aNameSize,
+        bool anExtraDataDefined = false, Byte *anExtraData = 0) const;
+  };
+  struct CBlock64
+  {
+    UInt16 HeadCRC;
+    Byte Type;
+    UInt16 Flags;
+    UInt16 HeadSize;
+    UInt32 PackSizeLow;
+    UInt32 UnPackSizeLow;
+    Byte HostOS;
+    UInt32 FileCRC;
+    UInt32 Time;
+    Byte UnPackVersion;
+    Byte Method;
+    UInt16 NameSize;
+    UInt32 Attributes;
+    UInt32 PackSizeHigh;
+    UInt32 UnPackSizeHigh;
+    UInt16 GetRealCRC(const void *aName, UInt32 aNameSize) const;
+  };
+  */
+  
+  const int kLabelFileAttribute            = 0x08;
+  const int kWinFileDirectoryAttributeMask = 0x10;
+  
+  enum CHostOS
+  {
+    kHostMSDOS = 0,
+      kHostOS2   = 1,
+      kHostWin32 = 2,
+      kHostUnix  = 3,
+      kHostMacOS = 4,
+      kHostBeOS = 5
+  };
+}
+
+namespace NBlock
+{
+  const UInt16 kLongBlock = 1 << 15;
+  struct CBlock
+  {
+    UInt16 CRC;
+    Byte Type;
+    UInt16 Flags;
+    UInt16 HeadSize;
+    //  UInt32 DataSize;
+  };
+}
+
+/*
+struct CSubBlock
+{
+  UInt16 HeadCRC;
+  Byte HeadType;
+  UInt16 Flags;
+  UInt16 HeadSize;
+  UInt32 DataSize;
+  UInt16 SubType;
+  Byte Level; // Reserved : Must be 0
+};
+
+struct CCommentBlock
+{
+  UInt16 HeadCRC;
+  Byte HeadType;
+  UInt16 Flags;
+  UInt16 HeadSize;
+  UInt16 UnpSize;
+  Byte UnpVer;
+  Byte Method;
+  UInt16 CommCRC;
+};
+
+
+struct CProtectHeader
+{
+  UInt16 HeadCRC;
+  Byte HeadType;
+  UInt16 Flags;
+  UInt16 HeadSize;
+  UInt32 DataSize;
+  Byte Version;
+  UInt16 RecSectors;
+  UInt32 TotalBlocks;
+  Byte Mark[8];
+};
+*/
+
+}}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarIn.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarIn.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarIn.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarIn.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,478 @@
+// Archive/RarIn.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/7zCrc.h"
+#include "../../../../C/CpuArch.h"
+
+#include "Common/StringConvert.h"
+#include "Common/UTFConvert.h"
+
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/StreamUtils.h"
+
+#include "../Common/FindSignature.h"
+
+#include "RarIn.h"
+
+#define Get16(p) GetUi16(p)
+#define Get32(p) GetUi32(p)
+#define Get64(p) GetUi64(p)
+
+namespace NArchive {
+namespace NRar {
+
+static const char *k_UnexpectedEnd = "Unexpected end of archive";
+static const char *k_DecryptionError = "Decryption Error";
+
+void CInArchive::ThrowExceptionWithCode(
+    CInArchiveException::CCauseType cause)
+{
+  throw CInArchiveException(cause);
+}
+
+HRESULT CInArchive::Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit)
+{
+  try
+  {
+    Close();
+    HRESULT res = Open2(inStream, searchHeaderSizeLimit);
+    if (res == S_OK)
+      return res;
+    Close();
+    return res;
+  }
+  catch(...) { Close(); throw; }
+}
+
+void CInArchive::Close()
+{
+  m_Stream.Release();
+}
+
+HRESULT CInArchive::ReadBytesSpec(void *data, size_t *resSize)
+{
+  if (m_CryptoMode)
+  {
+    size_t size = *resSize;
+    *resSize = 0;
+    const Byte *bufData = m_DecryptedDataAligned;
+    UInt32 bufSize = m_DecryptedDataSize;
+    size_t i;
+    for (i = 0; i < size && m_CryptoPos < bufSize; i++)
+      ((Byte *)data)[i] = bufData[m_CryptoPos++];
+    *resSize = i;
+    return S_OK;
+  }
+  return ReadStream(m_Stream, data, resSize);
+}
+
+bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size)
+{
+  size_t processed = size;
+  if (ReadBytesSpec(data, &processed) != S_OK)
+    return false;
+  return processed == size;
+}
+
+HRESULT CInArchive::Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
+{
+  m_CryptoMode = false;
+  RINOK(stream->Seek(0, STREAM_SEEK_SET, &m_StreamStartPosition));
+  m_Position = m_StreamStartPosition;
+
+  UInt64 arcStartPos;
+  RINOK(FindSignatureInStream(stream, NHeader::kMarker, NHeader::kMarkerSize,
+      searchHeaderSizeLimit, arcStartPos));
+  m_Position = arcStartPos + NHeader::kMarkerSize;
+  RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL));
+  Byte buf[NHeader::NArchive::kArchiveHeaderSize + 1];
+
+  RINOK(ReadStream_FALSE(stream, buf, NHeader::NArchive::kArchiveHeaderSize));
+  AddToSeekValue(NHeader::NArchive::kArchiveHeaderSize);
+
+
+  UInt32 blockSize = Get16(buf + 5);
+
+  _header.EncryptVersion = 0;
+  _header.Flags = Get16(buf + 3);
+
+  UInt32 headerSize = NHeader::NArchive::kArchiveHeaderSize;
+  if (_header.IsThereEncryptVer())
+  {
+    if (blockSize <= headerSize)
+      return S_FALSE;
+    RINOK(ReadStream_FALSE(stream, buf + NHeader::NArchive::kArchiveHeaderSize, 1));
+    AddToSeekValue(1);
+    _header.EncryptVersion = buf[NHeader::NArchive::kArchiveHeaderSize];
+    headerSize += 1;
+  }
+  if (blockSize < headerSize ||
+      buf[2] != NHeader::NBlockType::kArchiveHeader ||
+      (UInt32)Get16(buf) != (CrcCalc(buf + 2, headerSize - 2) & 0xFFFF))
+    return S_FALSE;
+
+  size_t commentSize = blockSize - headerSize; 
+  _comment.SetCapacity(commentSize);
+  RINOK(ReadStream_FALSE(stream, _comment, commentSize));
+  AddToSeekValue(commentSize);
+  m_Stream = stream;
+  _header.StartPosition = arcStartPos;
+  return S_OK;
+}
+
+void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const
+{
+  archiveInfo = _header;
+}
+
+static void DecodeUnicodeFileName(const char *name, const Byte *encName,
+    int encSize, wchar_t *unicodeName, int maxDecSize)
+{
+  int encPos = 0;
+  int decPos = 0;
+  int flagBits = 0;
+  Byte flags = 0;
+  Byte highByte = encName[encPos++];
+  while (encPos < encSize && decPos < maxDecSize)
+  {
+    if (flagBits == 0)
+    {
+      flags = encName[encPos++];
+      flagBits = 8;
+    }
+    switch(flags >> 6)
+    {
+      case 0:
+        unicodeName[decPos++] = encName[encPos++];
+        break;
+      case 1:
+        unicodeName[decPos++] = (wchar_t)(encName[encPos++] + (highByte << 8));
+        break;
+      case 2:
+        unicodeName[decPos++] = (wchar_t)(encName[encPos] + (encName[encPos + 1] << 8));
+        encPos += 2;
+        break;
+      case 3:
+        {
+          int length = encName[encPos++];
+          if (length & 0x80)
+          {
+            Byte correction = encName[encPos++];
+            for (length = (length & 0x7f) + 2;
+                length > 0 && decPos < maxDecSize; length--, decPos++)
+              unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + (highByte << 8));
+          }
+          else
+            for (length += 2; length > 0 && decPos < maxDecSize; length--, decPos++)
+              unicodeName[decPos] = name[decPos];
+        }
+        break;
+    }
+    flags <<= 2;
+    flagBits -= 2;
+  }
+  unicodeName[decPos < maxDecSize ? decPos : maxDecSize - 1] = 0;
+}
+
+void CInArchive::ReadName(CItemEx &item, int nameSize)
+{
+  item.UnicodeName.Empty();
+  if (nameSize > 0)
+  {
+    m_NameBuffer.EnsureCapacity(nameSize + 1);
+    char *buffer = (char *)m_NameBuffer;
+
+    for (int i = 0; i < nameSize; i++)
+      buffer[i] = ReadByte();
+
+    int mainLen;
+    for (mainLen = 0; mainLen < nameSize; mainLen++)
+      if (buffer[mainLen] == '\0')
+        break;
+    buffer[mainLen] = '\0';
+    item.Name = buffer;
+
+    if(item.HasUnicodeName())
+    {
+      if(mainLen < nameSize)
+      {
+        int unicodeNameSizeMax = MyMin(nameSize, (0x400));
+        _unicodeNameBuffer.EnsureCapacity(unicodeNameSizeMax + 1);
+        DecodeUnicodeFileName(buffer, (const Byte *)buffer + mainLen + 1,
+            nameSize - (mainLen + 1), _unicodeNameBuffer, unicodeNameSizeMax);
+        item.UnicodeName = _unicodeNameBuffer;
+      }
+      else if (!ConvertUTF8ToUnicode(item.Name, item.UnicodeName))
+        item.UnicodeName.Empty();
+    }
+  }
+  else
+    item.Name.Empty();
+}
+
+Byte CInArchive::ReadByte()
+{
+  if (m_CurPos >= m_PosLimit)
+    throw CInArchiveException(CInArchiveException::kIncorrectArchive);
+  return m_CurData[m_CurPos++];
+}
+
+UInt16 CInArchive::ReadUInt16()
+{
+  UInt16 value = 0;
+  for (int i = 0; i < 2; i++)
+  {
+    Byte b = ReadByte();
+    value |= (UInt16(b) << (8 * i));
+  }
+  return value;
+}
+
+UInt32 CInArchive::ReadUInt32()
+{
+  UInt32 value = 0;
+  for (int i = 0; i < 4; i++)
+  {
+    Byte b = ReadByte();
+    value |= (UInt32(b) << (8 * i));
+  }
+  return value;
+}
+
+void CInArchive::ReadTime(Byte mask, CRarTime &rarTime)
+{
+  rarTime.LowSecond = (Byte)(((mask & 4) != 0) ? 1 : 0);
+  int numDigits = (mask & 3);
+  rarTime.SubTime[0] = rarTime.SubTime[1] = rarTime.SubTime[2] = 0;
+  for (int i = 0; i < numDigits; i++)
+    rarTime.SubTime[3 - numDigits + i] = ReadByte();
+}
+
+void CInArchive::ReadHeaderReal(CItemEx &item)
+{
+  item.Flags = m_BlockHeader.Flags;
+  item.PackSize = ReadUInt32();
+  item.Size = ReadUInt32();
+  item.HostOS = ReadByte();
+  item.FileCRC = ReadUInt32();
+  item.MTime.DosTime = ReadUInt32();
+  item.UnPackVersion = ReadByte();
+  item.Method = ReadByte();
+  int nameSize = ReadUInt16();
+  item.Attrib = ReadUInt32();
+
+  item.MTime.LowSecond = 0;
+  item.MTime.SubTime[0] =
+      item.MTime.SubTime[1] =
+      item.MTime.SubTime[2] = 0;
+
+  if((item.Flags & NHeader::NFile::kSize64Bits) != 0)
+  {
+    item.PackSize |= ((UInt64)ReadUInt32() << 32);
+    item.Size |= ((UInt64)ReadUInt32() << 32);
+  }
+
+  ReadName(item, nameSize);
+
+  if (item.HasSalt())
+    for (int i = 0; i < sizeof(item.Salt); i++)
+      item.Salt[i] = ReadByte();
+
+  // some rar archives have HasExtTime flag without field.
+  if (m_CurPos < m_PosLimit && item.HasExtTime())
+  {
+    Byte accessMask = (Byte)(ReadByte() >> 4);
+    Byte b = ReadByte();
+    Byte modifMask = (Byte)(b >> 4);
+    Byte createMask = (Byte)(b & 0xF);
+    if ((modifMask & 8) != 0)
+      ReadTime(modifMask, item.MTime);
+    item.CTimeDefined = ((createMask & 8) != 0);
+    if (item.CTimeDefined)
+    {
+      item.CTime.DosTime = ReadUInt32();
+      ReadTime(createMask, item.CTime);
+    }
+    item.ATimeDefined = ((accessMask & 8) != 0);
+    if (item.ATimeDefined)
+    {
+      item.ATime.DosTime = ReadUInt32();
+      ReadTime(accessMask, item.ATime);
+    }
+  }
+
+  UInt16 fileHeaderWithNameSize = (UInt16)m_CurPos;
+  
+  item.Position = m_Position;
+  item.MainPartSize = fileHeaderWithNameSize;
+  item.CommentSize = (UInt16)(m_BlockHeader.HeadSize - fileHeaderWithNameSize);
+
+  if (m_CryptoMode)
+    item.AlignSize = (UInt16)((16 - ((m_BlockHeader.HeadSize) & 0xF)) & 0xF);
+  else
+    item.AlignSize = 0;
+  AddToSeekValue(m_BlockHeader.HeadSize);
+}
+
+void CInArchive::AddToSeekValue(UInt64 addValue)
+{
+  m_Position += addValue;
+}
+
+HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage)
+{
+  decryptionError = false;
+  for (;;)
+  {
+    SeekInArchive(m_Position);
+    if (!m_CryptoMode && (_header.Flags &
+        NHeader::NArchive::kBlockHeadersAreEncrypted) != 0)
+    {
+      m_CryptoMode = false;
+      if (getTextPassword == 0)
+        return S_FALSE;
+      if (!m_RarAES)
+      {
+        m_RarAESSpec = new NCrypto::NRar29::CDecoder;
+        m_RarAES = m_RarAESSpec;
+      }
+      m_RarAESSpec->SetRar350Mode(_header.IsEncryptOld());
+
+      // Salt
+      const UInt32 kSaltSize = 8;
+      Byte salt[kSaltSize];
+      if(!ReadBytesAndTestSize(salt, kSaltSize))
+        return S_FALSE;
+      m_Position += kSaltSize;
+      RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize))
+      // Password
+      CMyComBSTR password;
+      RINOK(getTextPassword->CryptoGetTextPassword(&password))
+      UString unicodePassword(password);
+
+      CByteBuffer buffer;
+      const UInt32 sizeInBytes = unicodePassword.Length() * 2;
+      buffer.SetCapacity(sizeInBytes);
+      for (int i = 0; i < unicodePassword.Length(); i++)
+      {
+        wchar_t c = unicodePassword[i];
+        ((Byte *)buffer)[i * 2] = (Byte)c;
+        ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
+      }
+
+      RINOK(m_RarAESSpec->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
+
+      const UInt32 kDecryptedBufferSize = (1 << 12);
+      if (m_DecryptedData.GetCapacity() == 0)
+      {
+        const UInt32 kAlign = 16;
+        m_DecryptedData.SetCapacity(kDecryptedBufferSize + kAlign);
+        m_DecryptedDataAligned = (Byte *)((ptrdiff_t)((Byte *)m_DecryptedData + kAlign - 1) & ~(ptrdiff_t)(kAlign - 1));
+      }
+      RINOK(m_RarAES->Init());
+      size_t decryptedDataSizeT = kDecryptedBufferSize;
+      RINOK(ReadStream(m_Stream, m_DecryptedDataAligned, &decryptedDataSizeT));
+      m_DecryptedDataSize = (UInt32)decryptedDataSizeT;
+      m_DecryptedDataSize = m_RarAES->Filter(m_DecryptedDataAligned, m_DecryptedDataSize);
+
+      m_CryptoMode = true;
+      m_CryptoPos = 0;
+    }
+
+    m_FileHeaderData.EnsureCapacity(7);
+    size_t processed = 7;
+    RINOK(ReadBytesSpec((Byte *)m_FileHeaderData, &processed));
+    if (processed != 7)
+    {
+      if (processed != 0)
+        errorMessage = k_UnexpectedEnd;
+      return S_FALSE;
+    }
+
+    m_CurData = (Byte *)m_FileHeaderData;
+    m_CurPos = 0;
+    m_PosLimit = 7;
+    m_BlockHeader.CRC = ReadUInt16();
+    m_BlockHeader.Type = ReadByte();
+    m_BlockHeader.Flags = ReadUInt16();
+    m_BlockHeader.HeadSize = ReadUInt16();
+
+    if (m_BlockHeader.HeadSize < 7)
+      ThrowExceptionWithCode(CInArchiveException::kIncorrectArchive);
+
+    if (m_BlockHeader.Type == NHeader::NBlockType::kEndOfArchive)
+      return S_FALSE;
+
+    if (m_BlockHeader.Type == NHeader::NBlockType::kFileHeader)
+    {
+      m_FileHeaderData.EnsureCapacity(m_BlockHeader.HeadSize);
+      m_CurData = (Byte *)m_FileHeaderData;
+      m_PosLimit = m_BlockHeader.HeadSize;
+      if (!ReadBytesAndTestSize(m_CurData + m_CurPos, m_BlockHeader.HeadSize - 7))
+      {
+        errorMessage = k_UnexpectedEnd;
+        return S_FALSE;
+      }
+
+      ReadHeaderReal(item);
+      if ((CrcCalc(m_CurData + 2,
+          m_BlockHeader.HeadSize - item.CommentSize - 2) & 0xFFFF) != m_BlockHeader.CRC)
+        ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError);
+
+      FinishCryptoBlock();
+      m_CryptoMode = false;
+      SeekInArchive(m_Position); // Move Position to compressed Data;
+      AddToSeekValue(item.PackSize);  // m_Position points to next header;
+      return S_OK;
+    }
+    if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 10))
+    {
+      decryptionError = true;
+      errorMessage = k_DecryptionError;
+      return S_FALSE;
+    }
+    if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0)
+    {
+      m_FileHeaderData.EnsureCapacity(7 + 4);
+      m_CurData = (Byte *)m_FileHeaderData;
+      if (!ReadBytesAndTestSize(m_CurData + m_CurPos, 4))
+      {
+        errorMessage = k_UnexpectedEnd;
+        return S_FALSE;
+      }
+      m_PosLimit = 7 + 4;
+      UInt32 dataSize = ReadUInt32();
+      AddToSeekValue(dataSize);
+      if (m_CryptoMode && dataSize > (1 << 27))
+      {
+        decryptionError = true;
+        errorMessage = k_DecryptionError;
+        return S_FALSE;
+      }
+      m_CryptoPos = m_BlockHeader.HeadSize;
+    }
+    else
+      m_CryptoPos = 0;
+    AddToSeekValue(m_BlockHeader.HeadSize);
+    FinishCryptoBlock();
+    m_CryptoMode = false;
+  }
+}
+
+void CInArchive::SeekInArchive(UInt64 position)
+{
+  m_Stream->Seek(position, STREAM_SEEK_SET, NULL);
+}
+
+ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size)
+{
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);
+  SeekInArchive(position);
+  streamSpec->SetStream(m_Stream);
+  streamSpec->Init(size);
+  return inStream.Detach();
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarIn.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarIn.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarIn.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarIn.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,123 @@
+// RarIn.h
+
+#ifndef __ARCHIVE_RAR_IN_H
+#define __ARCHIVE_RAR_IN_H
+
+#include "Common/DynamicBuffer.h"
+#include "Common/MyCom.h"
+
+#include "../../ICoder.h"
+#include "../../IStream.h"
+
+#include "../../Common/StreamObjects.h"
+
+#include "../../Crypto/RarAes.h"
+
+#include "RarHeader.h"
+#include "RarItem.h"
+
+namespace NArchive {
+namespace NRar {
+
+class CInArchiveException
+{
+public:
+  enum CCauseType
+  {
+    kUnexpectedEndOfArchive = 0,
+    kArchiveHeaderCRCError,
+    kFileHeaderCRCError,
+    kIncorrectArchive
+  }
+  Cause;
+  CInArchiveException(CCauseType cause) :   Cause(cause) {}
+};
+
+
+struct CInArchiveInfo
+{
+  UInt32 Flags;
+  Byte EncryptVersion;
+  UInt64 StartPosition;
+  
+  bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; }
+  bool IsCommented() const {  return (Flags & NHeader::NArchive::kComment) != 0; }
+  bool IsVolume() const {  return (Flags & NHeader::NArchive::kVolume) != 0; }
+  bool HaveNewVolumeName() const {  return (Flags & NHeader::NArchive::kNewVolName) != 0; }
+  bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; }
+  bool IsThereEncryptVer() const { return (Flags & NHeader::NArchive::kEncryptVer) != 0; }
+  bool IsEncryptOld() const { return (!IsThereEncryptVer() || EncryptVersion < 36); }
+};
+
+class CInArchive
+{
+  CMyComPtr<IInStream> m_Stream;
+  
+  UInt64 m_StreamStartPosition;
+  
+  CInArchiveInfo _header;
+  CDynamicBuffer<char> m_NameBuffer;
+  CDynamicBuffer<wchar_t> _unicodeNameBuffer;
+
+  CByteBuffer _comment;
+  
+  void ReadName(CItemEx &item, int nameSize);
+  void ReadHeaderReal(CItemEx &item);
+  
+  HRESULT ReadBytesSpec(void *data, size_t *size);
+  bool ReadBytesAndTestSize(void *data, UInt32 size);
+  
+  HRESULT Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
+
+  void ThrowExceptionWithCode(CInArchiveException::CCauseType cause);
+  void ThrowUnexpectedEndOfArchiveException();
+  
+  void AddToSeekValue(UInt64 addValue);
+  
+  CDynamicBuffer<Byte> m_FileHeaderData;
+  
+  NHeader::NBlock::CBlock m_BlockHeader;
+
+  NCrypto::NRar29::CDecoder *m_RarAESSpec;
+  CMyComPtr<ICompressFilter> m_RarAES;
+  
+  Byte *m_CurData; // it must point to start of Rar::Block
+  UInt32 m_CurPos;
+  UInt32 m_PosLimit;
+  Byte ReadByte();
+  UInt16 ReadUInt16();
+  UInt32 ReadUInt32();
+  void ReadTime(Byte mask, CRarTime &rarTime);
+
+  CBuffer<Byte> m_DecryptedData;
+  Byte *m_DecryptedDataAligned;
+  UInt32 m_DecryptedDataSize;
+
+  bool m_CryptoMode;
+  UInt32 m_CryptoPos;
+  void FinishCryptoBlock()
+  {
+    if (m_CryptoMode)
+      while ((m_CryptoPos & 0xF) != 0)
+      {
+        m_CryptoPos++;
+        m_Position++;
+      }
+  }
+
+public:
+  UInt64 m_Position;
+
+  HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit);
+  void Close();
+  HRESULT GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage);
+  
+  void GetArchiveInfo(CInArchiveInfo &archiveInfo) const;
+  
+  void SeekInArchive(UInt64 position);
+  ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size);
+};
+  
+}}
+  
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarItem.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarItem.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarItem.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarItem.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,55 @@
+// RarItem.cpp
+
+#include "StdAfx.h"
+
+#include "RarItem.h"
+
+namespace NArchive{
+namespace NRar{
+
+bool CItem::IgnoreItem() const
+{
+  switch(HostOS)
+  {
+    case NHeader::NFile::kHostMSDOS:
+    case NHeader::NFile::kHostOS2:
+    case NHeader::NFile::kHostWin32:
+      return ((Attrib & NHeader::NFile::kLabelFileAttribute) != 0);
+  }
+  return false;
+}
+
+bool CItem::IsDir() const
+{
+  if (GetDictSize() == NHeader::NFile::kDictDirectoryValue)
+    return true;
+  switch(HostOS)
+  {
+    case NHeader::NFile::kHostMSDOS:
+    case NHeader::NFile::kHostOS2:
+    case NHeader::NFile::kHostWin32:
+      if ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
+        return true;
+  }
+  return false;
+}
+
+UInt32 CItem::GetWinAttributes() const
+{
+  UInt32 winAttributes;
+  switch(HostOS)
+  {
+    case NHeader::NFile::kHostMSDOS:
+    case NHeader::NFile::kHostOS2:
+    case NHeader::NFile::kHostWin32:
+      winAttributes = Attrib;
+      break;
+    default:
+      winAttributes = 0; // must be converted from unix value;
+  }
+  if (IsDir())
+    winAttributes |= NHeader::NFile::kWinFileDirectoryAttributeMask;
+  return winAttributes;
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarItem.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarItem.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarItem.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarItem.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,79 @@
+// RarItem.h
+
+#ifndef __ARCHIVE_RAR_ITEM_H
+#define __ARCHIVE_RAR_ITEM_H
+
+#include "Common/Types.h"
+#include "Common/MyString.h"
+
+#include "RarHeader.h"
+
+namespace NArchive{
+namespace NRar{
+
+struct CRarTime
+{
+  UInt32 DosTime;
+  Byte LowSecond;
+  Byte SubTime[3];
+};
+
+struct CItem
+{
+  UInt64 Size;
+  UInt64 PackSize;
+  
+  CRarTime CTime;
+  CRarTime ATime;
+  CRarTime MTime;
+
+  UInt32 FileCRC;
+  UInt32 Attrib;
+
+  UInt16 Flags;
+  Byte HostOS;
+  Byte UnPackVersion;
+  Byte Method;
+
+  bool CTimeDefined;
+  bool ATimeDefined;
+
+  AString Name;
+  UString UnicodeName;
+
+  Byte Salt[8];
+  
+  bool IsEncrypted()   const { return (Flags & NHeader::NFile::kEncrypted) != 0; }
+  bool IsSolid()       const { return (Flags & NHeader::NFile::kSolid) != 0; }
+  bool IsCommented()   const { return (Flags & NHeader::NFile::kComment) != 0; }
+  bool IsSplitBefore() const { return (Flags & NHeader::NFile::kSplitBefore) != 0; }
+  bool IsSplitAfter()  const { return (Flags & NHeader::NFile::kSplitAfter) != 0; }
+  bool HasSalt()       const { return (Flags & NHeader::NFile::kSalt) != 0; }
+  bool HasExtTime()    const { return (Flags & NHeader::NFile::kExtTime) != 0; }
+  bool HasUnicodeName()const { return (Flags & NHeader::NFile::kUnicodeName) != 0; }
+  bool IsOldVersion()  const { return (Flags & NHeader::NFile::kOldVersion) != 0; }
+  
+  UInt32 GetDictSize() const { return (Flags >> NHeader::NFile::kDictBitStart) & NHeader::NFile::kDictMask; }
+  bool IsDir() const;
+  bool IgnoreItem() const;
+  UInt32 GetWinAttributes() const;
+  
+  CItem(): CTimeDefined(false), ATimeDefined(false) {}
+};
+
+class CItemEx: public CItem
+{
+public:
+  UInt64 Position;
+  UInt16 MainPartSize;
+  UInt16 CommentSize;
+  UInt16 AlignSize;
+  UInt64 GetFullSize()  const { return MainPartSize + CommentSize + AlignSize + PackSize; };
+  //  DWORD GetHeaderWithCommentSize()  const { return MainPartSize + CommentSize; };
+  UInt64 GetCommentPosition() const { return Position + MainPartSize; };
+  UInt64 GetDataPosition()    const { return GetCommentPosition() + CommentSize + AlignSize; };
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarRegister.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarRegister.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarRegister.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarRegister.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,13 @@
+// RarRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterArc.h"
+
+#include "RarHandler.h"
+static IInArchive *CreateArc() { return new NArchive::NRar::CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"Rar", L"rar r00", 0, 3, {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}, 7, false, CreateArc, 0,  };
+
+REGISTER_ARC(Rar)

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,78 @@
+// RarVolumeInStream.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/7zCrc.h"
+
+#include "RarVolumeInStream.h"
+
+namespace NArchive {
+namespace NRar {
+
+void CFolderInStream::Init(
+    CObjectVector<CInArchive> *archives,
+    const CObjectVector<CItemEx> *items,
+    const CRefItem &refItem)
+{
+  _archives = archives;
+  _items = items;
+  _refItem = refItem;
+  _curIndex = 0;
+  CRCs.Clear();
+  _fileIsOpen = false;
+}
+
+HRESULT CFolderInStream::OpenStream()
+{
+  while (_curIndex < _refItem.NumItems)
+  {
+    const CItemEx &item = (*_items)[_refItem.ItemIndex + _curIndex];
+    _stream.Attach((*_archives)[_refItem.VolumeIndex + _curIndex].
+        CreateLimitedStream(item.GetDataPosition(), item.PackSize));
+    _curIndex++;
+    _fileIsOpen = true;
+    _crc = CRC_INIT_VAL;
+    return S_OK;
+  }
+  return S_OK;
+}
+
+HRESULT CFolderInStream::CloseStream()
+{
+  CRCs.Add(CRC_GET_DIGEST(_crc));
+  _stream.Release();
+  _fileIsOpen = false;
+  return S_OK;
+}
+
+STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 realProcessedSize = 0;
+  while ((_curIndex < _refItem.NumItems || _fileIsOpen) && size > 0)
+  {
+    if (_fileIsOpen)
+    {
+      UInt32 localProcessedSize;
+      RINOK(_stream->Read(
+          ((Byte *)data) + realProcessedSize, size, &localProcessedSize));
+      _crc = CrcUpdate(_crc, ((Byte *)data) + realProcessedSize, localProcessedSize);
+      if (localProcessedSize == 0)
+      {
+        RINOK(CloseStream());
+        continue;
+      }
+      realProcessedSize += localProcessedSize;
+      size -= localProcessedSize;
+      break;
+    }
+    else
+    {
+      RINOK(OpenStream());
+    }
+  }
+  if (processedSize != 0)
+    *processedSize = realProcessedSize;
+  return S_OK;
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarVolumeInStream.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarVolumeInStream.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarVolumeInStream.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Rar/RarVolumeInStream.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,49 @@
+// RarVolumeInStream.h
+
+#ifndef __RAR_VOLUME_IN_STREAM_H
+#define __RAR_VOLUME_IN_STREAM_H
+
+#include "../../IStream.h"
+#include "RarIn.h"
+
+namespace NArchive {
+namespace NRar {
+
+struct CRefItem
+{
+  int VolumeIndex;
+  int ItemIndex;
+  int NumItems;
+};
+
+class CFolderInStream:
+  public ISequentialInStream,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+private:
+  CObjectVector<CInArchive> *_archives;
+  const CObjectVector<CItemEx> *_items;
+  CRefItem _refItem;
+  int _curIndex;
+  UInt32 _crc;
+  bool _fileIsOpen;
+  CMyComPtr<ISequentialInStream> _stream;
+
+  HRESULT OpenStream();
+  HRESULT CloseStream();
+public:
+  void Init(CObjectVector<CInArchive> *archives,
+      const CObjectVector<CItemEx> *items,
+      const CRefItem &refItem);
+
+  CRecordVector<UInt32> CRCs;
+};
+  
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/RpmHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/RpmHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/RpmHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/RpmHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,292 @@
+// RpmHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/ComTry.h"
+#include "Common/MyString.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../Common/LimitedStreams.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+
+using namespace NWindows;
+
+#define Get16(p) GetBe16(p)
+#define Get32(p) GetBe32(p)
+
+namespace NArchive {
+namespace NRpm {
+
+/* Reference: lib/signature.h of rpm package */
+#define RPMSIG_NONE         0  /* Do not change! */
+/* The following types are no longer generated */
+#define RPMSIG_PGP262_1024  1  /* No longer generated */ /* 256 byte */
+/* These are the new-style signatures.  They are Header structures.    */
+/* Inside them we can put any number of any type of signature we like. */
+
+#define RPMSIG_HEADERSIG    5  /* New Header style signature */
+
+const UInt32 kLeadSize = 96;
+struct CLead
+{
+  unsigned char Magic[4];
+  unsigned char Major;  // not supported  ver1, only support 2,3 and lator
+  unsigned char Minor;
+  UInt16 Type;
+  UInt16 ArchNum;
+  char Name[66];
+  UInt16 OSNum;
+  UInt16 SignatureType;
+  char Reserved[16];  // pad to 96 bytes -- 8 byte aligned
+  bool MagicCheck() const
+    { return Magic[0] == 0xed && Magic[1] == 0xab && Magic[2] == 0xee && Magic[3] == 0xdb; };
+};
+  
+const UInt32 kEntryInfoSize = 16;
+/*
+struct CEntryInfo
+{
+  int Tag;
+  int Type;
+  int Offset; // Offset from beginning of data segment, only defined on disk
+  int Count;
+};
+*/
+
+// case: SignatureType == RPMSIG_HEADERSIG
+const UInt32 kCSigHeaderSigSize = 16;
+struct CSigHeaderSig
+{
+  unsigned char Magic[4];
+  UInt32 Reserved;
+  UInt32 IndexLen;  // count of index entries
+  UInt32 DataLen;   // number of bytes
+  bool MagicCheck()
+    { return Magic[0] == 0x8e && Magic[1] == 0xad && Magic[2] == 0xe8 && Magic[3] == 0x01; };
+  UInt32 GetLostHeaderLen()
+    { return IndexLen * kEntryInfoSize + DataLen; };
+};
+
+static HRESULT RedSigHeaderSig(IInStream *inStream, CSigHeaderSig &h)
+{
+  char dat[kCSigHeaderSigSize];
+  char *cur = dat;
+  RINOK(ReadStream_FALSE(inStream, dat, kCSigHeaderSigSize));
+  memcpy(h.Magic, cur, 4);
+  cur += 4;
+  cur += 4;
+  h.IndexLen = Get32(cur);
+  cur += 4;
+  h.DataLen = Get32(cur);
+  return S_OK;
+}
+
+HRESULT OpenArchive(IInStream *inStream)
+{
+  UInt64 pos;
+  char leadData[kLeadSize];
+  char *cur = leadData;
+  CLead lead;
+  RINOK(ReadStream_FALSE(inStream, leadData, kLeadSize));
+  memcpy(lead.Magic, cur, 4);
+  cur += 4;
+  lead.Major = *cur++;
+  lead.Minor = *cur++;
+  lead.Type = Get16(cur);
+  cur += 2;
+  lead.ArchNum = Get16(cur);
+  cur += 2;
+  memcpy(lead.Name, cur, sizeof(lead.Name));
+  cur += sizeof(lead.Name);
+  lead.OSNum = Get16(cur);
+  cur += 2;
+  lead.SignatureType = Get16(cur);
+  cur += 2;
+
+  if (!lead.MagicCheck() || lead.Major < 3)
+    return S_FALSE;
+
+  CSigHeaderSig sigHeader, header;
+  if (lead.SignatureType == RPMSIG_NONE)
+  {
+    ;
+  }
+  else if (lead.SignatureType == RPMSIG_PGP262_1024)
+  {
+    UInt64 pos;
+    RINOK(inStream->Seek(256, STREAM_SEEK_CUR, &pos));
+  }
+  else if (lead.SignatureType == RPMSIG_HEADERSIG)
+  {
+    RINOK(RedSigHeaderSig(inStream, sigHeader));
+    if (!sigHeader.MagicCheck())
+      return S_FALSE;
+    UInt32 len = sigHeader.GetLostHeaderLen();
+    RINOK(inStream->Seek(len, STREAM_SEEK_CUR, &pos));
+    if ((pos % 8) != 0)
+    {
+      RINOK(inStream->Seek((pos / 8 + 1) * 8 - pos,
+          STREAM_SEEK_CUR, &pos));
+    }
+  }
+  else
+    return S_FALSE;
+
+  RINOK(RedSigHeaderSig(inStream, header));
+  if (!header.MagicCheck())
+    return S_FALSE;
+  int headerLen = header.GetLostHeaderLen();
+  if (headerLen == -1)
+    return S_FALSE;
+  RINOK(inStream->Seek(headerLen, STREAM_SEEK_CUR, &pos));
+  return S_OK;
+}
+
+class CHandler:
+  public IInArchive,
+  public IInArchiveGetStream,
+  public CMyUnknownImp
+{
+  CMyComPtr<IInStream> _stream;
+  UInt64 _pos;
+  UInt64 _size;
+  Byte _sig[4];
+public:
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+  INTERFACE_IInArchive(;)
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+};
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidSize, VT_UI8}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_NO_Table
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  NCOM::CPropVariant prop;
+  switch(propID) { case kpidMainSubfile: prop = (UInt32)0; break; }
+  prop.Detach(value);
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *inStream,
+    const UInt64 * /* maxCheckStartPosition */,
+    IArchiveOpenCallback * /* openArchiveCallback */)
+{
+  COM_TRY_BEGIN
+  try
+  {
+    Close();
+    if (OpenArchive(inStream) != S_OK)
+      return S_FALSE;
+    RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_pos));
+    RINOK(ReadStream_FALSE(inStream, _sig, sizeof(_sig) / sizeof(_sig[0])));
+    UInt64 endPosition;
+    RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPosition));
+    _size = endPosition - _pos;
+    _stream = inStream;
+    return S_OK;
+  }
+  catch(...) { return S_FALSE; }
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _stream.Release();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = 1;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
+{
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidSize:
+    case kpidPackSize:
+      prop = _size;
+      break;
+    case kpidExtension:
+    {
+      char s[32];
+      MyStringCopy(s, "cpio.");
+      const char *ext;
+      if (_sig[0] == 0x1F && _sig[1] == 0x8B)
+        ext = "gz";
+      else if (_sig[0] == 'B' && _sig[1] == 'Z' && _sig[2] == 'h')
+        ext = "bz2";
+      else
+        ext = "lzma";
+      MyStringCopy(s + MyStringLen(s), ext);
+      prop = s;
+      break;
+    }
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  if (numItems == 0)
+    return S_OK;
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
+    return E_INVALIDARG;
+
+  RINOK(extractCallback->SetTotal(_size));
+  CMyComPtr<ISequentialOutStream> outStream;
+  Int32 askMode = testMode ?
+      NExtract::NAskMode::kTest :
+      NExtract::NAskMode::kExtract;
+  RINOK(extractCallback->GetStream(0, &outStream, askMode));
+  if (!testMode && !outStream)
+    return S_OK;
+  RINOK(extractCallback->PrepareOperation(askMode));
+
+  CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+  
+  RINOK(_stream->Seek(_pos, STREAM_SEEK_SET, NULL));
+  RINOK(copyCoder->Code(_stream, outStream, NULL, NULL, progress));
+  outStream.Release();
+  return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK);
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream)
+{
+  COM_TRY_BEGIN
+  return CreateLimitedInStream(_stream, _pos, _size, stream);
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new NArchive::NRpm::CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"Rpm", L"rpm", 0, 0xEB, { 0xED, 0xAB, 0xEE, 0xDB}, 4, false, CreateArc, 0 };
+
+REGISTER_ARC(Rpm)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/SplitHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/SplitHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/SplitHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/SplitHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,366 @@
+// SplitHandler.cpp
+
+#include "StdAfx.h"
+
+#include "Common/ComTry.h"
+#include "Common/MyString.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+
+#include "../Compress/CopyCoder.h"
+
+#include "Common/MultiStream.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NSplit {
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidSize, VT_UI8}
+};
+
+STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidNumVolumes, VT_UI4}
+};
+
+class CHandler:
+  public IInArchive,
+  public IInArchiveGetStream,
+  public CMyUnknownImp
+{
+  UString _subName;
+  CObjectVector<CMyComPtr<IInStream> > _streams;
+  CRecordVector<UInt64> _sizes;
+  UInt64 _totalSize;
+public:
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+  INTERFACE_IInArchive(;)
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidMainSubfile: prop = (UInt32)0; break;
+    case kpidNumVolumes: prop = (UInt32)_streams.Size(); break;
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+struct CSeqName
+{
+  UString _unchangedPart;
+  UString _changedPart;
+  bool _splitStyle;
+  
+  UString GetNextName()
+  {
+    UString newName;
+    if (_splitStyle)
+    {
+      int i;
+      int numLetters = _changedPart.Length();
+      for (i = numLetters - 1; i >= 0; i--)
+      {
+        wchar_t c = _changedPart[i];
+        if (c == 'z')
+        {
+          c = 'a';
+          newName = c + newName;
+          continue;
+        }
+        else if (c == 'Z')
+        {
+          c = 'A';
+          newName = c + newName;
+          continue;
+        }
+        c++;
+        if ((c == 'z' || c == 'Z') && i == 0)
+        {
+          _unchangedPart += c;
+          wchar_t newChar = (c == 'z') ? L'a' : L'A';
+          newName.Empty();
+          numLetters++;
+          for (int k = 0; k < numLetters; k++)
+            newName += newChar;
+          break;
+        }
+        newName = c + newName;
+        i--;
+        for (; i >= 0; i--)
+          newName = _changedPart[i] + newName;
+        break;
+      }
+    }
+    else
+    {
+      int i;
+      int numLetters = _changedPart.Length();
+      for (i = numLetters - 1; i >= 0; i--)
+      {
+        wchar_t c = _changedPart[i];
+        if (c == L'9')
+        {
+          c = L'0';
+          newName = c + newName;
+          if (i == 0)
+            newName = UString(L'1') + newName;
+          continue;
+        }
+        c++;
+        newName = c + newName;
+        i--;
+        for (; i >= 0; i--)
+          newName = _changedPart[i] + newName;
+        break;
+      }
+    }
+    _changedPart = newName;
+    return _unchangedPart + _changedPart;
+  }
+};
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+    const UInt64 * /* maxCheckStartPosition */,
+    IArchiveOpenCallback *openArchiveCallback)
+{
+  COM_TRY_BEGIN
+  Close();
+  if (openArchiveCallback == 0)
+    return S_FALSE;
+  // try
+  {
+    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
+    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback;
+    if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback,
+        &openVolumeCallback) != S_OK)
+      return S_FALSE;
+    
+    UString name;
+    {
+      NCOM::CPropVariant prop;
+      RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
+      if (prop.vt != VT_BSTR)
+        return S_FALSE;
+      name = prop.bstrVal;
+    }
+    
+    int dotPos = name.ReverseFind('.');
+    UString prefix, ext;
+    if (dotPos >= 0)
+    {
+      prefix = name.Left(dotPos + 1);
+      ext = name.Mid(dotPos + 1);
+    }
+    else
+      ext = name;
+    UString extBig = ext;
+    extBig.MakeUpper();
+
+    CSeqName seqName;
+
+    int numLetters = 2;
+    bool splitStyle = false;
+    if (extBig.Right(2) == L"AA")
+    {
+      splitStyle = true;
+      while (numLetters < extBig.Length())
+      {
+        if (extBig[extBig.Length() - numLetters - 1] != 'A')
+          break;
+        numLetters++;
+      }
+    }
+    else if (ext.Right(2) == L"01")
+    {
+      while (numLetters < extBig.Length())
+      {
+        if (extBig[extBig.Length() - numLetters - 1] != '0')
+          break;
+        numLetters++;
+      }
+      if (numLetters != ext.Length())
+        return S_FALSE;
+    }
+    else
+      return S_FALSE;
+
+    _streams.Add(stream);
+
+    seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters);
+    seqName._changedPart = ext.Right(numLetters);
+    seqName._splitStyle = splitStyle;
+
+    if (prefix.Length() < 1)
+      _subName = L"file";
+    else
+      _subName = prefix.Left(prefix.Length() - 1);
+
+    _totalSize = 0;
+    UInt64 size;
+    {
+      NCOM::CPropVariant prop;
+      RINOK(openVolumeCallback->GetProperty(kpidSize, &prop));
+      if (prop.vt != VT_UI8)
+        return E_INVALIDARG;
+      size = prop.uhVal.QuadPart;
+    }
+    _totalSize += size;
+    _sizes.Add(size);
+    
+    if (openArchiveCallback != NULL)
+    {
+      UInt64 numFiles = _streams.Size();
+      RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
+    }
+
+    for (;;)
+    {
+      UString fullName = seqName.GetNextName();
+      CMyComPtr<IInStream> nextStream;
+      HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);
+      if (result == S_FALSE)
+        break;
+      if (result != S_OK)
+        return result;
+      if (!stream)
+        break;
+      {
+        NCOM::CPropVariant prop;
+        RINOK(openVolumeCallback->GetProperty(kpidSize, &prop));
+        if (prop.vt != VT_UI8)
+          return E_INVALIDARG;
+        size = prop.uhVal.QuadPart;
+      }
+      _totalSize += size;
+      _sizes.Add(size);
+      _streams.Add(nextStream);
+      if (openArchiveCallback != NULL)
+      {
+        UInt64 numFiles = _streams.Size();
+        RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
+      }
+    }
+  }
+  /*
+  catch(...)
+  {
+    return S_FALSE;
+  }
+  */
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _sizes.Clear();
+  _streams.Clear();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _streams.IsEmpty() ? 0 : 1;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
+{
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidPath: prop = _subName; break;
+    case kpidSize:
+    case kpidPackSize:
+      prop = _totalSize;
+      break;
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  if (numItems == 0)
+    return S_OK;
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
+    return E_INVALIDARG;
+
+  UInt64 currentTotalSize = 0;
+  RINOK(extractCallback->SetTotal(_totalSize));
+  CMyComPtr<ISequentialOutStream> outStream;
+  Int32 askMode = testMode ?
+      NExtract::NAskMode::kTest :
+      NExtract::NAskMode::kExtract;
+  RINOK(extractCallback->GetStream(0, &outStream, askMode));
+  if (!testMode && !outStream)
+    return S_OK;
+  RINOK(extractCallback->PrepareOperation(askMode));
+  
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  for (int i = 0; i < _streams.Size(); i++)
+  {
+    lps->InSize = lps->OutSize = currentTotalSize;
+    RINOK(lps->SetCur());
+    IInStream *inStream = _streams[i];
+    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
+    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
+    currentTotalSize += copyCoderSpec->TotalSize;
+  }
+  outStream.Release();
+  return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK);
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+  COM_TRY_BEGIN
+  if (index != 0)
+    return E_INVALIDARG;
+  *stream = 0;
+  CMultiStream *streamSpec = new CMultiStream;
+  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
+  for (int i = 0; i < _streams.Size(); i++)
+  {
+    CMultiStream::CSubStreamInfo subStreamInfo;
+    subStreamInfo.Stream = _streams[i];
+    subStreamInfo.Size = _sizes[i];
+    streamSpec->Streams.Add(subStreamInfo);
+  }
+  streamSpec->Init();
+  *stream = streamTemp.Detach();
+  return S_OK;
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+{ L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 };
+
+REGISTER_ARC(Split)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/SquashfsHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/SquashfsHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/SquashfsHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/SquashfsHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,2155 @@
+// SquashfsHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/7zCrc.h"
+#include "../../../C/Alloc.h"
+#include "../../../C/CpuArch.h"
+
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/PropVariantUtils.h"
+#include "Windows/Time.h"
+
+#include "../Common/LimitedStreams.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamObjects.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+#include "../Compress/ZlibDecoder.h"
+#include "../Compress/LzmaDecoder.h"
+
+namespace NArchive {
+namespace NSquashfs {
+
+static const UInt32 kNumFilesMax = (1 << 28);
+static const unsigned kNumDirLevelsMax = (1 << 10);
+
+// Layout: Header, Data, inodes, Directories, Fragments, UIDs, GIDs
+
+/*
+#define Get16(p) (be ? GetBe16(p) : GetUi16(p))
+#define Get32(p) (be ? GetBe32(p) : GetUi32(p))
+#define Get64(p) (be ? GetBe64(p) : GetUi64(p))
+*/
+
+UInt16 Get16b(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); }
+UInt32 Get32b(const Byte *p, bool be) { return be ? GetBe32(p) : GetUi32(p); }
+UInt64 Get64b(const Byte *p, bool be) { return be ? GetBe64(p) : GetUi64(p); }
+
+#define Get16(p) Get16b(p, be)
+#define Get32(p) Get32b(p, be)
+#define Get64(p) Get64b(p, be)
+
+#define LE_16(offs, dest) dest = GetUi16(p + (offs));
+#define LE_32(offs, dest) dest = GetUi32(p + (offs));
+#define LE_64(offs, dest) dest = GetUi64(p + (offs));
+
+#define GET_16(offs, dest) dest = Get16(p + (offs));
+#define GET_32(offs, dest) dest = Get32(p + (offs));
+#define GET_64(offs, dest) dest = Get64(p + (offs));
+
+static const UInt32 kSignatureSize = 4;
+#define SIGNATURE { 'h', 's', 'q', 's' }
+static const UInt32 kSignature32_LE = 0x73717368;
+static const UInt32 kSignature32_BE = 0x68737173;
+static const UInt32 kSignature32_LZ = 0x71736873;
+
+#define kMethod_ZLIB 1
+#define kMethod_LZMA 2
+#define kMethod_LZO  3
+
+static const char *k_Methods[] =
+{
+  "Unknown",
+  "ZLIB",
+  "LZMA",
+  "LZO"
+};
+
+static const UInt32 kMetadataBlockSizeLog = 13;
+static const UInt32 kMetadataBlockSize = (1 << kMetadataBlockSizeLog);
+
+#define MY_S_IFIFO  0x1000
+#define MY_S_IFCHR  0x2000
+#define MY_S_IFDIR  0x4000
+#define MY_S_IFBLK  0x6000
+#define MY_S_IFREG  0x8000
+#define MY_S_IFLNK  0xA000
+#define MY_S_IFSOCK 0xC000
+
+enum
+{
+  kType_IPC,
+  kType_DIR,
+  kType_FILE,
+  kType_LNK,
+  kType_BLK,
+  kType_CHR,
+  kType_FIFO,
+  kType_SOCK
+};
+
+static const UInt32 k_TypeToMode[] =
+{
+  0,
+  MY_S_IFDIR, MY_S_IFREG, MY_S_IFLNK, MY_S_IFBLK, MY_S_IFCHR, MY_S_IFIFO, MY_S_IFSOCK,
+  MY_S_IFDIR, MY_S_IFREG, MY_S_IFLNK, MY_S_IFBLK, MY_S_IFCHR, MY_S_IFIFO, MY_S_IFSOCK
+};
+
+
+enum
+{
+  kFlag_UNC_INODES,
+  kFlag_UNC_DATA,
+  kFlag_CHECK,
+  kFlag_UNC_FRAGS,
+  kFlag_NO_FRAGS,
+  kFlag_ALWAYS_FRAG,
+  kFlag_DUPLICATE,
+  kFlag_EXPORT
+};
+
+static const CUInt32PCharPair k_Flags[] =
+{
+  { kFlag_UNC_INODES, "UNCOMPRESSED_INODES" },
+  { kFlag_UNC_DATA, "UNCOMPRESSED_DATA" },
+  { kFlag_CHECK, "CHECK" },
+  { kFlag_UNC_FRAGS, "UNCOMPRESSED_FRAGMENTS" },
+  { kFlag_NO_FRAGS, "NO_FRAGMENTS" },
+  { kFlag_ALWAYS_FRAG, "ALWAYS_FRAGMENTS" },
+  { kFlag_DUPLICATE, "DUPLICATES_REMOVED" },
+  { kFlag_EXPORT, "EXPORTABLE" }
+};
+
+static const UInt32 kNotCompressedBit16 = (1 << 15);
+static const UInt32 kNotCompressedBit32 = (1 << 24);
+
+#define GET_COMPRESSED_BLOCK_SIZE(size) ((size) & ~kNotCompressedBit32)
+#define IS_COMPRESSED_BLOCK(size) (((size) & kNotCompressedBit32) == 0)
+
+static const UInt32 kHeaderSize1 = 0x33;
+static const UInt32 kHeaderSize2 = 0x3F;
+static const UInt32 kHeaderSize3 = 0x77;
+static const UInt32 kHeaderSize4 = 0x60;
+
+struct CHeader
+{
+  bool be;
+  bool SeveralMethods;
+  Byte NumUids;
+  Byte NumGids;
+
+  UInt32 NumInodes;
+  UInt32 CTime;
+  UInt32 BlockSize;
+  UInt32 NumFrags;
+  UInt16 Method;
+  UInt16 BlockSizeLog;
+  UInt16 Flags;
+  UInt16 NumIDs;
+  UInt16 Major;
+  UInt16 Minor;
+  UInt64 RootInode;
+  UInt64 Size;
+  UInt64 UidTable;
+  UInt64 GidTable;
+  UInt64 XattrIdTable;
+  UInt64 InodeTable;
+  UInt64 DirTable;
+  UInt64 FragTable;
+  UInt64 LookupTable;
+
+  void Parse3(const Byte *p)
+  {
+    Method = kMethod_ZLIB;
+    GET_32 (0x08, Size);
+    GET_32 (0x0C, UidTable);
+    GET_32 (0x10, GidTable);
+    GET_32 (0x14, InodeTable);
+    GET_32 (0x18, DirTable);
+    GET_16 (0x20, BlockSize);
+    GET_16 (0x22, BlockSizeLog);
+    Flags   = p[0x24];
+    NumUids = p[0x25];
+    NumGids = p[0x26];
+    GET_32 (0x27, CTime);
+    GET_64 (0x2B, RootInode);
+    NumFrags = 0;
+    FragTable = UidTable;
+
+    if (Major >= 2)
+    {
+      GET_32 (0x33, BlockSize);
+      GET_32 (0x37, NumFrags);
+      GET_32 (0x3B, FragTable);
+      if (Major == 3)
+      {
+        GET_64 (0x3F, Size);
+        GET_64 (0x47, UidTable);
+        GET_64 (0x4F, GidTable);
+        GET_64 (0x57, InodeTable);
+        GET_64 (0x5F, DirTable);
+        GET_64 (0x67, FragTable);
+        GET_64 (0x6F, LookupTable);
+      }
+    }
+  }
+
+  void Parse4(const Byte *p)
+  {
+    LE_32 (0x08, CTime);
+    LE_32 (0x0C, BlockSize);
+    LE_32 (0x10, NumFrags);
+    LE_16 (0x14, Method);
+    LE_16 (0x16, BlockSizeLog);
+    LE_16 (0x18, Flags);
+    LE_16 (0x1A, NumIDs);
+    LE_64 (0x20, RootInode);
+    LE_64 (0x28, Size);
+    LE_64 (0x30, UidTable);
+    LE_64 (0x38, XattrIdTable);
+    LE_64 (0x40, InodeTable);
+    LE_64 (0x48, DirTable);
+    LE_64 (0x50, FragTable);
+    LE_64 (0x58, LookupTable);
+    GidTable = 0;
+  }
+
+  bool Parse(const Byte *p)
+  {
+    be = false;
+    SeveralMethods = false;
+    switch (GetUi32(p))
+    {
+      case kSignature32_LE: break;
+      case kSignature32_BE: be = true; break;
+      case kSignature32_LZ: SeveralMethods = true; break;
+      default: return false;
+    }
+    GET_32 (4, NumInodes);
+    GET_16 (0x1C, Major);
+    GET_16 (0x1E, Minor);
+    if (Major <= 3)
+      Parse3(p);
+    else
+    {
+      if (be)
+        return false;
+      Parse4(p);
+    }
+    return
+      InodeTable < DirTable &&
+      DirTable <= FragTable &&
+      FragTable <= Size &&
+      UidTable <= Size &&
+      BlockSizeLog >= 12 &&
+      BlockSizeLog < 31 &&
+      BlockSize == ((UInt32)1 << BlockSizeLog);
+  }
+
+  bool IsSupported() const { return Major > 0 && Major <= 4 && BlockSizeLog <= 23; }
+  bool IsOldVersion() const { return Major < 4; }
+  bool NeedCheckData() const { return (Flags & (1 << kFlag_CHECK)) != 0; }
+  unsigned GetFileNameOffset() const { return Major <= 2 ? 3 : (Major == 3 ? 5 : 8); }
+  unsigned GetSymLinkOffset() const { return Major <= 1 ? 5: (Major <= 2 ? 6: (Major == 3 ? 18 : 24)); }
+  unsigned GetSpecGuidIndex() const { return Major <= 1 ? 0xF: 0xFF; }
+};
+
+static const UInt32 kFrag_Empty = (UInt32)(Int32)-1;
+// static const UInt32 kXattr_Empty = (UInt32)(Int32)-1;
+
+struct CNode
+{
+  UInt16 Type;
+  UInt16 Mode;
+  UInt16 Uid;
+  UInt16 Gid;
+  UInt32 Frag;
+  UInt32 Offset;
+  // UInt32 MTime;
+  // UInt32 Number;
+  // UInt32 NumLinks;
+  // UInt32 RDev;
+  // UInt32 Xattr;
+  // UInt32 Parent;
+  
+  UInt64 FileSize;
+  UInt64 StartBlock;
+  // UInt64 Sparse;
+  
+  UInt32 Parse1(const Byte *p, UInt32 size, const CHeader &_h);
+  UInt32 Parse2(const Byte *p, UInt32 size, const CHeader &_h);
+  UInt32 Parse3(const Byte *p, UInt32 size, const CHeader &_h);
+  UInt32 Parse4(const Byte *p, UInt32 size, const CHeader &_h);
+  
+  bool IsDir() const { return (Type == kType_DIR || Type == kType_DIR + 7); }
+  bool IsLink() const { return (Type == kType_LNK || Type == kType_LNK + 7); }
+  UInt64 GetSize() const { return IsDir() ? 0 : FileSize; }
+  
+  bool ThereAreFrags() const { return Frag != kFrag_Empty; }
+  UInt64 GetNumBlocks(const CHeader &_h) const
+  {
+    return (FileSize >> _h.BlockSizeLog) +
+      (!ThereAreFrags() && (FileSize & (_h.BlockSize - 1)) != 0);
+  }
+};
+
+UInt32 CNode::Parse1(const Byte *p, UInt32 size, const CHeader &_h)
+{
+  bool be = _h.be;
+  if (size < 4)
+    return 0;
+  UInt16 t = Get16(p);
+  if (be)
+  {
+    Type = t >> 12;
+    Mode = t & 0xFFF;
+    Uid = p[2] >> 4;
+    Gid = p[2] & 0xF;
+  }
+  else
+  {
+    Type = t & 0xF;
+    Mode = t >> 4;
+    Uid = p[2] & 0xF;
+    Gid = p[2] >> 4;
+  }
+
+  // Xattr = kXattr_Empty;
+  // MTime = 0;
+  FileSize = 0;
+  StartBlock = 0;
+  Frag = kFrag_Empty;
+
+  if (Type == 0)
+  {
+    Byte t = p[3];
+    if (be)
+    {
+      Type = t >> 4;
+      Offset = t & 0xF;
+    }
+    else
+    {
+      Type = t & 0xF;
+      Offset = t >> 4;
+    }
+    return (Type == kType_FIFO || Type == kType_SOCK) ? 4 : 0;
+  }
+
+  Type--;
+  Uid += (Type / 5) * 16;
+  Type = (Type % 5) + 1;
+
+  if (Type == kType_FILE)
+  {
+    if (size < 15)
+      return 0;
+    // GET_32 (3, MTime);
+    GET_32 (7, StartBlock);
+    UInt32 t;
+    GET_32 (11, t);
+    FileSize = t;
+    UInt32 numBlocks = t >> _h.BlockSizeLog;
+    if ((t & (_h.BlockSize - 1)) != 0)
+      numBlocks++;
+    UInt32 pos = numBlocks * 2 + 15;
+    return (pos <= size) ? pos : 0;
+  }
+  
+  if (Type == kType_DIR)
+  {
+    if (size < 14)
+      return 0;
+    UInt32 t = Get32(p + 3);
+    if (be)
+    {
+      FileSize = t >> 13;
+      Offset = t & 0x1FFF;
+    }
+    else
+    {
+      FileSize = t & 0x7FFFF;
+      Offset = t >> 19;
+    }
+    // GET_32 (7, MTime);
+    GET_32 (10, StartBlock);
+    if (be)
+      StartBlock &= 0xFFFFFF;
+    else
+      StartBlock >>= 8;
+    return 14;
+  }
+  
+  if (size < 5)
+    return 0;
+
+  if (Type == kType_LNK)
+  {
+    UInt32 len;
+    GET_16 (3, len);
+    FileSize = len;
+    len += 5;
+    return (len <= size) ? len : 0;
+  }
+
+  // GET_32 (3, RDev);
+  return 5;
+}
+
+UInt32 CNode::Parse2(const Byte *p, UInt32 size, const CHeader &_h)
+{
+  bool be = _h.be;
+  if (size < 4)
+    return 0;
+  UInt16 t = Get16(p);
+  if (be)
+  {
+    Type = t >> 12;
+    Mode = t & 0xFFF;
+  }
+  else
+  {
+    Type = t & 0xF;
+    Mode = t >> 4;
+  }
+  Uid = p[2];
+  Gid = p[3];
+
+  // Xattr = kXattr_Empty;
+
+  if (Type == kType_FILE)
+  {
+    if (size < 24)
+      return 0;
+    // GET_32 (4, MTime);
+    GET_32 (8, StartBlock);
+    GET_32 (12, Frag);
+    GET_32 (16, Offset);
+    UInt32 t;
+    GET_32 (20, t);
+    FileSize = t;
+    UInt32 numBlocks = t >> _h.BlockSizeLog;
+    if (!ThereAreFrags() && (t & (_h.BlockSize - 1)) != 0)
+      numBlocks++;
+    UInt32 pos = numBlocks * 4 + 24;
+    return (pos <= size) ? (UInt32)pos : 0;
+  }
+
+  FileSize = 0;
+  // MTime = 0;
+  StartBlock = 0;
+  Frag = kFrag_Empty;
+  
+  if (Type == kType_DIR)
+  {
+    if (size < 15)
+      return 0;
+    UInt32 t = Get32(p + 4);
+    if (be)
+    {
+      FileSize = t >> 13;
+      Offset = t & 0x1FFF;
+    }
+    else
+    {
+      FileSize = t & 0x7FFFF;
+      Offset = t >> 19;
+    }
+    // GET_32 (8, MTime);
+    GET_32 (11, StartBlock);
+    if (be)
+      StartBlock &= 0xFFFFFF;
+    else
+      StartBlock >>= 8;
+    return 15;
+  }
+  
+  if (Type == kType_DIR + 7)
+  {
+    if (size < 18)
+      return 0;
+    UInt32 t = Get32(p + 4);
+    UInt32 t2 = Get16(p + 7);
+    if (be)
+    {
+      FileSize = t >> 5;
+      Offset = t2 & 0x1FFF;
+    }
+    else
+    {
+      FileSize = t & 0x7FFFFFF;
+      Offset = t2 >> 3;
+    }
+    // GET_32 (9, MTime);
+    GET_32 (12, StartBlock);
+    if (be)
+      StartBlock &= 0xFFFFFF;
+    else
+      StartBlock >>= 8;
+    UInt32 iCount;
+    GET_16 (16, iCount);
+    UInt32 pos = 18;
+    for (UInt32 i = 0; i < iCount; i++)
+    {
+      // 27 bits: index
+      // 29 bits: startBlock
+      if (pos + 8 > size)
+        return 0;
+      pos += 8 + (UInt32)p[pos + 7] + 1; // nameSize
+      if (pos > size)
+        return 0;
+    }
+    return pos;
+  }
+
+  if (Type == kType_FIFO || Type == kType_SOCK)
+    return 4;
+
+  if (size < 6)
+    return 0;
+  
+  if (Type == kType_LNK)
+  {
+    UInt32 len;
+    GET_16 (4, len);
+    FileSize = len;
+    len += 6;
+    return (len <= size) ? len : 0;
+  }
+  
+  if (Type == kType_BLK || Type == kType_CHR)
+  {
+    // GET_16 (4, RDev);
+    return 6;
+  }
+  
+  return 0;
+}
+
+UInt32 CNode::Parse3(const Byte *p, UInt32 size, const CHeader &_h)
+{
+  bool be = _h.be;
+  if (size < 12)
+    return 0;
+  UInt16 t = Get16(p);
+  if (be)
+  {
+    Type = t >> 12;
+    Mode = t & 0xFFF;
+  }
+  else
+  {
+    Type = t & 0xF;
+    Mode = t >> 4;
+  }
+  Uid = p[2];
+  Gid = p[3];
+  // GET_32 (4, MTime);
+  // GET_32 (8, Number);
+  // Xattr = kXattr_Empty;
+  FileSize = 0;
+  StartBlock = 0;
+  
+  if (Type == kType_FILE || Type == kType_FILE + 7)
+  {
+    UInt32 offset;
+    if (Type == kType_FILE)
+    {
+      if (size < 32)
+        return 0;
+      GET_64 (12, StartBlock);
+      GET_32 (20, Frag);
+      GET_32 (24, Offset);
+      GET_32 (28, FileSize);
+      offset = 32;
+    }
+    else
+    {
+      if (size < 40)
+        return 0;
+      // GET_32 (12, NumLinks);
+      GET_64 (16, StartBlock);
+      GET_32 (24, Frag);
+      GET_32 (28, Offset);
+      GET_64 (32, FileSize);
+      offset = 40;
+    }
+    UInt64 pos = GetNumBlocks(_h) * 4 + offset;
+    return (pos <= size) ? (UInt32)pos : 0;
+  }
+
+  if (size < 16)
+    return 0;
+  // GET_32 (12, NumLinks);
+ 
+  if (Type == kType_DIR)
+  {
+    if (size < 28)
+      return 0;
+    UInt32 t = Get32(p + 16);
+    if (be)
+    {
+      FileSize = t >> 13;
+      Offset = t & 0x1FFF;
+    }
+    else
+    {
+      FileSize = t & 0x7FFFF;
+      Offset = t >> 19;
+    }
+    GET_32 (20, StartBlock);
+    // GET_32 (24, Parent);
+    return 28;
+  }
+  
+  if (Type == kType_DIR + 7)
+  {
+    if (size < 31)
+      return 0;
+    UInt32 t = Get32(p + 16);
+    UInt32 t2 = Get16(p + 19);
+    if (be)
+    {
+      FileSize = t >> 5;
+      Offset = t2 & 0x1FFF;
+    }
+    else
+    {
+      FileSize = t & 0x7FFFFFF;
+      Offset = t2 >> 3;
+    }
+    GET_32 (21, StartBlock);
+    UInt32 iCount;
+    GET_16 (25, iCount);
+    // GET_32 (27, Parent);
+    UInt32 pos = 31;
+    for (UInt32 i = 0; i < iCount; i++)
+    {
+      // UInt32 index
+      // UInt32 startBlock
+      if (pos + 9 > size)
+        return 0;
+      pos += 9 + (unsigned)p[pos + 8] + 1; // nameSize
+      if (pos > size)
+        return 0;
+    }
+    return pos;
+  }
+
+  if (Type == kType_FIFO || Type == kType_SOCK)
+    return 16;
+  
+  if (size < 18)
+    return 0;
+  if (Type == kType_LNK)
+  {
+    UInt32 len;
+    GET_16 (16, len);
+    FileSize = len;
+    len += 18;
+    return (len <= size) ? len : 0;
+  }
+
+  if (Type == kType_BLK || Type == kType_CHR)
+  {
+    // GET_16 (16, RDev);
+    return 18;
+  }
+  
+  return 0;
+}
+
+UInt32 CNode::Parse4(const Byte *p, UInt32 size, const CHeader &_h)
+{
+  if (size < 20)
+    return 0;
+  LE_16 (0, Type);
+  LE_16 (2, Mode);
+  LE_16 (4, Uid);
+  LE_16 (6, Gid);
+  // LE_32 (8, MTime);
+  // LE_32 (12, Number);
+  
+  // Xattr = kXattr_Empty;
+  FileSize = 0;
+  StartBlock = 0;
+  
+  if (Type == kType_FILE || Type == kType_FILE + 7)
+  {
+    UInt32 offset;
+    if (Type == kType_FILE)
+    {
+      if (size < 32)
+        return 0;
+      LE_32 (16, StartBlock);
+      LE_32 (20, Frag);
+      LE_32 (24, Offset);
+      LE_32 (28, FileSize);
+      offset = 32;
+    }
+    else
+    {
+      if (size < 56)
+        return 0;
+      LE_64 (16, StartBlock);
+      LE_64 (24, FileSize);
+      // LE_64 (32, Sparse);
+      // LE_32 (40, NumLinks);
+      LE_32 (44, Frag);
+      LE_32 (48, Offset);
+      // LE_32 (52, Xattr);
+      offset = 56;
+    }
+    UInt64 pos = GetNumBlocks(_h) * 4 + offset;
+    return (pos <= size) ? (UInt32)pos : 0;
+  }
+  
+  if (Type == kType_DIR)
+  {
+    if (size < 32)
+      return 0;
+    LE_32 (16, StartBlock);
+    // LE_32 (20, NumLinks);
+    LE_16 (24, FileSize);
+    LE_16 (26, Offset);
+    // LE_32 (28, Parent);
+    return 32;
+  }
+  
+  // LE_32 (16, NumLinks);
+
+  if (Type == kType_DIR + 7)
+  {
+    if (size < 40)
+      return 0;
+    LE_32 (20, FileSize);
+    LE_32 (24, StartBlock);
+    // LE_32 (28, Parent);
+    UInt32 iCount;
+    LE_16 (32, iCount);
+    LE_16 (34, Offset);
+    // LE_32 (36, Xattr);
+
+    UInt32 pos = 40;
+    for (UInt32 i = 0; i < iCount; i++)
+    {
+      // UInt32 index
+      // UInt32 startBlock
+      if (pos + 12 > size)
+        return 0;
+      UInt32 nameLen = GetUi32(p + pos + 8);
+      pos += 12 + nameLen + 1;
+      if (pos > size || nameLen > (1 << 10))
+        return 0;
+    }
+    return pos;
+  }
+  
+  unsigned offset = 20;
+  switch(Type)
+  {
+    case kType_FIFO: case kType_FIFO + 7:
+    case kType_SOCK: case kType_SOCK + 7:
+      break;
+    case kType_LNK: case kType_LNK + 7:
+    {
+      if (size < 24)
+        return 0;
+      UInt32 len;
+      LE_32 (20, len);
+      FileSize = len;
+      offset = len + 24;
+      if (size < offset || len > (1 << 30))
+        return 0;
+      break;
+    }
+    case kType_BLK: case kType_BLK + 7:
+    case kType_CHR: case kType_CHR + 7:
+      if (size < 24)
+        return 0;
+      // LE_32 (20, RDev);
+      offset = 24;
+      break;
+    default:
+      return 0;
+  }
+  
+  if (Type >= 8)
+  {
+    if (size < offset + 4)
+      return 0;
+    // LE_32 (offset, Xattr);
+    offset += 4;
+  }
+  return offset;
+}
+
+struct CItem
+{
+  int Node;
+  int Parent;
+  UInt32 Ptr;
+};
+
+struct CData
+{
+  CByteBuffer Data;
+  CRecordVector<UInt32> PackPos;
+  CRecordVector<UInt32> UnpackPos; // additional item at the end contains TotalUnpackSize
+  
+  UInt32 GetNumBlocks() const { return PackPos.Size(); }
+  void Clear()
+  {
+    Data.Free();
+    PackPos.Clear();
+    UnpackPos.Clear();
+  }
+};
+
+struct CFrag
+{
+  UInt64 StartBlock;
+  UInt32 Size;
+};
+
+class CHandler:
+  public IInArchive,
+  public IInArchiveGetStream,
+  public CMyUnknownImp
+{
+  CRecordVector<CItem> _items;
+  CRecordVector<CNode> _nodes;
+  CRecordVector<UInt32> _nodesPos;
+  CRecordVector<UInt32> _blockToNode;
+  CData _inodesData;
+  CData _dirs;
+  CRecordVector<CFrag> _frags;
+  // CByteBuffer _uids;
+  // CByteBuffer _gids;
+  CHeader _h;
+
+  CMyComPtr<IInStream> _stream;
+  UInt64 _sizeCalculated;
+
+  IArchiveOpenCallback *_openCallback;
+
+  int _nodeIndex;
+  CRecordVector<bool> _blockCompressed;
+  CRecordVector<UInt64> _blockOffsets;
+  
+  CByteBuffer _cachedBlock;
+  UInt64 _cachedBlockStartPos;
+  UInt32 _cachedPackBlockSize;
+  UInt32 _cachedUnpackBlockSize;
+
+  CLimitedSequentialInStream *_limitedInStreamSpec;
+  CMyComPtr<ISequentialInStream> _limitedInStream;
+
+  CBufPtrSeqOutStream *_outStreamSpec;
+  CMyComPtr<ISequentialOutStream> _outStream;
+
+  NCompress::NLzma::CDecoder *_lzmaDecoderSpec;
+  CMyComPtr<ICompressCoder> _lzmaDecoder;
+
+  NCompress::NZlib::CDecoder *_zlibDecoderSpec;
+  CMyComPtr<ICompressCoder> _zlibDecoder;
+  
+  CByteBuffer _inputBuffer;
+
+  CDynBufSeqOutStream *_dynOutStreamSpec;
+  CMyComPtr<ISequentialOutStream> _dynOutStream;
+
+  void ClearCache()
+  {
+    _cachedBlockStartPos = 0;
+    _cachedPackBlockSize = 0;
+    _cachedUnpackBlockSize = 0;
+  }
+
+  HRESULT Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool *outBufWasWritten, UInt32 *outBufWasWrittenSize,
+      UInt32 inSize, UInt32 outSizeMax);
+  HRESULT ReadMetadataBlock(UInt32 &packSize);
+  HRESULT ReadData(CData &data, UInt64 start, UInt64 end);
+
+  HRESULT OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned level, int &nodeIndex);
+  HRESULT ScanInodes(UInt64 ptr);
+  // HRESULT ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids);
+  HRESULT Open2(IInStream *inStream);
+  AString GetPath(int index) const;
+  bool GetPackSize(int index, UInt64 &res, bool fillOffsets);
+
+public:
+  CHandler();
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+  INTERFACE_IInArchive(;)
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+
+  HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);
+};
+
+CHandler::CHandler()
+{
+  _limitedInStreamSpec = new CLimitedSequentialInStream;
+  _limitedInStream = _limitedInStreamSpec;
+
+  _outStreamSpec = new CBufPtrSeqOutStream();
+  _outStream = _outStreamSpec;
+
+  _dynOutStreamSpec = new CDynBufSeqOutStream;
+  _dynOutStream = _dynOutStreamSpec;
+}
+
+static const STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidIsDir, VT_BOOL},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMTime, VT_FILETIME},
+  { NULL, kpidPosixAttrib, VT_UI4}
+  // { NULL, kpidUser, VT_BSTR},
+  // { NULL, kpidGroup, VT_BSTR},
+  // { NULL, kpidLinks, VT_UI4},
+  // { NULL, kpidOffset, VT_UI4}
+};
+
+static const STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidFileSystem, VT_BSTR},
+  { NULL, kpidMethod, VT_BSTR},
+  { NULL, kpidBlock, VT_UI4},
+  { NULL, kpidPhySize, VT_UI8},
+  { NULL, kpidHeadersSize, VT_UI8},
+  { NULL, kpidBigEndian, VT_BOOL},
+  { NULL, kpidCTime, VT_FILETIME},
+  { NULL, kpidCharacts, VT_BSTR}
+  // { NULL, kpidNumBlocks, VT_UI4}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+static HRESULT LzoDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen)
+{
+  SizeT destRem = *destLen;
+  SizeT srcRem = *srcLen;
+  *destLen = 0;
+  *srcLen = 0;
+  const Byte *destStart = dest;
+  const Byte *srcStart = src;
+  unsigned mode = 2;
+
+  {
+    if (srcRem == 0)
+      return S_FALSE;
+    UInt32 b = *src;
+    if (b > 17)
+    {
+      src++;
+      srcRem--;
+      b -= 17;
+      mode = (b < 4 ? 0 : 1);
+      if (b > srcRem || b > destRem)
+        return S_FALSE;
+      srcRem -= b;
+      destRem -= b;
+      do
+        *dest++ = *src++;
+      while (--b);
+    }
+  }
+
+  for (;;)
+  {
+    if (srcRem < 3)
+      return S_FALSE;
+    UInt32 b = *src++;
+    srcRem--;
+    UInt32 len, back;
+    if (b >= 64)
+    {
+      srcRem--;
+      back = ((b >> 2) & 7) + ((UInt32)*src++ << 3);
+      len = (b >> 5) + 1;
+    }
+    else if (b < 16)
+    {
+      if (mode == 2)
+      {
+        if (b == 0)
+        {
+          for (b = 15;; b += 255)
+          {
+            if (srcRem == 0)
+              return S_FALSE;
+            UInt32 b2 = *src++;
+            srcRem--;
+            if (b2 != 0)
+            {
+              b += b2;
+              break;
+            }
+          }
+        }
+        b += 3;
+        if (b > srcRem || b > destRem)
+          return S_FALSE;
+        srcRem -= b;
+        destRem -= b;
+        mode = 1;
+        do
+          *dest++ = *src++;
+        while (--b);
+        continue;
+      }
+      srcRem--;
+      back = (b >> 2) + (*src++ << 2);
+      len = 2;
+      if (mode == 1)
+      {
+        back += (1 << 11);
+        len = 3;
+      }
+    }
+    else
+    {
+      UInt32 bOld = b;
+      b = (b < 32 ? 7 : 31);
+      len = bOld & b;
+      if (len == 0)
+      {
+        for (len = b;; len += 255)
+        {
+          if (srcRem == 0)
+            return S_FALSE;
+          UInt32 b2 = *src++;
+          srcRem--;
+          if (b2 != 0)
+          {
+            len += b2;
+            break;
+          }
+        }
+      }
+      len += 2;
+      if (srcRem < 2)
+        return S_FALSE;
+      b = *src;
+      back = (b >> 2) + ((UInt32)src[1] << 6);
+      src += 2;
+      srcRem -= 2;
+      if (bOld < 32)
+      {
+        if (back == 0)
+        {
+          *destLen = dest - destStart;
+          *srcLen = src - srcStart;
+          return S_OK;
+        }
+        back += ((bOld & 8) << 11) + (1 << 14) - 1;
+      }
+    }
+    back++;
+    if (len > destRem || (size_t)(dest - destStart) < back)
+      return S_FALSE;
+    destRem -= len;
+    Byte *destTemp = dest - back;
+    dest += len;
+    do
+    {
+      *(destTemp + back) = *destTemp;
+      destTemp++;
+    }
+    while (--len);
+    b &= 3;
+    if (b == 0)
+    {
+      mode = 2;
+      continue;
+    }
+    if (b > srcRem || b > destRem)
+      return S_FALSE;
+    srcRem -= b;
+    destRem -= b;
+    mode = 0;
+    *dest++ = *src++;
+    if (b > 1)
+    {
+      *dest++ = *src++;
+      if (b > 2)
+        *dest++ = *src++;
+    }
+  }
+}
+
+HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool *outBufWasWritten, UInt32 *outBufWasWrittenSize, UInt32 inSize, UInt32 outSizeMax)
+{
+  if (outBuf)
+  {
+    *outBufWasWritten = false;
+    *outBufWasWrittenSize = 0;
+  }
+  UInt32 method = _h.Method;
+  if (_h.SeveralMethods)
+  {
+    Byte props[1];
+    RINOK(ReadStream_FALSE(_stream, props, 1));
+    method = (props[0] == 0x5D ? kMethod_LZMA : kMethod_ZLIB);
+    RINOK(_stream->Seek(-1, STREAM_SEEK_CUR, NULL));
+  }
+
+  if (method == kMethod_LZO)
+  {
+    if (_inputBuffer.GetCapacity() < inSize)
+    {
+      _inputBuffer.Free();
+      _inputBuffer.SetCapacity(inSize);
+    }
+    RINOK(ReadStream_FALSE(_stream, _inputBuffer, inSize));
+
+    Byte *dest = outBuf;
+    if (!outBuf)
+    {
+      dest = _dynOutStreamSpec->GetBufPtrForWriting(outSizeMax);
+      if (!dest)
+        return E_OUTOFMEMORY;
+    }
+    SizeT destLen = outSizeMax, srcLen = inSize;
+    RINOK(LzoDecode(dest, &destLen, _inputBuffer, &srcLen));
+    if (inSize != srcLen)
+      return S_FALSE;
+    if (outBuf)
+    {
+      *outBufWasWritten = true;
+      *outBufWasWrittenSize = (UInt32)destLen;
+    }
+    else
+      _dynOutStreamSpec->UpdateSize(destLen);
+  }
+  else if (method == kMethod_LZMA)
+  {
+    if (!_lzmaDecoder)
+    {
+      _lzmaDecoderSpec = new NCompress::NLzma::CDecoder();
+      _lzmaDecoderSpec->FinishStream = true;
+      _lzmaDecoder = _lzmaDecoderSpec;
+    }
+    const UInt32 kPropsSize = 5 + 8;
+    Byte props[kPropsSize];
+    ReadStream_FALSE(_limitedInStream, props, kPropsSize);
+    RINOK(_lzmaDecoderSpec->SetDecoderProperties2(props, 5));
+    UInt64 outSize = GetUi64(props + 5);
+    if (outSize > outSizeMax)
+      return S_FALSE;
+    RINOK(_lzmaDecoder->Code(_limitedInStream, outStream, NULL, &outSize, NULL));
+    if (inSize != kPropsSize + _lzmaDecoderSpec->GetInputProcessedSize())
+      return S_FALSE;
+  }
+  else
+  {
+    if (!_zlibDecoder)
+    {
+      _zlibDecoderSpec = new NCompress::NZlib::CDecoder();
+      _zlibDecoder = _zlibDecoderSpec;
+    }
+    RINOK(_zlibDecoder->Code(_limitedInStream, outStream, NULL, NULL, NULL));
+    if (inSize != _zlibDecoderSpec->GetInputProcessedSize())
+      return S_FALSE;
+  }
+  return S_OK;
+}
+
+HRESULT CHandler::ReadMetadataBlock(UInt32 &packSize)
+{
+  Byte temp[3];
+  unsigned offset = _h.NeedCheckData() ? 3 : 2;
+  if (offset > packSize)
+    return S_FALSE;
+  RINOK(ReadStream_FALSE(_stream, temp, offset));
+  // if (NeedCheckData && Major < 4) checkByte must be = 0xFF
+  bool be = _h.be;
+  UInt32 size = Get16(temp);
+  bool isCompressed = ((size & kNotCompressedBit16) == 0);
+  if (size != kNotCompressedBit16)
+    size &= ~kNotCompressedBit16;
+
+  if (size > kMetadataBlockSize || offset + size > packSize)
+    return S_FALSE;
+  packSize = offset + size;
+  if (isCompressed)
+  {
+    _limitedInStreamSpec->Init(size);
+    RINOK(Decompress(_dynOutStream, NULL, NULL, NULL, size, kMetadataBlockSize));
+  }
+  else
+  {
+    // size != 0 here
+    Byte *buf = _dynOutStreamSpec->GetBufPtrForWriting(size);
+    if (!buf)
+      return E_OUTOFMEMORY;
+    RINOK(ReadStream_FALSE(_stream, buf, size));
+    _dynOutStreamSpec->UpdateSize(size);
+  }
+  return S_OK;
+}
+
+HRESULT CHandler::ReadData(CData &data, UInt64 start, UInt64 end)
+{
+  if (end < start || end - start >= ((UInt64)1 << 32))
+    return S_FALSE;
+  UInt32 size = (UInt32)(end - start);
+  RINOK(_stream->Seek(start, STREAM_SEEK_SET, NULL));
+  _dynOutStreamSpec->Init();
+  UInt32 packPos = 0;
+  while (packPos != size)
+  {
+    data.PackPos.Add(packPos);
+    data.UnpackPos.Add((UInt32)_dynOutStreamSpec->GetSize());
+    if (packPos > size)
+      return S_FALSE;
+    UInt32 packSize = size - packPos;
+    RINOK(ReadMetadataBlock(packSize));
+    if (_dynOutStreamSpec->GetSize() >= ((UInt64)1 << 32))
+      return S_FALSE;
+    packPos += packSize;
+  }
+  data.UnpackPos.Add((UInt32)_dynOutStreamSpec->GetSize());
+  _dynOutStreamSpec->CopyToBuffer(data.Data);
+  return S_OK;
+}
+
+struct CTempItem
+{
+  UInt32 StartBlock;
+  // UInt32 iNodeNumber1;
+  UInt32 Offset;
+  // UInt16 iNodeNumber2;
+  UInt16 Type;
+};
+  
+HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned level, int &nodeIndex)
+{
+  if (level > kNumDirLevelsMax)
+    return S_FALSE;
+
+  int blockIndex = _inodesData.PackPos.FindInSorted(startBlock);
+  if (blockIndex < 0)
+    return S_FALSE;
+  UInt32 unpackPos = _inodesData.UnpackPos[blockIndex] + offset;
+  if (unpackPos < offset)
+    return S_FALSE;
+
+  nodeIndex = _nodesPos.FindInSorted(unpackPos, _blockToNode[blockIndex], _blockToNode[blockIndex + 1]);
+  // nodeIndex = _nodesPos.FindInSorted(unpackPos);
+  if (nodeIndex < 0)
+    return S_FALSE;
+  
+  const CNode &n = _nodes[nodeIndex];
+  if (!n.IsDir())
+    return S_OK;
+  blockIndex = _dirs.PackPos.FindInSorted((UInt32)n.StartBlock);
+  if (blockIndex < 0)
+    return S_FALSE;
+  unpackPos = _dirs.UnpackPos[blockIndex] + n.Offset;
+  if (unpackPos < n.Offset || unpackPos > _dirs.Data.GetCapacity())
+    return S_FALSE;
+
+  UInt32 rem = (UInt32)_dirs.Data.GetCapacity() - unpackPos;
+  const Byte *p = _dirs.Data + unpackPos;
+  UInt32 fileSize = (UInt32)n.FileSize;
+
+  if (fileSize > rem)
+    return S_FALSE;
+  rem = fileSize;
+  if (_h.Major >= 3)
+  {
+    if (rem < 3)
+      return S_FALSE;
+    rem -= 3;
+  }
+
+  CRecordVector<CTempItem> tempItems;
+  while (rem != 0)
+  {
+    bool be = _h.be;
+    UInt32 count;
+    CTempItem tempItem;
+    if (_h.Major <= 2)
+    {
+      if (rem < 4)
+        return S_FALSE;
+      count = p[0];
+      tempItem.StartBlock = Get32(p);
+      if (be)
+        tempItem.StartBlock &= 0xFFFFFF;
+      else
+        tempItem.StartBlock >>= 8;
+      p += 4;
+      rem -= 4;
+    }
+    else
+    {
+      if (_h.Major == 3)
+      {
+        if (rem < 9)
+          return S_FALSE;
+        count = p[0];
+        p += 1;
+        rem -= 1;
+      }
+      else
+      {
+        if (rem < 12)
+          return S_FALSE;
+        count = GetUi32(p);
+        p += 4;
+        rem -= 4;
+      }
+      GET_32 (0, tempItem.StartBlock);
+      // GET_32 (4, tempItem.iNodeNumber1);
+      p += 8;
+      rem -= 8;
+    }
+    count++;
+    
+    for (UInt32 i = 0; i < count; i++)
+    {
+      if (rem == 0)
+        return S_FALSE;
+
+      UInt32 nameOffset = _h.GetFileNameOffset();
+      if (rem < nameOffset)
+        return S_FALSE;
+
+      if ((UInt32)_items.Size() >= kNumFilesMax)
+        return S_FALSE;
+      if (_openCallback)
+      {
+        UInt64 numFiles = _items.Size();
+        if ((numFiles & 0xFFFF) == 0)
+        {
+          RINOK(_openCallback->SetCompleted(&numFiles, NULL));
+        }
+      }
+      
+      CItem item;
+      item.Ptr = (UInt32)(p - _dirs.Data);
+
+      UInt32 size;
+      if (_h.IsOldVersion())
+      {
+        UInt32 t = Get16(p);
+        if (be)
+        {
+          tempItem.Offset = t >> 3;
+          tempItem.Type = (UInt16)(t & 0x7);
+        }
+        else
+        {
+          tempItem.Offset = t & 0x1FFF;
+          tempItem.Type = (UInt16)(t >> 13);
+        }
+        size = (UInt32)p[2];
+        /*
+        if (_h.Major > 2)
+          tempItem.iNodeNumber2 = Get16(p + 3);
+        */
+      }
+      else
+      {
+        GET_16 (0, tempItem.Offset);
+        // GET_16 (2, tempItem.iNodeNumber2);
+        GET_16 (4, tempItem.Type);
+        GET_16 (6, size);
+      }
+      p += nameOffset;
+      rem -= nameOffset;
+      size++;
+      if (rem < size)
+        return S_FALSE;
+      p += size;
+      rem -= size;
+      item.Parent = parent;
+      _items.Add(item);
+      tempItems.Add(tempItem);
+    }
+  }
+
+  int startItemIndex = _items.Size() - tempItems.Size();
+  for (int i = 0; i < tempItems.Size(); i++)
+  {
+    const CTempItem &tempItem = tempItems[i];
+    int index = startItemIndex + i;
+    CItem &item = _items[index];
+    RINOK(OpenDir(index, tempItem.StartBlock, tempItem.Offset, level + 1, item.Node));
+  }
+
+  return S_OK;
+}
+
+/*
+HRESULT CHandler::ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids)
+{
+  size_t size = num * 4;
+  ids.SetCapacity(size);
+  RINOK(_stream->Seek(start, STREAM_SEEK_SET, NULL));
+  return ReadStream_FALSE(_stream, ids, size);
+}
+*/
+
+HRESULT CHandler::Open2(IInStream *inStream)
+{
+  {
+    Byte buf[kHeaderSize3];
+    RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize3));
+    if (!_h.Parse(buf))
+      return S_FALSE;
+    if (!_h.IsSupported())
+      return E_NOTIMPL;
+    
+    switch (_h.Method)
+    {
+      case kMethod_ZLIB:
+      case kMethod_LZMA:
+      case kMethod_LZO:
+        break;
+      default:
+        return E_NOTIMPL;
+    }
+  }
+
+  _stream = inStream;
+
+  if (_h.NumFrags != 0)
+  {
+    if (_h.NumFrags > kNumFilesMax)
+      return S_FALSE;
+    _frags.Reserve(_h.NumFrags);
+    CByteBuffer data;
+    unsigned bigFrag = (_h.Major > 2);
+    
+    unsigned fragPtrsInBlockLog = kMetadataBlockSizeLog - (3 + bigFrag);
+    UInt32 numBlocks = (_h.NumFrags + (1 << fragPtrsInBlockLog) - 1) >> fragPtrsInBlockLog;
+    size_t numBlocksBytes = (size_t)numBlocks << (2 + bigFrag);
+    data.SetCapacity(numBlocksBytes);
+    RINOK(inStream->Seek(_h.FragTable, STREAM_SEEK_SET, NULL));
+    RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes));
+    bool be = _h.be;
+    
+    for (UInt32 i = 0; i < numBlocks; i++)
+    {
+      UInt64 offset = bigFrag ? Get64(data + i * 8) : Get32(data + i * 4);
+      RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL));
+      _dynOutStreamSpec->Init();
+      UInt32 packSize = kMetadataBlockSize + 3;
+      RINOK(ReadMetadataBlock(packSize));
+      UInt32 unpackSize = (UInt32)_dynOutStreamSpec->GetSize();
+      if (unpackSize != kMetadataBlockSize)
+        if (i != numBlocks - 1 || unpackSize != ((_h.NumFrags << (3 + bigFrag)) & (kMetadataBlockSize - 1)))
+          return S_FALSE;
+      const Byte *buf = _dynOutStreamSpec->GetBuffer();
+      for (UInt32 j = 0; j < kMetadataBlockSize && j < unpackSize;)
+      {
+        CFrag frag;
+        if (bigFrag)
+        {
+          frag.StartBlock = Get64(buf + j);
+          frag.Size = Get32(buf + j + 8);
+          // some archives contain nonzero in unused (buf + j + 12)
+          j += 16;
+        }
+        else
+        {
+          frag.StartBlock = Get32(buf + j);
+          frag.Size = Get32(buf + j + 4);
+          j += 8;
+        }
+        _frags.Add(frag);
+      }
+    }
+    if ((UInt32)_frags.Size() != _h.NumFrags)
+      return S_FALSE;
+  }
+
+  // RINOK(inStream->Seek(_h.InodeTable, STREAM_SEEK_SET, NULL));
+
+  RINOK(ReadData(_inodesData, _h.InodeTable, _h.DirTable));
+  RINOK(ReadData(_dirs, _h.DirTable, _h.FragTable));
+
+  UInt64 absOffset = _h.RootInode >> 16;
+  if (absOffset >= ((UInt64)1 << 32))
+    return S_FALSE;
+  {
+    UInt32 pos = 0;
+    UInt32 totalSize = (UInt32)_inodesData.Data.GetCapacity();
+    _nodesPos.Reserve(_h.NumInodes);
+    _nodes.Reserve(_h.NumInodes);
+    // we use _blockToNode for binary search seed optimizations
+    _blockToNode.Reserve(_inodesData.GetNumBlocks() + 1);
+    int curBlock = 0;
+    for (UInt32 i = 0; i < _h.NumInodes; i++)
+    {
+      CNode n;
+      const Byte *p = _inodesData.Data + pos;
+      UInt32 size = totalSize - pos;
+
+      switch(_h.Major)
+      {
+        case 1:  size = n.Parse1(p, size, _h); break;
+        case 2:  size = n.Parse2(p, size, _h); break;
+        case 3:  size = n.Parse3(p, size, _h); break;
+        default: size = n.Parse4(p, size, _h); break;
+      }
+      if (size == 0)
+        return S_FALSE;
+      while (pos >= _inodesData.UnpackPos[curBlock])
+      {
+        _blockToNode.Add(_nodesPos.Size());
+        curBlock++;
+      }
+      _nodesPos.Add(pos);
+      _nodes.Add(n);
+      pos += size;
+    }
+    _blockToNode.Add(_nodesPos.Size());
+    if (pos != totalSize)
+      return S_FALSE;
+  }
+  int rootNodeIndex;
+  RINOK(OpenDir(-1, (UInt32)absOffset, (UInt32)_h.RootInode & 0xFFFF, 0, rootNodeIndex));
+
+  /*
+  if (_h.Major < 4)
+  {
+    RINOK(ReadUids(_h.UidTable, _h.NumUids, _uids));
+    RINOK(ReadUids(_h.GidTable, _h.NumGids, _gids));
+  }
+  else
+  {
+    UInt32 size = _h.NumIDs * 4;
+    _uids.SetCapacity(size);
+
+    UInt32 numBlocks = (size + kMetadataBlockSize - 1) / kMetadataBlockSize;
+    UInt32 numBlocksBytes = numBlocks << 3;
+    CByteBuffer data;
+    data.SetCapacity(numBlocksBytes);
+    RINOK(inStream->Seek(_h.UidTable, STREAM_SEEK_SET, NULL));
+    RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes));
+
+    for (UInt32 i = 0; i < numBlocks; i++)
+    {
+      UInt64 offset = GetUi64(data + i * 8);
+      UInt32 unpackSize, packSize;
+      RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL));
+      RINOK(ReadMetadataBlock(NULL, _uids + kMetadataBlockSize * i, packSize, unpackSize));
+      if (unpackSize != kMetadataBlockSize)
+        if (i != numBlocks - 1 || unpackSize != (size & (kMetadataBlockSize - 1)))
+          return S_FALSE;
+    }
+  }
+  */
+
+  {
+    const UInt32 alignSize = 1 << 12;
+    Byte buf[alignSize];
+    RINOK(inStream->Seek(_h.Size, STREAM_SEEK_SET, NULL));
+    UInt32 rem = (UInt32)(0 - _h.Size) & (alignSize - 1);
+    _sizeCalculated = _h.Size;
+    if (rem != 0)
+    {
+      if (ReadStream_FALSE(_stream, buf, rem) == S_OK)
+      {
+        size_t i;
+        for (i = 0; i < rem && buf[i] == 0; i++);
+        if (i == rem)
+          _sizeCalculated = _h.Size + rem;
+      }
+    }
+  }
+  return S_OK;
+}
+
+AString CHandler::GetPath(int index) const
+{
+  unsigned len = 0;
+  int indexMem = index;
+  bool be = _h.be;
+  do
+  {
+    const CItem &item = _items[index];
+    index = item.Parent;
+    const Byte *p = _dirs.Data + item.Ptr;
+    unsigned size = (_h.IsOldVersion() ? (unsigned)p[2] : (unsigned)Get16(p + 6)) + 1;
+    p += _h.GetFileNameOffset();
+    unsigned i;
+    for (i = 0; i < size && p[i]; i++);
+    len += i + 1;
+  }
+  while (index >= 0);
+  len--;
+
+  AString path;
+  char *dest = path.GetBuffer(len) + len;
+  index = indexMem;
+  for (;;)
+  {
+    const CItem &item = _items[index];
+    index = item.Parent;
+
+    const Byte *p = _dirs.Data + item.Ptr;
+    unsigned size = (_h.IsOldVersion() ? (unsigned)p[2] : (unsigned)Get16(p + 6)) + 1;
+    p += _h.GetFileNameOffset();
+    unsigned i;
+    for (i = 0; i < size && p[i]; i++);
+    dest -= i;
+    memcpy(dest, p, i);
+    if (index < 0)
+      break;
+    *(--dest) = CHAR_PATH_SEPARATOR;
+  }
+  path.ReleaseBuffer(len);
+  return path;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)
+{
+  COM_TRY_BEGIN
+  {
+    Close();
+    _limitedInStreamSpec->SetStream(stream);
+    HRESULT res;
+    try
+    {
+      RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
+      _openCallback = callback;
+      res = Open2(stream);
+    }
+    catch(...)
+    {
+      Close();
+      throw;
+    }
+    if (res != S_OK)
+    {
+      Close();
+      return res;
+    }
+    _stream = stream;
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _limitedInStreamSpec->ReleaseStream();
+  _stream.Release();
+
+  _items.Clear();
+  _nodes.Clear();
+  _nodesPos.Clear();
+  _blockToNode.Clear();
+  _frags.Clear();
+  _inodesData.Clear();
+  _dirs.Clear();
+
+  // _uids.Free();
+  // _gids.Free();;
+
+  _cachedBlock.Free();
+  ClearCache();
+
+  return S_OK;
+}
+
+bool CHandler::GetPackSize(int index, UInt64 &totalPack, bool fillOffsets)
+{
+  totalPack = 0;
+  const CItem &item = _items[index];
+  const CNode &node = _nodes[item.Node];
+  UInt32 ptr = _nodesPos[item.Node];
+  const Byte *p = _inodesData.Data + ptr;
+  bool be = _h.be;
+
+  UInt32 type = node.Type;
+  UInt32 offset;
+  if (node.IsLink() || node.FileSize == 0)
+  {
+    totalPack = node.FileSize;
+    return true;
+  }
+
+  UInt32 numBlocks = (UInt32)node.GetNumBlocks(_h);
+
+  if (fillOffsets)
+  {
+    _blockOffsets.Clear();
+    _blockCompressed.Clear();
+    _blockOffsets.Add(totalPack);
+  }
+
+  if (_h.Major <= 1)
+  {
+    offset = 15;
+    p += offset;
+    
+    for (UInt32 i = 0; i < numBlocks; i++)
+    {
+      UInt32 t = Get16(p + i * 2);
+      if (fillOffsets)
+        _blockCompressed.Add((t & kNotCompressedBit16) == 0);
+      if (t != kNotCompressedBit16)
+        t &= ~kNotCompressedBit16;
+      totalPack += t;
+      if (fillOffsets)
+        _blockOffsets.Add(totalPack);
+    }
+  }
+  else
+  {
+    if (_h.Major <= 2)
+      offset = 24;
+    else if (type == kType_FILE)
+      offset = 32;
+    else if (type == kType_FILE + 7)
+      offset = (_h.Major <= 3 ? 40 : 56);
+    else
+      return false;
+    
+    p += offset;
+    
+    for (UInt64 i = 0; i < numBlocks; i++)
+    {
+      UInt32 t = Get32(p + i * 4);
+      if (fillOffsets)
+        _blockCompressed.Add(IS_COMPRESSED_BLOCK(t));
+      UInt32 size = GET_COMPRESSED_BLOCK_SIZE(t);
+      if (size > _h.BlockSize)
+        return false;
+      totalPack += size;
+      if (fillOffsets)
+        _blockOffsets.Add(totalPack);
+    }
+
+    if (node.ThereAreFrags())
+    {
+      if (node.Frag >= (UInt32)_frags.Size())
+        return false;
+      const CFrag &frag = _frags[node.Frag];
+      if (node.Offset == 0)
+      {
+        UInt32 size = GET_COMPRESSED_BLOCK_SIZE(frag.Size);
+        if (size > _h.BlockSize)
+          return false;
+        totalPack += size;
+      }
+    }
+  }
+  return true;
+}
+
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _items.Size();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidMethod:
+    {
+      const char *s;
+      if (_h.SeveralMethods)
+        s = "LZMA ZLIB";
+      else
+      {
+        s = k_Methods[0];
+        if (_h.Method < sizeof(k_Methods) / sizeof(k_Methods[0]))
+          s = k_Methods[_h.Method];
+      }
+      prop = s;
+      break;
+    }
+    case kpidFileSystem:
+    {
+      AString res = "SquashFS";
+      if (_h.SeveralMethods)
+        res += "-LZMA";
+      res += ' ';
+      char s[16];
+      ConvertUInt32ToString(_h.Major, s);
+      res += s;
+      res += '.';
+      ConvertUInt32ToString(_h.Minor, s);
+      res += s;
+      prop = res;
+      break;
+    }
+    case kpidBlock: prop = _h.BlockSize; break;
+    case kpidBigEndian: prop = _h.be; break;
+    case kpidCTime:
+      if (_h.CTime != 0)
+      {
+        FILETIME ft;
+        NWindows::NTime::UnixTimeToFileTime(_h.CTime, ft);
+        prop = ft;
+      }
+      break;
+    case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break;
+    // case kpidNumBlocks: prop = _h.NumFrags; break;
+    case kpidPhySize: prop = _sizeCalculated; break;
+    case kpidHeadersSize:
+      if (_sizeCalculated >= _h.InodeTable)
+        prop = _sizeCalculated - _h.InodeTable;
+      break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  const CItem &item = _items[index];
+  const CNode &node = _nodes[item.Node];
+  bool isDir = node.IsDir();
+  bool be = _h.be;
+
+  switch(propID)
+  {
+    case kpidPath: prop = MultiByteToUnicodeString(GetPath(index), CP_OEMCP); break;
+    case kpidIsDir: prop = isDir; break;
+    // case kpidOffset: if (!node.IsLink()) prop = (UInt64)node.StartBlock; break;
+    case kpidSize: if (!isDir) prop = node.GetSize(); break;
+    case kpidPackSize:
+      if (!isDir)
+      {
+        UInt64 size;
+        if (GetPackSize(index, size, false))
+          prop = size;
+      }
+      break;
+    case kpidMTime:
+    {
+      UInt32 offset = 0;
+      switch(_h.Major)
+      {
+        case 1:
+          if (node.Type == kType_FILE)
+            offset = 3;
+          else if (node.Type == kType_DIR)
+            offset = 7;
+          break;
+        case 2:
+          if (node.Type == kType_FILE)
+            offset = 4;
+          else if (node.Type == kType_DIR)
+            offset = 8;
+          else if (node.Type == kType_DIR + 7)
+            offset = 9;
+          break;
+        case 3: offset = 4; break;
+        case 4: offset = 8; break;
+      }
+      if (offset != 0)
+      {
+        const Byte *p = _inodesData.Data + _nodesPos[item.Node] + offset;
+        FILETIME ft;
+        NWindows::NTime::UnixTimeToFileTime(Get32(p), ft);
+        prop = ft;
+      }
+      break;
+    }
+    case kpidPosixAttrib:
+    {
+      if (node.Type != 0 && node.Type < sizeof(k_TypeToMode) / sizeof(k_TypeToMode[0]))
+        prop = (UInt32)(node.Mode & 0xFFF) | k_TypeToMode[node.Type];
+      break;
+    }
+    /*
+    case kpidUser:
+    {
+      UInt32 offset = node.Uid * 4;
+      if (offset < _uids.GetCapacity())
+        prop = (UInt32)Get32(_uids + offset);
+      break;
+    }
+    case kpidGroup:
+    {
+      if (_h.Major == 4 || node.Gid == _h.GetSpecGuidIndex())
+      {
+        UInt32 offset = node.Uid * 4;
+        if (offset < _uids.GetCapacity())
+          prop = (UInt32)Get32(_uids + offset);
+      }
+      else
+      {
+        UInt32 offset = node.Gid * 4;
+        if (offset < _gids.GetCapacity())
+          prop = (UInt32)Get32(_gids + offset);
+      }
+      break;
+    }
+    */
+    /*
+    case kpidLinks:
+      if (_h.Major >= 3 && node.Type != kType_FILE)
+        prop = node.NumLinks;
+      break;
+    */
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+class CSquashfsInStream: public CCachedInStream
+{
+  HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);
+public:
+  CHandler *Handler;
+};
+
+HRESULT CSquashfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
+{
+  return Handler->ReadBlock(blockIndex, dest, blockSize);
+}
+
+HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
+{
+  const CNode &node = _nodes[_nodeIndex];
+  UInt64 blockOffset;
+  UInt32 packBlockSize;
+  UInt32 offsetInBlock = 0;
+  bool compressed;
+  if (blockIndex < _blockCompressed.Size())
+  {
+    compressed = _blockCompressed[(int)blockIndex];
+    blockOffset = _blockOffsets[(int)blockIndex];
+    packBlockSize = (UInt32)(_blockOffsets[(int)blockIndex + 1] - blockOffset);
+    blockOffset += node.StartBlock;
+  }
+  else
+  {
+    if (!node.ThereAreFrags())
+      return S_FALSE;
+    const CFrag &frag = _frags[node.Frag];
+    offsetInBlock = node.Offset;
+    blockOffset = frag.StartBlock;
+    packBlockSize = GET_COMPRESSED_BLOCK_SIZE(frag.Size);
+    compressed = IS_COMPRESSED_BLOCK(frag.Size);
+  }
+
+  if (packBlockSize == 0)
+  {
+    // sparse file ???
+    memset(dest, 0, blockSize);
+    return S_OK;
+  }
+
+  if (blockOffset != _cachedBlockStartPos ||
+      packBlockSize != _cachedPackBlockSize)
+  {
+    ClearCache();
+    RINOK(_stream->Seek(blockOffset, STREAM_SEEK_SET, NULL));
+    _limitedInStreamSpec->Init(packBlockSize);
+    
+    if (compressed)
+    {
+      _outStreamSpec->Init((Byte *)_cachedBlock, _h.BlockSize);
+      bool outBufWasWritten;
+      UInt32 outBufWasWrittenSize;
+      HRESULT res = Decompress(_outStream, _cachedBlock, &outBufWasWritten, &outBufWasWrittenSize, packBlockSize, _h.BlockSize);
+      if (outBufWasWritten)
+        _cachedUnpackBlockSize = outBufWasWrittenSize;
+      else
+        _cachedUnpackBlockSize = (UInt32)_outStreamSpec->GetPos();
+      RINOK(res);
+    }
+    else
+    {
+      RINOK(ReadStream_FALSE(_limitedInStream, _cachedBlock, packBlockSize));
+      _cachedUnpackBlockSize = packBlockSize;
+    }
+    _cachedBlockStartPos = blockOffset;
+    _cachedPackBlockSize = packBlockSize;
+  }
+  if (offsetInBlock + blockSize > _cachedUnpackBlockSize)
+    return S_FALSE;
+  memcpy(dest, _cachedBlock + offsetInBlock, blockSize);
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _items.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt64 totalSize = 0;
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+  {
+    const CItem &item = _items[allFilesMode ? i : indices[i]];
+    const CNode &node = _nodes[item.Node];
+    totalSize += node.GetSize();
+  }
+  extractCallback->SetTotal(totalSize);
+
+  UInt64 totalPackSize;
+  totalSize = totalPackSize = 0;
+  
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  for (i = 0; i < numItems; i++)
+  {
+    lps->InSize = totalPackSize;
+    lps->OutSize = totalSize;
+    RINOK(lps->SetCur());
+    CMyComPtr<ISequentialOutStream> outStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    UInt32 index = allFilesMode ? i : indices[i];
+    const CItem &item = _items[index];
+    const CNode &node = _nodes[item.Node];
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));
+    // const Byte *p = _data + item.Offset;
+
+    if (node.IsDir())
+    {
+      RINOK(extractCallback->PrepareOperation(askMode));
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+      continue;
+    }
+    UInt64 unpackSize = node.GetSize();
+    totalSize += unpackSize;
+    UInt64 packSize;
+    if (GetPackSize(index, packSize, false))
+      totalPackSize += packSize;
+
+    if (!testMode && !outStream)
+      continue;
+    RINOK(extractCallback->PrepareOperation(askMode));
+
+    int res = NExtract::NOperationResult::kDataError;
+    {
+      CMyComPtr<ISequentialInStream> inSeqStream;
+      CMyComPtr<IInStream> inStream;
+      HRESULT hres = GetStream(index, &inSeqStream);
+      if (inSeqStream)
+        inSeqStream.QueryInterface(IID_IInStream, &inStream);
+      if (hres == S_FALSE || !inStream)
+      {
+        if (hres == E_OUTOFMEMORY)
+          return hres;
+        res = NExtract::NOperationResult::kUnSupportedMethod;
+      }
+      else
+      {
+        RINOK(hres);
+        if (inStream)
+        {
+          HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
+          if (hres != S_OK &&  hres != S_FALSE)
+          {
+            RINOK(hres);
+          }
+          if (copyCoderSpec->TotalSize == unpackSize && hres == S_OK)
+            res = NExtract::NOperationResult::kOK;
+          else
+          {
+            res = res;
+          }
+        }
+      }
+    }
+    RINOK(extractCallback->SetOperationResult(res));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+  COM_TRY_BEGIN
+
+  const CItem &item = _items[index];
+  const CNode &node = _nodes[item.Node];
+
+  if (node.IsDir())
+    return E_FAIL;
+
+  const Byte *p = _inodesData.Data + _nodesPos[item.Node];
+
+  if (node.FileSize == 0 || node.IsLink())
+  {
+    CBufInStream *streamSpec = new CBufInStream;
+    CMyComPtr<IInStream> streamTemp = streamSpec;
+    if (node.IsLink())
+      streamSpec->Init(p + _h.GetSymLinkOffset(), (size_t)node.FileSize);
+    else
+      streamSpec->Init(NULL, 0);
+    *stream = streamTemp.Detach();
+    return S_OK;
+  }
+
+  UInt64 packSize;
+  if (!GetPackSize(index, packSize, true))
+    return S_FALSE;
+
+  _nodeIndex = item.Node;
+
+  size_t cacheSize = _h.BlockSize;
+  if (_cachedBlock.GetCapacity() != cacheSize)
+  {
+    ClearCache();
+    _cachedBlock.SetCapacity(cacheSize);
+  }
+
+  CSquashfsInStream *streamSpec = new CSquashfsInStream;
+  CMyComPtr<IInStream> streamTemp = streamSpec;
+  streamSpec->Handler = this;
+  unsigned cacheSizeLog = 22;
+  if (cacheSizeLog <= _h.BlockSizeLog)
+    cacheSizeLog = _h.BlockSizeLog + 1;
+  if (!streamSpec->Alloc(_h.BlockSizeLog, cacheSizeLog - _h.BlockSizeLog))
+    return E_OUTOFMEMORY;
+  streamSpec->Init(node.FileSize);
+  *stream = streamTemp.Detach();
+
+  return S_OK;
+
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new NArchive::NSquashfs::CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"SquashFS", L"squashfs", 0, 0xD2, SIGNATURE, kSignatureSize, false, CreateArc, 0 };
+
+REGISTER_ARC(Cramfs)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/SwfHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/SwfHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/SwfHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/SwfHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,706 @@
+// SwfHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/Buffer.h"
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+#include "Common/MyString.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../Common/InBuffer.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+#include "../Compress/ZlibDecoder.h"
+#include "../Compress/ZlibEncoder.h"
+
+#include "Common/DummyOutStream.h"
+
+#include "DeflateProps.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NSwfc {
+
+static const UInt32 kHeaderSize = 8;
+
+static const Byte SWF_UNCOMPRESSED = 'F';
+static const Byte SWF_COMPRESSED = 'C';
+static const Byte SWF_MIN_COMPRESSED_VER = 6;
+
+struct CItem
+{
+  Byte Buf[kHeaderSize];
+
+  UInt32 GetSize() const { return GetUi32(Buf + 4); }
+  bool IsSwf(Byte c) const { return (Buf[0] == c && Buf[1] == 'W' && Buf[2] == 'S' && Buf[3] < 32); }
+  bool IsUncompressed() const { return IsSwf(SWF_UNCOMPRESSED); }
+  bool IsCompressed() const { return IsSwf(SWF_COMPRESSED); }
+
+  void MakeUncompressed() { Buf[0] = SWF_UNCOMPRESSED; }
+  void MakeCompressed()
+  {
+    Buf[0] = SWF_COMPRESSED;
+    if (Buf[3] < SWF_MIN_COMPRESSED_VER)
+      Buf[3] = SWF_MIN_COMPRESSED_VER;
+  }
+
+  HRESULT ReadHeader(ISequentialInStream *stream) { return ReadStream_FALSE(stream, Buf, kHeaderSize); }
+  HRESULT WriteHeader(ISequentialOutStream *stream) { return WriteStream(stream, Buf, kHeaderSize); }
+};
+
+class CHandler:
+  public IInArchive,
+  public IArchiveOpenSeq,
+  public IOutArchive,
+  public ISetProperties,
+  public CMyUnknownImp
+{
+  CItem _item;
+  UInt64 _packSize;
+  bool _packSizeDefined;
+  CMyComPtr<ISequentialInStream> _seqStream;
+  CMyComPtr<IInStream> _stream;
+
+  CDeflateProps _method;
+
+public:
+  MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)
+  INTERFACE_IInArchive(;)
+  INTERFACE_IOutArchive(;)
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);
+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);
+};
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_NO_Table
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = 1;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
+{
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidSize: prop = (UInt64)_item.GetSize(); break;
+    case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *)
+{
+  RINOK(OpenSeq(stream));
+  _stream = stream;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
+{
+  Close();
+  HRESULT res = _item.ReadHeader(stream);
+  if (res == S_OK)
+    if (_item.IsCompressed())
+      _seqStream = stream;
+    else
+      res = S_FALSE;
+  return res;
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _packSizeDefined = false;
+  _seqStream.Release();
+  _stream.Release();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  if (numItems == 0)
+    return S_OK;
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
+    return E_INVALIDARG;
+
+  extractCallback->SetTotal(_item.GetSize());
+  CMyComPtr<ISequentialOutStream> realOutStream;
+  Int32 askMode = testMode ?
+      NExtract::NAskMode::kTest :
+      NExtract::NAskMode::kExtract;
+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
+  if (!testMode && !realOutStream)
+    return S_OK;
+
+  extractCallback->PrepareOperation(askMode);
+
+  NCompress::NZlib::CDecoder *_decoderSpec = new NCompress::NZlib::CDecoder;
+  CMyComPtr<ICompressCoder> _decoder = _decoderSpec;
+
+  CDummyOutStream *outStreamSpec = new CDummyOutStream;
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+  outStreamSpec->SetStream(realOutStream);
+  outStreamSpec->Init();
+  realOutStream.Release();
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  lps->InSize = kHeaderSize;
+  lps->OutSize = outStreamSpec->GetSize();
+  RINOK(lps->SetCur());
+  
+  CItem item = _item;
+  item.MakeUncompressed();
+  RINOK(item.WriteHeader(outStream));
+  if (_stream)
+    RINOK(_stream->Seek(kHeaderSize, STREAM_SEEK_SET, NULL));
+  HRESULT result = _decoderSpec->Code(_seqStream, outStream, NULL, NULL, progress);
+  Int32 opRes = NExtract::NOperationResult::kDataError;
+  if (result == S_OK)
+  {
+    if (_item.GetSize() == outStreamSpec->GetSize())
+    {
+      _packSizeDefined = true;
+      _packSize = _decoderSpec->GetInputProcessedSize() + kHeaderSize;
+      opRes = NExtract::NOperationResult::kOK;
+    }
+  }
+  else if (result != S_FALSE)
+    return result;
+
+  outStream.Release();
+  return extractCallback->SetOperationResult(opRes);
+  COM_TRY_END
+}
+
+static HRESULT UpdateArchive(ISequentialOutStream *outStream,
+    UInt64 size, CDeflateProps &deflateProps,
+    IArchiveUpdateCallback *updateCallback)
+{
+  UInt64 complexity = 0;
+  RINOK(updateCallback->SetTotal(size));
+  RINOK(updateCallback->SetCompleted(&complexity));
+
+  CMyComPtr<ISequentialInStream> fileInStream;
+  RINOK(updateCallback->GetStream(0, &fileInStream));
+
+  CItem item;
+  HRESULT res = item.ReadHeader(fileInStream);
+  if (res == S_FALSE)
+    return E_INVALIDARG;
+  RINOK(res);
+  if (!item.IsUncompressed() || size != item.GetSize())
+    return E_INVALIDARG;
+
+  item.MakeCompressed();
+  item.WriteHeader(outStream);
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(updateCallback, true);
+  
+  NCompress::NZlib::CEncoder *encoderSpec = new NCompress::NZlib::CEncoder;
+  CMyComPtr<ICompressCoder> encoder = encoderSpec;
+  encoderSpec->Create();
+  RINOK(deflateProps.SetCoderProperties(encoderSpec->DeflateEncoderSpec));
+  RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, progress));
+  if (encoderSpec->GetInputProcessedSize() + kHeaderSize != size)
+    return E_INVALIDARG;
+  return updateCallback->SetOperationResult(NUpdate::NOperationResult::kOK);
+}
+
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
+{
+  *timeType = NFileTimeType::kUnix;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+    IArchiveUpdateCallback *updateCallback)
+{
+  if (numItems != 1)
+    return E_INVALIDARG;
+
+  Int32 newData, newProps;
+  UInt32 indexInArchive;
+  if (!updateCallback)
+    return E_FAIL;
+  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));
+
+  if (IntToBool(newProps))
+  {
+    {
+      NCOM::CPropVariant prop;
+      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));
+      if (prop.vt == VT_BOOL)
+      {
+        if (prop.boolVal != VARIANT_FALSE)
+          return E_INVALIDARG;
+      }
+      else if (prop.vt != VT_EMPTY)
+        return E_INVALIDARG;
+    }
+  }
+
+  if (IntToBool(newData))
+  {
+    UInt64 size;
+    {
+      NCOM::CPropVariant prop;
+      RINOK(updateCallback->GetProperty(0, kpidSize, &prop));
+      if (prop.vt != VT_UI8)
+        return E_INVALIDARG;
+      size = prop.uhVal.QuadPart;
+    }
+    return UpdateArchive(outStream, size, _method, updateCallback);
+  }
+    
+  if (indexInArchive != 0)
+    return E_INVALIDARG;
+
+  if (!_seqStream)
+    return E_NOTIMPL;
+
+  if (_stream)
+  {
+    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));
+  }
+  else
+    _item.WriteHeader(outStream);
+  return NCompress::CopyStream(_seqStream, outStream, NULL);
+}
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
+{
+  return _method.SetProperties(names, values, numProps);
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+#ifndef EXTRACT_ONLY
+static IOutArchive *CreateArcOut() { return new CHandler; }
+#else
+#define CreateArcOut 0
+#endif
+
+static CArcInfo g_ArcInfo =
+  { L"SWFc", L"swf", L"~.swf", 0xD8, { 'C', 'W', 'S' }, 3, true, CreateArc, CreateArcOut };
+
+REGISTER_ARC(Swfc)
+
+}
+
+namespace NSwf {
+
+static const UInt32 kFileSizeMax = (UInt32)1 << 30;
+static const int kNumTagsMax = (UInt32)1 << 23;
+
+struct CTag
+{
+  UInt32 Type;
+  CByteBuffer Buf;
+};
+
+class CHandler:
+  public IInArchive,
+  public IArchiveOpenSeq,
+  public CMyUnknownImp
+{
+  CObjectVector<CTag> _tags;
+  NSwfc::CItem _item;
+  UInt64 _packSize;
+
+  HRESULT OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *callback);
+  HRESULT OpenSeq2(ISequentialInStream *stream, IArchiveOpenCallback *callback);
+public:
+  MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq)
+  INTERFACE_IInArchive(;)
+
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);
+};
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidComment, VT_BSTR}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_NO_Table
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidPhySize: prop = _packSize; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _tags.Size();
+  return S_OK;
+}
+
+static const char *g_TagDesc[92] =
+{
+  "End",
+  "ShowFrame",
+  "DefineShape",
+  NULL,
+  "PlaceObject",
+  "RemoveObject",
+  "DefineBits",
+  "DefineButton",
+  "JPEGTables",
+  "SetBackgroundColor",
+  "DefineFont",
+  "DefineText",
+  "DoAction",
+  "DefineFontInfo",
+  "DefineSound",
+  "StartSound",
+  NULL,
+  "DefineButtonSound",
+  "SoundStreamHead",
+  "SoundStreamBlock",
+  "DefineBitsLossless",
+  "DefineBitsJPEG2",
+  "DefineShape2",
+  "DefineButtonCxform",
+  "Protect",
+  NULL,
+  "PlaceObject2",
+  NULL,
+  "RemoveObject2",
+  NULL,
+  NULL,
+  NULL,
+  "DefineShape3",
+  "DefineText2",
+  "DefineButton2",
+  "DefineBitsJPEG3",
+  "DefineBitsLossless2",
+  "DefineEditText",
+  NULL,
+  "DefineSprite",
+  NULL,
+  "41",
+  NULL,
+  "FrameLabel",
+  NULL,
+  "SoundStreamHead2",
+  "DefineMorphShape",
+  NULL,
+  "DefineFont2",
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  "ExportAssets",
+  "ImportAssets",
+  "EnableDebugger",
+  "DoInitAction",
+  "DefineVideoStream",
+  "VideoFrame",
+  "DefineFontInfo2",
+  NULL,
+  "EnableDebugger2",
+  "ScriptLimits",
+  "SetTabIndex",
+  NULL,
+  NULL,
+  "FileAttributes",
+  "PlaceObject3",
+  "ImportAssets2",
+  NULL,
+  "DefineFontAlignZones",
+  "CSMTextSettings",
+  "DefineFont3",
+  "SymbolClass",
+  "Metadata",
+  "DefineScalingGrid",
+  NULL,
+  NULL,
+  NULL,
+  "DoABC",
+  "DefineShape4",
+  "DefineMorphShape2",
+  NULL,
+  "DefineSceneAndFrameLabelData",
+  "DefineBinaryData",
+  "DefineFontName",
+  "StartSound2",
+  "DefineBitsJPEG4",
+  "DefineFont4"
+};
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  NWindows::NCOM::CPropVariant prop;
+  const CTag &tag = _tags[index];
+  switch(propID)
+  {
+    case kpidPath:
+    {
+      char s[32];
+      ConvertUInt32ToString(index, s);
+      size_t i = strlen(s);
+      s[i++] = '.';
+      ConvertUInt32ToString(tag.Type, s + i);
+      prop = s;
+      break;
+    }
+    case kpidSize:
+    case kpidPackSize:
+      prop = (UInt64)tag.Buf.GetCapacity(); break;
+    case kpidComment:
+      if (tag.Type < sizeof(g_TagDesc) / sizeof(g_TagDesc[0]))
+      {
+        const char *s = g_TagDesc[tag.Type];
+        if (s != NULL)
+          prop = s;
+      }
+      break;
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)
+{
+  return OpenSeq2(stream, callback);
+}
+
+static UInt16 Read16(CInBuffer &stream)
+{
+  UInt16 res = 0;
+  for (int i = 0; i < 2; i++)
+  {
+    Byte b;
+    if (!stream.ReadByte(b))
+      throw 1;
+    res |= (UInt16)b << (i * 8);
+  }
+  return res;
+}
+
+static UInt32 Read32(CInBuffer &stream)
+{
+  UInt32 res = 0;
+  for (int i = 0; i < 4; i++)
+  {
+    Byte b;
+    if (!stream.ReadByte(b))
+      throw 1;
+    res |= (UInt32)b << (i * 8);
+  }
+  return res;
+}
+
+struct CBitReader
+{
+  CInBuffer *stream;
+  unsigned NumBits;
+  Byte Val;
+
+  CBitReader(): NumBits(0), Val(0) {}
+
+  UInt32 ReadBits(unsigned numBits);
+};
+
+UInt32 CBitReader::ReadBits(unsigned numBits)
+{
+  UInt32 res = 0;
+  while (numBits > 0)
+  {
+    if (NumBits == 0)
+    {
+      Val = stream->ReadByte();
+      NumBits = 8;
+    }
+    if (numBits <= NumBits)
+    {
+      res <<= numBits;
+      NumBits -= numBits;
+      res |= (Val >> NumBits);
+      Val &= (1 << NumBits) - 1;
+      break;
+    }
+    else
+    {
+      res <<= NumBits;
+      res |= Val;
+      numBits -= NumBits;
+      NumBits = 0;
+    }
+  }
+  return res;
+}
+
+HRESULT CHandler::OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *callback)
+{
+  RINOK(_item.ReadHeader(stream))
+  if (!_item.IsUncompressed())
+    return S_FALSE;
+  
+  CInBuffer s;
+  if (!s.Create(1 << 20))
+    return E_OUTOFMEMORY;
+  s.SetStream(stream);
+  s.Init();
+  {
+    CBitReader br;
+    br.stream = &s;
+    unsigned numBits = br.ReadBits(5);
+    /* UInt32 xMin = */ br.ReadBits(numBits);
+    /* UInt32 xMax = */ br.ReadBits(numBits);
+    /* UInt32 yMin = */ br.ReadBits(numBits);
+    /* UInt32 yMax = */ br.ReadBits(numBits);
+  }
+  /* UInt32 frameDelay = */ Read16(s);
+  /* UInt32 numFrames =  */ Read16(s);
+
+  _tags.Clear();
+  UInt64 offsetPrev = 0;
+  for (;;)
+  {
+    UInt32 pair = Read16(s);
+    UInt32 type = pair >> 6;
+    UInt32 length = pair & 0x3F;
+    if (length == 0x3F)
+      length = Read32(s);
+    if (type == 0)
+      break;
+    UInt64 offset = s.GetProcessedSize() + NSwfc::kHeaderSize + length;
+    if (offset > kFileSizeMax || _tags.Size() >= kNumTagsMax)
+      return S_FALSE;
+    _tags.Add(CTag());
+    CTag &tag = _tags.Back();
+    tag.Type = type;
+    tag.Buf.SetCapacity(length);
+    if (s.ReadBytes(tag.Buf, length) != length)
+      return S_FALSE;
+    if (callback && offset >= offsetPrev + (1 << 20))
+    {
+      UInt64 numItems = _tags.Size();
+      RINOK(callback->SetCompleted(&numItems, &offset));
+      offsetPrev = offset;
+    }
+  }
+  _packSize = s.GetProcessedSize() + NSwfc::kHeaderSize;
+  return S_OK;
+}
+
+HRESULT CHandler::OpenSeq2(ISequentialInStream *stream, IArchiveOpenCallback *callback)
+{
+  HRESULT res;
+  try { res = OpenSeq3(stream, callback); }
+  catch(...) { res = S_FALSE; }
+  return res;
+}
+
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
+{
+  return OpenSeq2(stream, NULL);
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _tags.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt64 totalSize = 0;
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+    totalSize += _tags[allFilesMode ? i : indices[i]].Buf.GetCapacity();
+  extractCallback->SetTotal(totalSize);
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  totalSize = 0;
+
+  for (i = 0; i < numItems; i++)
+  {
+    lps->InSize = lps->OutSize = totalSize;
+    RINOK(lps->SetCur());
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    UInt32 index = allFilesMode ? i : indices[i];
+    const CByteBuffer &buf = _tags[index].Buf;
+    totalSize += buf.GetCapacity();
+
+    CMyComPtr<ISequentialOutStream> outStream;
+    RINOK(extractCallback->GetStream(index, &outStream, askMode));
+    if (!testMode && !outStream)
+      continue;
+      
+    RINOK(extractCallback->PrepareOperation(askMode));
+    if (outStream)
+      RINOK(WriteStream(outStream, buf, buf.GetCapacity()));
+    outStream.Release();
+    RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"SWF", L"swf", 0, 0xD7, { 'F', 'W', 'S' }, 3, true, CreateArc, 0 };
+
+REGISTER_ARC(Swf)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,386 @@
+// TarHandler.cpp
+
+#include "StdAfx.h"
+
+#include "Common/ComTry.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/StreamUtils.h"
+
+#include "../Common/ItemNameUtils.h"
+
+#include "TarHandler.h"
+#include "TarIn.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NTar {
+
+static const char *kUnexpectedEnd = "Unexpected end of archive";
+
+static const STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidIsDir, VT_BOOL},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMTime, VT_FILETIME},
+  { NULL, kpidPosixAttrib, VT_UI4},
+  { NULL, kpidUser, VT_BSTR},
+  { NULL, kpidGroup, VT_BSTR},
+  { NULL, kpidLink, VT_BSTR}
+};
+
+static const STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidPhySize, VT_UI8},
+  { NULL, kpidHeadersSize, VT_UI8}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidPhySize: if (_phySizeDefined) prop = _phySize; break;
+    case kpidHeadersSize: if (_phySizeDefined) prop = _headersSize; break;
+    case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+HRESULT CHandler::ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &item)
+{
+  item.HeaderPos = _phySize;
+  RINOK(ReadItem(stream, filled, item, _errorMessage));
+  _phySize += item.HeaderSize;
+  _headersSize += item.HeaderSize;
+  return S_OK;
+}
+
+HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
+{
+  UInt64 endPos = 0;
+  {
+    RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));
+    RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
+  }
+  
+  _phySizeDefined = true;
+  for (;;)
+  {
+    CItemEx item;
+    bool filled;
+    RINOK(ReadItem2(stream, filled, item));
+    if (!filled)
+      break;
+    _items.Add(item);
+    
+    RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &_phySize));
+    if (_phySize > endPos)
+    {
+      _errorMessage = kUnexpectedEnd;
+      break;
+    }
+    /*
+    if (_phySize == endPos)
+    {
+      _errorMessage = "There are no trailing zero-filled records";
+      break;
+    }
+    */
+    if (callback != NULL)
+    {
+      if (_items.Size() == 1)
+      {
+        RINOK(callback->SetTotal(NULL, &endPos));
+      }
+      if (_items.Size() % 100 == 0)
+      {
+        UInt64 numFiles = _items.Size();
+        RINOK(callback->SetCompleted(&numFiles, &_phySize));
+      }
+    }
+  }
+
+  if (_items.Size() == 0)
+  {
+    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
+    if (!callback)
+      return S_FALSE;
+    callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
+    if (!openVolumeCallback)
+      return S_FALSE;
+    NCOM::CPropVariant prop;
+    if (openVolumeCallback->GetProperty(kpidName, &prop) != S_OK)
+      return S_FALSE;
+    if (prop.vt != VT_BSTR)
+      return S_FALSE;
+    UString baseName = prop.bstrVal;
+    baseName = baseName.Right(4);
+    if (baseName.CompareNoCase(L".tar") != 0)
+      return S_FALSE;
+  }
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openArchiveCallback)
+{
+  COM_TRY_BEGIN
+  {
+    Close();
+    RINOK(Open2(stream, openArchiveCallback));
+    _stream = stream;
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
+{
+  Close();
+  _seqStream = stream;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _errorMessage.Empty();
+  _phySizeDefined = false;
+  _phySize = 0;
+  _headersSize = 0;
+  _curIndex = 0;
+  _latestIsRead = false;
+  _items.Clear();
+  _seqStream.Release();
+  _stream.Release();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = (_stream ? _items.Size() : (UInt32)(Int32)-1);
+  return S_OK;
+}
+
+CHandler::CHandler()
+{
+  copyCoderSpec = new NCompress::CCopyCoder();
+  copyCoder = copyCoderSpec;
+}
+
+HRESULT CHandler::SkipTo(UInt32 index)
+{
+  while (_curIndex < index || !_latestIsRead)
+  {
+    if (_latestIsRead)
+    {
+      UInt64 packSize = _latestItem.GetPackSize();
+      RINOK(copyCoderSpec->Code(_seqStream, NULL, &packSize, &packSize, NULL));
+      _phySize += copyCoderSpec->TotalSize;
+      if (copyCoderSpec->TotalSize != packSize)
+      {
+        _errorMessage = kUnexpectedEnd;
+        return S_FALSE;
+      }
+      _latestIsRead = false;
+      _curIndex++;
+    }
+    else
+    {
+      bool filled;
+      RINOK(ReadItem2(_seqStream, filled, _latestItem));
+      if (!filled)
+      {
+        _phySizeDefined = true;
+        return E_INVALIDARG;
+      }
+      _latestIsRead = true;
+    }
+  }
+  return S_OK;
+}
+
+static UString TarStringToUnicode(const AString &s)
+{
+  return MultiByteToUnicodeString(s, CP_OEMCP);
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+
+  const CItemEx *item;
+  if (_stream)
+    item = &_items[index];
+  else
+  {
+    if (index < _curIndex)
+      return E_INVALIDARG;
+    else
+    {
+      RINOK(SkipTo(index));
+      item = &_latestItem;
+    }
+  }
+
+  switch(propID)
+  {
+    case kpidPath: prop = NItemName::GetOSName2(TarStringToUnicode(item->Name)); break;
+    case kpidIsDir: prop = item->IsDir(); break;
+    case kpidSize: prop = item->GetUnpackSize(); break;
+    case kpidPackSize: prop = item->GetPackSize(); break;
+    case kpidMTime:
+      if (item->MTime != 0)
+      {
+        FILETIME ft;
+        NTime::UnixTimeToFileTime(item->MTime, ft);
+        prop = ft;
+      }
+      break;
+    case kpidPosixAttrib: prop = item->Mode; break;
+    case kpidUser: prop = TarStringToUnicode(item->User); break;
+    case kpidGroup: prop = TarStringToUnicode(item->Group); break;
+    case kpidLink: prop = TarStringToUnicode(item->LinkName); break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  ISequentialInStream *stream = _seqStream;
+  bool seqMode = (_stream == NULL);
+  if (!seqMode)
+    stream = _stream;
+
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _items.Size();
+  if (_stream && numItems == 0)
+    return S_OK;
+  UInt64 totalSize = 0;
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+    totalSize += _items[allFilesMode ? i : indices[i]].GetUnpackSize();
+  extractCallback->SetTotal(totalSize);
+
+  UInt64 totalPackSize;
+  totalSize = totalPackSize = 0;
+  
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<ISequentialInStream> inStream(streamSpec);
+  streamSpec->SetStream(stream);
+
+  CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+
+  for (i = 0; i < numItems || seqMode; i++)
+  {
+    lps->InSize = totalPackSize;
+    lps->OutSize = totalSize;
+    RINOK(lps->SetCur());
+    CMyComPtr<ISequentialOutStream> realOutStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    Int32 index = allFilesMode ? i : indices[i];
+    const CItemEx *item;
+    if (seqMode)
+    {
+      HRESULT res = SkipTo(index);
+      if (res == E_INVALIDARG)
+        break;
+      RINOK(res);
+      item = &_latestItem;
+    }
+    else
+      item = &_items[index];
+
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+    UInt64 unpackSize = item->GetUnpackSize();
+    totalSize += unpackSize;
+    totalPackSize += item->GetPackSize();
+    if (item->IsDir())
+    {
+      RINOK(extractCallback->PrepareOperation(askMode));
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+      continue;
+    }
+    bool skipMode = false;
+    if (!testMode && !realOutStream)
+    {
+      if (!seqMode)
+        continue;
+      skipMode = true;
+      askMode = NExtract::NAskMode::kSkip;
+    }
+    RINOK(extractCallback->PrepareOperation(askMode));
+
+    outStreamSpec->SetStream(realOutStream);
+    realOutStream.Release();
+    outStreamSpec->Init(skipMode ? 0 : unpackSize, true);
+
+    if (item->IsLink())
+    {
+      RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Length()));
+    }
+    else
+    {
+      if (!seqMode)
+      {
+        RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL));
+      }
+      streamSpec->Init(item->GetPackSize());
+      RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
+    }
+    if (seqMode)
+    {
+      _latestIsRead = false;
+      _curIndex++;
+    }
+    outStreamSpec->ReleaseStream();
+    RINOK(extractCallback->SetOperationResult(outStreamSpec->GetRem() == 0 ?
+        NExtract::NOperationResult::kOK:
+        NExtract::NOperationResult::kDataError));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+  COM_TRY_BEGIN
+  const CItemEx &item = _items[index];
+  if (item.IsLink())
+  {
+    CBufInStream *streamSpec = new CBufInStream;
+    CMyComPtr<IInStream> streamTemp = streamSpec;
+    streamSpec->Init((const Byte *)(const char *)item.LinkName, item.LinkName.Length(), (IInArchive *)this);
+    *stream = streamTemp.Detach();
+    return S_OK;
+  }
+  return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream);
+  COM_TRY_END
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHandler.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHandler.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHandler.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHandler.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,61 @@
+// TarHandler.h
+
+#ifndef __TAR_HANDLER_H
+#define __TAR_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+
+#include "../../Compress/CopyCoder.h"
+
+#include "TarItem.h"
+
+namespace NArchive {
+namespace NTar {
+
+class CHandler:
+  public IInArchive,
+  public IArchiveOpenSeq,
+  public IInArchiveGetStream,
+  public IOutArchive,
+  public CMyUnknownImp
+{
+  CObjectVector<CItemEx> _items;
+  CMyComPtr<IInStream> _stream;
+  CMyComPtr<ISequentialInStream> _seqStream;
+  
+  UInt32 _curIndex;
+  bool _latestIsRead;
+  CItemEx _latestItem;
+
+  UInt64 _phySize;
+  UInt64 _headersSize;
+  bool _phySizeDefined;
+  AString _errorMessage;
+
+  NCompress::CCopyCoder *copyCoderSpec;
+  CMyComPtr<ICompressCoder> copyCoder;
+
+  HRESULT ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo);
+  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
+  HRESULT SkipTo(UInt32 index);
+
+public:
+  MY_UNKNOWN_IMP4(
+    IInArchive,
+    IArchiveOpenSeq,
+    IInArchiveGetStream,
+    IOutArchive
+  )
+
+  INTERFACE_IInArchive(;)
+  INTERFACE_IOutArchive(;)
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+
+  CHandler();
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHandlerOut.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHandlerOut.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHandlerOut.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,122 @@
+// TarHandlerOut.cpp
+
+#include "StdAfx.h"
+
+#include "Common/ComTry.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "TarHandler.h"
+#include "TarUpdate.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NTar {
+
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
+{
+  *type = NFileTimeType::kUnix;
+  return S_OK;
+}
+
+static HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res)
+{
+  NCOM::CPropVariant prop;
+  RINOK(callback->GetProperty(index, propId, &prop));
+  if (prop.vt == VT_BSTR)
+    res = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP);
+  else if (prop.vt != VT_EMPTY)
+    return E_INVALIDARG;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+    IArchiveUpdateCallback *callback)
+{
+  COM_TRY_BEGIN
+  if ((_stream && !_errorMessage.IsEmpty()) || _seqStream)
+    return E_NOTIMPL;
+  CObjectVector<CUpdateItem> updateItems;
+  for (UInt32 i = 0; i < numItems; i++)
+  {
+    CUpdateItem ui;
+    Int32 newData;
+    Int32 newProps;
+    UInt32 indexInArchive;
+    if (!callback)
+      return E_FAIL;
+    RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
+    ui.NewProps = IntToBool(newProps);
+    ui.NewData = IntToBool(newData);
+    ui.IndexInArchive = indexInArchive;
+    ui.IndexInClient = i;
+
+    if (IntToBool(newProps))
+    {
+      {
+        NCOM::CPropVariant prop;
+        RINOK(callback->GetProperty(i, kpidIsDir, &prop));
+        if (prop.vt == VT_EMPTY)
+          ui.IsDir = false;
+        else if (prop.vt != VT_BOOL)
+          return E_INVALIDARG;
+        else
+          ui.IsDir = (prop.boolVal != VARIANT_FALSE);
+      }
+
+      {
+        NCOM::CPropVariant prop;
+        RINOK(callback->GetProperty(i, kpidPosixAttrib, &prop));
+        if (prop.vt == VT_EMPTY)
+          ui.Mode = 0777 | (ui.IsDir ? 0040000 : 0100000);
+        else if (prop.vt != VT_UI4)
+          return E_INVALIDARG;
+        else
+          ui.Mode = prop.ulVal;
+      }
+      {
+        NCOM::CPropVariant prop;
+        RINOK(callback->GetProperty(i, kpidMTime, &prop));
+        if (prop.vt == VT_EMPTY)
+          ui.Time = 0;
+        else if (prop.vt != VT_FILETIME)
+          return E_INVALIDARG;
+        else if (!NTime::FileTimeToUnixTime(prop.filetime, ui.Time))
+          ui.Time = 0;
+      }
+      {
+        NCOM::CPropVariant prop;
+        RINOK(callback->GetProperty(i, kpidPath, &prop));
+        if (prop.vt == VT_BSTR)
+          ui.Name = UnicodeStringToMultiByte(NItemName::MakeLegalName(prop.bstrVal), CP_OEMCP);
+        else if (prop.vt != VT_EMPTY)
+          return E_INVALIDARG;
+        if (ui.IsDir)
+          ui.Name += '/';
+      }
+      RINOK(GetPropString(callback, i, kpidUser, ui.User));
+      RINOK(GetPropString(callback, i, kpidGroup, ui.Group));
+    }
+    if (IntToBool(newData))
+    {
+      NCOM::CPropVariant prop;
+      RINOK(callback->GetProperty(i, kpidSize, &prop));
+      if (prop.vt != VT_UI8)
+        return E_INVALIDARG;
+      ui.Size = prop.uhVal.QuadPart;
+      /*
+      // now we support GNU extension for big files
+      if (ui.Size >= ((UInt64)1 << 33))
+        return E_INVALIDARG;
+      */
+    }
+    updateItems.Add(ui);
+  }
+  return UpdateArchive(_stream, outStream, _items, updateItems, callback);
+  COM_TRY_END
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHeader.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHeader.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHeader.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHeader.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,25 @@
+// Archive/Tar/Header.h
+
+#include "StdAfx.h"
+
+#include "TarHeader.h"
+
+namespace NArchive {
+namespace NTar {
+namespace NFileHeader {
+
+  // The checksum field is filled with this while the checksum is computed.
+  const char *kCheckSumBlanks = "        ";   // 8 blanks, no null
+
+  const char *kLongLink = "././@LongLink";
+  const char *kLongLink2 = "@LongLink";
+
+  // The magic field is filled with this if uname and gname are valid.
+  namespace NMagic
+  {
+    const char *kUsTar  = "ustar"; // 5 chars
+    const char *kGNUTar = "GNUtar "; // 7 chars and a null
+    const char *kEmpty = "\0\0\0\0\0\0\0\0"; // 7 chars and a null
+  }
+
+}}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHeader.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHeader.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHeader.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarHeader.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,108 @@
+// Archive/Tar/Header.h
+
+#ifndef __ARCHIVE_TAR_HEADER_H
+#define __ARCHIVE_TAR_HEADER_H
+
+#include "Common/Types.h"
+
+namespace NArchive {
+namespace NTar {
+
+namespace NFileHeader
+{
+  const int kRecordSize = 512;
+  const int kNameSize = 100;
+  const int kUserNameSize = 32;
+  const int kGroupNameSize = 32;
+  const int kPrefixSize = 155;
+
+  /*
+  struct CHeader
+  {
+    char Name[kNameSize];
+    char Mode[8];
+    char UID[8];
+    char GID[8];
+    char Size[12];
+    char ModificationTime[12];
+    char CheckSum[8];
+    char LinkFlag;
+    char LinkName[kNameSize];
+    char Magic[8];
+    char UserName[kUserNameSize];
+    char GroupName[kGroupNameSize];
+    char DeviceMajor[8];
+    char DeviceMinor[8];
+    char Prefix[155];
+  };
+  union CRecord
+  {
+    CHeader Header;
+    Byte Padding[kRecordSize];
+  };
+  */
+
+  namespace NMode
+  {
+    const int kSetUID   = 04000;  // Set UID on execution
+    const int kSetGID   = 02000;  // Set GID on execution
+    const int kSaveText = 01000;  // Save text (sticky bit)
+  }
+
+  namespace NFilePermissions
+  {
+    const int kUserRead     = 00400;  // read by owner
+    const int kUserWrite    = 00200;  // write by owner
+    const int kUserExecute  = 00100;  // execute/search by owner
+    const int kGroupRead    = 00040;  // read by group
+    const int kGroupWrite   = 00020;  // write by group
+    const int kGroupExecute = 00010;  // execute/search by group
+    const int kOtherRead    = 00004;  // read by other
+    const int kOtherWrite   = 00002;  // write by other
+    const int kOtherExecute = 00001;  // execute/search by other
+  }
+
+
+  // The linkflag defines the type of file
+  namespace NLinkFlag
+  {
+    const char kOldNormal    = '\0'; // Normal disk file, Unix compatible
+    const char kNormal       = '0'; // Normal disk file
+    const char kLink         = '1'; // Link to previously dumped file
+    const char kSymbolicLink = '2'; // Symbolic link
+    const char kCharacter    = '3'; // Character special file
+    const char kBlock        = '4'; // Block special file
+    const char kDirectory    = '5'; // Directory
+    const char kFIFO         = '6'; // FIFO special file
+    const char kContiguous   = '7'; // Contiguous file
+
+    const char kDumpDir       = 'D'; /* GNUTYPE_DUMPDIR.
+      data: list of files created by the --incremental (-G) option
+      Each file name is preceded by either
+        - 'Y' (file should be in this archive)
+        - 'N' (file is a directory, or is not stored in the archive.)
+        Each file name is terminated by a null + an additional null after
+        the last file name. */
+
+  }
+  // Further link types may be defined later.
+
+  // The checksum field is filled with this while the checksum is computed.
+  extern const char *kCheckSumBlanks;//   = "        ";   // 8 blanks, no null
+
+  extern const char *kLongLink;  //   = "././@LongLink";
+  extern const char *kLongLink2; //   = "@LongLink";
+
+  // The magic field is filled with this if uname and gname are valid.
+  namespace NMagic
+  {
+    extern const char *kUsTar; //   = "ustar"; // 5 chars
+    extern const char *kGNUTar; //  = "GNUtar "; // 7 chars and a null
+    extern const char *kEmpty; //  = "GNUtar "; // 7 chars and a null
+  }
+
+}
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarIn.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarIn.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarIn.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarIn.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,207 @@
+// TarIn.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/CpuArch.h"
+
+#include "Common/StringToInt.h"
+
+#include "../../Common/StreamUtils.h"
+
+#include "TarIn.h"
+
+namespace NArchive {
+namespace NTar {
+ 
+static void MyStrNCpy(char *dest, const char *src, int size)
+{
+  for (int i = 0; i < size; i++)
+  {
+    char c = src[i];
+    dest[i] = c;
+    if (c == 0)
+      break;
+  }
+}
+
+static bool OctalToNumber(const char *srcString, int size, UInt64 &res)
+{
+  char sz[32];
+  MyStrNCpy(sz, srcString, size);
+  sz[size] = 0;
+  const char *end;
+  int i;
+  for (i = 0; sz[i] == ' '; i++);
+  res = ConvertOctStringToUInt64(sz + i, &end);
+  return (*end == ' ' || *end == 0);
+}
+
+static bool OctalToNumber32(const char *srcString, int size, UInt32 &res)
+{
+  UInt64 res64;
+  if (!OctalToNumber(srcString, size, res64))
+    return false;
+  res = (UInt32)res64;
+  return (res64 <= 0xFFFFFFFF);
+}
+
+#define RIF(x) { if (!(x)) return S_FALSE; }
+
+static bool IsRecordLast(const char *buf)
+{
+  for (int i = 0; i < NFileHeader::kRecordSize; i++)
+    if (buf[i] != 0)
+      return false;
+  return true;
+}
+
+static void ReadString(const char *s, int size, AString &result)
+{
+  char temp[NFileHeader::kRecordSize + 1];
+  MyStrNCpy(temp, s, size);
+  temp[size] = '\0';
+  result = temp;
+}
+
+static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error)
+{
+  char buf[NFileHeader::kRecordSize];
+  char *p = buf;
+
+  error.Empty();
+  filled = false;
+
+  bool thereAreEmptyRecords = false;
+  for (;;)
+  {
+    size_t processedSize = NFileHeader::kRecordSize;
+    RINOK(ReadStream(stream, buf, &processedSize));
+    if (processedSize == 0)
+    {
+      if (!thereAreEmptyRecords )
+        error = "There are no trailing zero-filled records";
+      return S_OK;
+    }
+    if (processedSize != NFileHeader::kRecordSize)
+    {
+      error = "There is no correct record at the end of archive";
+      return S_OK;
+    }
+    item.HeaderSize += NFileHeader::kRecordSize;
+    if (!IsRecordLast(buf))
+      break;
+    thereAreEmptyRecords = true;
+  }
+  if (thereAreEmptyRecords)
+  {
+    error = "There are data after end of archive";
+    return S_OK;
+  }
+  
+  ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize;
+
+  RIF(OctalToNumber32(p, 8, item.Mode)); p += 8;
+
+  if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; p += 8;
+  if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; p += 8;
+
+  if (GetBe32(p) == (UInt32)1 << 31)
+  {
+    // GNU extension
+    item.Size = GetBe64(p + 4);
+  }
+  else
+  {
+    RIF(OctalToNumber(p, 12, item.Size));
+  }
+  p += 12;
+  RIF(OctalToNumber32(p, 12, item.MTime)); p += 12;
+  
+  UInt32 checkSum;
+  RIF(OctalToNumber32(p, 8, checkSum));
+  memcpy(p, NFileHeader::kCheckSumBlanks, 8); p += 8;
+
+  item.LinkFlag = *p++;
+
+  ReadString(p, NFileHeader::kNameSize, item.LinkName); p += NFileHeader::kNameSize;
+
+  memcpy(item.Magic, p, 8); p += 8;
+
+  ReadString(p, NFileHeader::kUserNameSize, item.User); p += NFileHeader::kUserNameSize;
+  ReadString(p, NFileHeader::kGroupNameSize, item.Group); p += NFileHeader::kGroupNameSize;
+
+  item.DeviceMajorDefined = (p[0] != 0); RIF(OctalToNumber32(p, 8, item.DeviceMajor)); p += 8;
+  item.DeviceMinorDefined = (p[0] != 0); RIF(OctalToNumber32(p, 8, item.DeviceMinor)); p += 8;
+
+  AString prefix;
+  ReadString(p, NFileHeader::kPrefixSize, prefix);
+  p += NFileHeader::kPrefixSize;
+  if (!prefix.IsEmpty() && item.IsMagic() &&
+      (item.LinkFlag != 'L' /* || prefix != "00000000000" */ ))
+    item.Name = prefix + AString('/') + item.Name;
+
+  if (item.LinkFlag == NFileHeader::NLinkFlag::kLink)
+    item.Size = 0;
+ 
+  UInt32 checkSumReal = 0;
+  for (int i = 0; i < NFileHeader::kRecordSize; i++)
+    checkSumReal += (Byte)buf[i];
+  
+  if (checkSumReal != checkSum)
+    return S_FALSE;
+
+  filled = true;
+  return S_OK;
+}
+
+HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error)
+{
+  item.HeaderSize = 0;
+  bool flagL = false;
+  bool flagK = false;
+  AString nameL;
+  AString nameK;
+  for (;;)
+  {
+    RINOK(GetNextItemReal(stream, filled, item, error));
+    if (!filled)
+      return S_OK;
+    if (item.LinkFlag == 'L' || // NEXT file has a long name
+        item.LinkFlag == 'K') // NEXT file has a long linkname
+    {
+      AString *name;
+      if (item.LinkFlag == 'L')
+        { if (flagL) return S_FALSE; flagL = true; name = &nameL; }
+      else
+        { if (flagK) return S_FALSE; flagK = true; name = &nameK; }
+
+      if (item.Name.Compare(NFileHeader::kLongLink) != 0 &&
+          item.Name.Compare(NFileHeader::kLongLink2) != 0)
+        return S_FALSE;
+      if (item.Size > (1 << 14))
+        return S_FALSE;
+      int packSize = (int)item.GetPackSize();
+      char *buf = name->GetBuffer(packSize);
+      RINOK(ReadStream_FALSE(stream, buf, packSize));
+      item.HeaderSize += packSize;
+      buf[(size_t)item.Size] = '\0';
+      name->ReleaseBuffer();
+      continue;
+    }
+    if (item.LinkFlag == 'g' || item.LinkFlag == 'x' || item.LinkFlag == 'X')
+    {
+      // pax Extended Header
+    }
+    else if (item.LinkFlag == NFileHeader::NLinkFlag::kDumpDir)
+    {
+      // GNU Extensions to the Archive Format
+    }
+    else if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0))
+      return S_FALSE;
+    if (flagL) item.Name = nameL;
+    if (flagK) item.LinkName = nameK;
+    return S_OK;
+  }
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarIn.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarIn.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarIn.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarIn.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,17 @@
+// TarIn.h
+
+#ifndef __ARCHIVE_TAR_IN_H
+#define __ARCHIVE_TAR_IN_H
+
+#include "../../IStream.h"
+
+#include "TarItem.h"
+
+namespace NArchive {
+namespace NTar {
+  
+HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo, AString &error);
+
+}}
+  
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarItem.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarItem.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarItem.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarItem.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,72 @@
+// TarItem.h
+
+#ifndef __ARCHIVE_TAR_ITEM_H
+#define __ARCHIVE_TAR_ITEM_H
+
+#include "../Common/ItemNameUtils.h"
+
+#include "TarHeader.h"
+
+namespace NArchive {
+namespace NTar {
+
+struct CItem
+{
+  AString Name;
+  UInt64 Size;
+
+  UInt32 Mode;
+  UInt32 UID;
+  UInt32 GID;
+  UInt32 MTime;
+  UInt32 DeviceMajor;
+  UInt32 DeviceMinor;
+
+  AString LinkName;
+  AString User;
+  AString Group;
+
+  char Magic[8];
+  char LinkFlag;
+  bool DeviceMajorDefined;
+  bool DeviceMinorDefined;
+
+  bool IsLink() const { return LinkFlag == NFileHeader::NLinkFlag::kSymbolicLink && (Size == 0); }
+  UInt64 GetUnpackSize() const { return IsLink() ? LinkName.Length() : Size; }
+
+  bool IsDir() const
+  {
+    switch(LinkFlag)
+    {
+      case NFileHeader::NLinkFlag::kDirectory:
+      case NFileHeader::NLinkFlag::kDumpDir:
+        return true;
+      case NFileHeader::NLinkFlag::kOldNormal:
+      case NFileHeader::NLinkFlag::kNormal:
+        return NItemName::HasTailSlash(Name, CP_OEMCP);
+    }
+    return false;
+  }
+
+  bool IsMagic() const
+  {
+    for (int i = 0; i < 5; i++)
+      if (Magic[i] != NFileHeader::NMagic::kUsTar[i])
+        return false;
+    return true;
+  }
+
+  UInt64 GetPackSize() const { return (Size + 0x1FF) & (~((UInt64)0x1FF)); }
+};
+
+struct CItemEx: public CItem
+{
+  UInt64 HeaderPos;
+  unsigned HeaderSize;
+  UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; }
+  UInt64 GetFullSize() const { return HeaderSize + Size; }
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarOut.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarOut.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarOut.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarOut.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,187 @@
+// TarOut.cpp
+
+#include "StdAfx.h"
+
+#include "Common/IntToString.h"
+
+#include "../../Common/StreamUtils.h"
+
+#include "TarOut.h"
+
+namespace NArchive {
+namespace NTar {
+
+HRESULT COutArchive::WriteBytes(const void *buffer, UInt32 size)
+{
+  return WriteStream(m_Stream, buffer, size);
+}
+
+void COutArchive::Create(ISequentialOutStream *outStream)
+{
+  m_Stream = outStream;
+}
+
+static AString MakeOctalString(UInt64 value)
+{
+  char s[32];
+  ConvertUInt64ToString(value, s, 8);
+  return AString(s) + ' ';
+}
+
+static void MyStrNCpy(char *dest, const char *src, int size)
+{
+  for (int i = 0; i < size; i++)
+  {
+    char c = src[i];
+    dest[i] = c;
+    if (c == 0)
+      break;
+  }
+}
+
+static bool MakeOctalString8(char *s, UInt32 value)
+{
+  AString tempString = MakeOctalString(value);
+
+  const int kMaxSize = 8;
+  if (tempString.Length() >= kMaxSize)
+    return false;
+  int numSpaces = kMaxSize - (tempString.Length() + 1);
+  for(int i = 0; i < numSpaces; i++)
+    s[i] = ' ';
+  MyStringCopy(s + numSpaces, (const char *)tempString);
+  return true;
+}
+
+static void MakeOctalString12(char *s, UInt64 value)
+{
+  AString tempString  = MakeOctalString(value);
+  const int kMaxSize = 12;
+  if (tempString.Length() > kMaxSize)
+  {
+    // GNU extension;
+    s[0] = (char)(Byte)0x80;
+    s[1] = s[2] = s[3] = 0;
+    for (int i = 0; i < 8; i++, value <<= 8)
+      s[4 + i] = (char)(value >> 56);
+    return;
+  }
+  int numSpaces = kMaxSize - tempString.Length();
+  for(int i = 0; i < numSpaces; i++)
+    s[i] = ' ';
+  memmove(s + numSpaces, (const char *)tempString, tempString.Length());
+}
+
+static bool CopyString(char *dest, const AString &src, int maxSize)
+{
+  if (src.Length() >= maxSize)
+    return false;
+  MyStringCopy(dest, (const char *)src);
+  return true;
+}
+
+#define RETURN_IF_NOT_TRUE(x) { if (!(x)) return E_FAIL; }
+
+HRESULT COutArchive::WriteHeaderReal(const CItem &item)
+{
+  char record[NFileHeader::kRecordSize];
+  char *cur = record;
+  int i;
+  for (i = 0; i < NFileHeader::kRecordSize; i++)
+    record[i] = 0;
+
+  // RETURN_IF_NOT_TRUE(CopyString(header.Name, item.Name, NFileHeader::kNameSize));
+  if (item.Name.Length() > NFileHeader::kNameSize)
+    return E_FAIL;
+  MyStrNCpy(cur, item.Name, NFileHeader::kNameSize);
+  cur += NFileHeader::kNameSize;
+
+  RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.Mode)); cur += 8;
+  RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.UID)); cur += 8;
+  RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.GID)); cur += 8;
+
+  MakeOctalString12(cur, item.Size); cur += 12;
+  MakeOctalString12(cur, item.MTime); cur += 12;
+  
+  memmove(cur, NFileHeader::kCheckSumBlanks, 8);
+  cur += 8;
+
+  *cur++ = item.LinkFlag;
+
+  RETURN_IF_NOT_TRUE(CopyString(cur, item.LinkName, NFileHeader::kNameSize));
+  cur += NFileHeader::kNameSize;
+
+  memmove(cur, item.Magic, 8);
+  cur += 8;
+
+  RETURN_IF_NOT_TRUE(CopyString(cur, item.User, NFileHeader::kUserNameSize));
+  cur += NFileHeader::kUserNameSize;
+  RETURN_IF_NOT_TRUE(CopyString(cur, item.Group, NFileHeader::kGroupNameSize));
+  cur += NFileHeader::kGroupNameSize;
+
+
+  if (item.DeviceMajorDefined)
+    RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMajor));
+  cur += 8;
+
+  if (item.DeviceMinorDefined)
+    RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMinor));
+  cur += 8;
+
+
+  UInt32 checkSumReal = 0;
+  for(i = 0; i < NFileHeader::kRecordSize; i++)
+    checkSumReal += Byte(record[i]);
+
+  RETURN_IF_NOT_TRUE(MakeOctalString8(record + 148, checkSumReal));
+
+  return WriteBytes(record, NFileHeader::kRecordSize);
+}
+
+HRESULT COutArchive::WriteHeader(const CItem &item)
+{
+  int nameSize = item.Name.Length();
+  if (nameSize < NFileHeader::kNameSize)
+    return WriteHeaderReal(item);
+
+  CItem modifiedItem = item;
+  int nameStreamSize = nameSize + 1;
+  modifiedItem.Size = nameStreamSize;
+  modifiedItem.LinkFlag = 'L';
+  modifiedItem.Name = NFileHeader::kLongLink;
+  modifiedItem.LinkName.Empty();
+  RINOK(WriteHeaderReal(modifiedItem));
+  RINOK(WriteBytes(item.Name, nameStreamSize));
+  RINOK(FillDataResidual(nameStreamSize));
+
+  modifiedItem = item;
+  modifiedItem.Name = item.Name.Left(NFileHeader::kNameSize - 1);
+  return WriteHeaderReal(modifiedItem);
+}
+
+HRESULT COutArchive::FillDataResidual(UInt64 dataSize)
+{
+  UInt32 lastRecordSize = UInt32(dataSize & (NFileHeader::kRecordSize - 1));
+  if (lastRecordSize == 0)
+    return S_OK;
+  UInt32 residualSize = NFileHeader::kRecordSize - lastRecordSize;
+  Byte residualBytes[NFileHeader::kRecordSize];
+  for (UInt32 i = 0; i < residualSize; i++)
+    residualBytes[i] = 0;
+  return WriteBytes(residualBytes, residualSize);
+}
+
+HRESULT COutArchive::WriteFinishHeader()
+{
+  Byte record[NFileHeader::kRecordSize];
+  int i;
+  for (i = 0; i < NFileHeader::kRecordSize; i++)
+    record[i] = 0;
+  for (i = 0; i < 2; i++)
+  {
+    RINOK(WriteBytes(record, NFileHeader::kRecordSize));
+  }
+  return S_OK;
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarOut.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarOut.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarOut.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarOut.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,28 @@
+// Archive/TarOut.h
+
+#ifndef __ARCHIVE_TAR_OUT_H
+#define __ARCHIVE_TAR_OUT_H
+
+#include "TarItem.h"
+
+#include "Common/MyCom.h"
+#include "../../IStream.h"
+
+namespace NArchive {
+namespace NTar {
+
+class COutArchive
+{
+  CMyComPtr<ISequentialOutStream> m_Stream;
+  HRESULT WriteBytes(const void *buffer, UInt32 size);
+public:
+  void Create(ISequentialOutStream *outStream);
+  HRESULT WriteHeaderReal(const CItem &item);
+  HRESULT WriteHeader(const CItem &item);
+  HRESULT FillDataResidual(UInt64 dataSize);
+  HRESULT WriteFinishHeader();
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarRegister.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarRegister.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarRegister.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarRegister.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,18 @@
+// TarRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterArc.h"
+
+#include "TarHandler.h"
+static IInArchive *CreateArc() { return new NArchive::NTar::CHandler; }
+#ifndef EXTRACT_ONLY
+static IOutArchive *CreateArcOut() { return new NArchive::NTar::CHandler; }
+#else
+#define CreateArcOut 0
+#endif
+
+static CArcInfo g_ArcInfo =
+{ L"tar", L"tar", 0, 0xEE, { 'u', 's', 't', 'a', 'r' }, 5, false, CreateArc, CreateArcOut };
+
+REGISTER_ARC(Tar)

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarUpdate.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarUpdate.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarUpdate.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarUpdate.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,139 @@
+// TarUpdate.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/ProgressUtils.h"
+
+#include "../../Compress/CopyCoder.h"
+
+#include "TarOut.h"
+#include "TarUpdate.h"
+
+namespace NArchive {
+namespace NTar {
+
+HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
+    const CObjectVector<NArchive::NTar::CItemEx> &inputItems,
+    const CObjectVector<CUpdateItem> &updateItems,
+    IArchiveUpdateCallback *updateCallback)
+{
+  COutArchive outArchive;
+  outArchive.Create(outStream);
+
+  UInt64 complexity = 0;
+
+  int i;
+  for(i = 0; i < updateItems.Size(); i++)
+  {
+    const CUpdateItem &ui = updateItems[i];
+    if (ui.NewData)
+      complexity += ui.Size;
+    else
+      complexity += inputItems[ui.IndexInArchive].GetFullSize();
+  }
+
+  RINOK(updateCallback->SetTotal(complexity));
+
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(updateCallback, true);
+
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);
+  streamSpec->SetStream(inStream);
+
+  complexity = 0;
+
+  for(i = 0; i < updateItems.Size(); i++)
+  {
+    lps->InSize = lps->OutSize = complexity;
+    RINOK(lps->SetCur());
+
+    const CUpdateItem &ui = updateItems[i];
+    CItem item;
+    if (ui.NewProps)
+    {
+      item.Mode = ui.Mode;
+      item.Name = ui.Name;
+      item.User = ui.User;
+      item.Group = ui.Group;
+      if (ui.IsDir)
+      {
+        item.LinkFlag = NFileHeader::NLinkFlag::kDirectory;
+        item.Size = 0;
+      }
+      else
+      {
+        item.LinkFlag = NFileHeader::NLinkFlag::kNormal;
+        item.Size = ui.Size;
+      }
+      item.MTime = ui.Time;
+      item.DeviceMajorDefined = false;
+      item.DeviceMinorDefined = false;
+      item.UID = 0;
+      item.GID = 0;
+      memmove(item.Magic, NFileHeader::NMagic::kEmpty, 8);
+    }
+    else
+      item = inputItems[ui.IndexInArchive];
+
+    if (ui.NewData)
+    {
+      item.Size = ui.Size;
+      if (item.Size == (UInt64)(Int64)-1)
+        return E_INVALIDARG;
+    }
+    else
+      item.Size = inputItems[ui.IndexInArchive].Size;
+  
+    if (ui.NewData)
+    {
+      CMyComPtr<ISequentialInStream> fileInStream;
+      HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);
+      if (res != S_FALSE)
+      {
+        RINOK(res);
+        RINOK(outArchive.WriteHeader(item));
+        if (!ui.IsDir)
+        {
+          RINOK(copyCoder->Code(fileInStream, outStream, NULL, NULL, progress));
+          if (copyCoderSpec->TotalSize != item.Size)
+            return E_FAIL;
+          RINOK(outArchive.FillDataResidual(item.Size));
+        }
+      }
+      complexity += ui.Size;
+      RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+    }
+    else
+    {
+      const CItemEx &existItem = inputItems[ui.IndexInArchive];
+      UInt64 size;
+      if (ui.NewProps)
+      {
+        RINOK(outArchive.WriteHeader(item));
+        RINOK(inStream->Seek(existItem.GetDataPosition(), STREAM_SEEK_SET, NULL));
+        size = existItem.Size;
+      }
+      else
+      {
+        RINOK(inStream->Seek(existItem.HeaderPos, STREAM_SEEK_SET, NULL));
+        size = existItem.GetFullSize();
+      }
+      streamSpec->Init(size);
+
+      RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress));
+      if (copyCoderSpec->TotalSize != size)
+        return E_FAIL;
+      RINOK(outArchive.FillDataResidual(existItem.Size));
+      complexity += size;
+    }
+  }
+  return outArchive.WriteFinishHeader();
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarUpdate.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarUpdate.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarUpdate.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Tar/TarUpdate.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,34 @@
+// TarUpdate.h
+
+#ifndef __TAR_UPDATE_H
+#define __TAR_UPDATE_H
+
+#include "../IArchive.h"
+#include "TarItem.h"
+
+namespace NArchive {
+namespace NTar {
+
+struct CUpdateItem
+{
+  int IndexInArchive;
+  int IndexInClient;
+  UInt32 Time;
+  UInt32 Mode;
+  UInt64 Size;
+  AString Name;
+  AString User;
+  AString Group;
+  bool NewData;
+  bool NewProps;
+  bool IsDir;
+};
+
+HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
+    const CObjectVector<CItemEx> &inputItems,
+    const CObjectVector<CUpdateItem> &updateItems,
+    IArchiveUpdateCallback *updateCallback);
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,451 @@
+// UdfHandler.cpp
+
+#include "StdAfx.h"
+
+#include "Common/ComTry.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/StreamObjects.h"
+
+#include "../../Compress/CopyCoder.h"
+
+#include "UdfHandler.h"
+
+namespace NArchive {
+namespace NUdf {
+
+void UdfTimeToFileTime(const CTime &t, NWindows::NCOM::CPropVariant &prop)
+{
+  UInt64 numSecs;
+  const Byte *d = t.Data;
+  if (!NWindows::NTime::GetSecondsSince1601(t.GetYear(), d[4], d[5], d[6], d[7], d[8], numSecs))
+    return;
+  if (t.IsLocal())
+    numSecs -= t.GetMinutesOffset() * 60;
+  FILETIME ft;
+  UInt64 v = (((numSecs * 100 + d[9]) * 100 + d[10]) * 100 + d[11]) * 10;
+  ft.dwLowDateTime = (UInt32)v;
+  ft.dwHighDateTime = (UInt32)(v >> 32);
+  prop = ft;
+}
+
+static STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidIsDir, VT_BOOL},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMTime, VT_FILETIME},
+  { NULL, kpidATime, VT_FILETIME}
+};
+
+static STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidComment, VT_BSTR},
+  { NULL, kpidClusterSize, VT_UI4},
+  { NULL, kpidCTime, VT_FILETIME}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidComment:
+    {
+      UString comment = _archive.GetComment();
+      if (!comment.IsEmpty())
+        prop = comment;
+      break;
+    }
+
+    case kpidClusterSize:
+      if (_archive.LogVols.Size() > 0)
+      {
+        UInt32 blockSize = _archive.LogVols[0].BlockSize;
+        int i;
+        for (i = 1; i < _archive.LogVols.Size(); i++)
+          if (_archive.LogVols[i].BlockSize != blockSize)
+            break;
+        if (i == _archive.LogVols.Size())
+          prop = blockSize;
+      }
+      break;
+
+    case kpidCTime:
+      if (_archive.LogVols.Size() == 1)
+      {
+        const CLogVol &vol = _archive.LogVols[0];
+        if (vol.FileSets.Size() >= 1)
+          UdfTimeToFileTime(vol.FileSets[0].RecodringTime, prop);
+      }
+      break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+class CProgressImp: public CProgressVirt
+{
+  CMyComPtr<IArchiveOpenCallback> _callback;
+  UInt64 _numFiles;
+  UInt64 _numBytes;
+public:
+  HRESULT SetTotal(UInt64 numBytes);
+  HRESULT SetCompleted(UInt64 numFiles, UInt64 numBytes);
+  HRESULT SetCompleted();
+  CProgressImp(IArchiveOpenCallback *callback): _callback(callback), _numFiles(0), _numBytes(0) {}
+};
+
+HRESULT CProgressImp::SetTotal(UInt64 numBytes)
+{
+  if (_callback)
+    return _callback->SetTotal(NULL, &numBytes);
+  return S_OK;
+}
+
+HRESULT CProgressImp::SetCompleted(UInt64 numFiles, UInt64 numBytes)
+{
+  _numFiles = numFiles;
+  _numBytes = numBytes;
+  return SetCompleted();
+}
+
+HRESULT CProgressImp::SetCompleted()
+{
+  if (_callback)
+    return _callback->SetCompleted(&_numFiles, &_numBytes);
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+    const UInt64 * /* maxCheckStartPosition */,
+    IArchiveOpenCallback *callback)
+{
+  COM_TRY_BEGIN
+  {
+    Close();
+    CProgressImp progressImp(callback);
+    RINOK(_archive.Open(stream, &progressImp));
+    bool showVolName = (_archive.LogVols.Size() > 1);
+    for (int volIndex = 0; volIndex < _archive.LogVols.Size(); volIndex++)
+    {
+      const CLogVol &vol = _archive.LogVols[volIndex];
+      bool showFileSetName = (vol.FileSets.Size() > 1);
+      for (int fsIndex = 0; fsIndex < vol.FileSets.Size(); fsIndex++)
+      {
+        const CFileSet &fs = vol.FileSets[fsIndex];
+        for (int i = ((showVolName || showFileSetName) ? 0 : 1); i < fs.Refs.Size(); i++)
+        {
+          CRef2 ref2;
+          ref2.Vol = volIndex;
+          ref2.Fs = fsIndex;
+          ref2.Ref = i;
+          _refs2.Add(ref2);
+        }
+      }
+    }
+    _inStream = stream;
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _inStream.Release();
+  _archive.Clear();
+  _refs2.Clear();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _refs2.Size();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  {
+    const CRef2 &ref2 = _refs2[index];
+    const CLogVol &vol = _archive.LogVols[ref2.Vol];
+    const CRef &ref = vol.FileSets[ref2.Fs].Refs[ref2.Ref];
+    const CFile &file = _archive.Files[ref.FileIndex];
+    const CItem &item = _archive.Items[file.ItemIndex];
+    switch(propID)
+    {
+      case kpidPath:  prop = _archive.GetItemPath(ref2.Vol, ref2.Fs, ref2.Ref,
+            _archive.LogVols.Size() > 1, vol.FileSets.Size() > 1); break;
+      case kpidIsDir:  prop = item.IsDir(); break;
+      case kpidSize:      if (!item.IsDir()) prop = (UInt64)item.Size; break;
+      case kpidPackSize:  if (!item.IsDir()) prop = (UInt64)item.NumLogBlockRecorded * vol.BlockSize; break;
+      case kpidMTime:  UdfTimeToFileTime(item.MTime, prop); break;
+      case kpidATime:  UdfTimeToFileTime(item.ATime, prop); break;
+    }
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+struct CSeekExtent
+{
+  UInt64 Phy;
+  UInt64 Virt;
+};
+
+class CExtentsStream:
+  public IInStream,
+  public CMyUnknownImp
+{
+  UInt64 _phyPos;
+  UInt64 _virtPos;
+  bool _needStartSeek;
+
+  HRESULT SeekToPhys() { return Stream->Seek(_phyPos, STREAM_SEEK_SET, NULL); }
+
+public:
+  CMyComPtr<IInStream> Stream;
+  CRecordVector<CSeekExtent> Extents;
+
+  MY_UNKNOWN_IMP1(IInStream)
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+  void ReleaseStream() { Stream.Release(); }
+
+  void Init()
+  {
+    _virtPos = 0;
+    _phyPos = 0;
+    _needStartSeek = true;
+  }
+
+};
+
+
+STDMETHODIMP CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  if (processedSize)
+    *processedSize = 0;
+  if (size > 0)
+  {
+    UInt64 totalSize = Extents.Back().Virt;
+    if (_virtPos >= totalSize)
+      return (_virtPos == totalSize) ? S_OK : E_FAIL;
+    int left = 0, right = Extents.Size() - 1;
+    for (;;)
+    {
+      int mid = (left + right) / 2;
+      if (mid == left)
+        break;
+      if (_virtPos < Extents[mid].Virt)
+        right = mid;
+      else
+        left = mid;
+    }
+    
+    const CSeekExtent &extent = Extents[left];
+    UInt64 phyPos = extent.Phy + (_virtPos - extent.Virt);
+    if (_needStartSeek || _phyPos != phyPos)
+    {
+      _needStartSeek = false;
+      _phyPos = phyPos;
+      RINOK(SeekToPhys());
+    }
+
+    UInt64 rem = Extents[left + 1].Virt - _virtPos;
+    if (size > rem)
+      size = (UInt32)rem;
+ 
+    HRESULT res = Stream->Read(data, size, &size);
+    _phyPos += size;
+    _virtPos += size;
+    if (processedSize)
+      *processedSize = size;
+    return res;
+  }
+  return S_OK;
+}
+
+STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+  switch(seekOrigin)
+  {
+    case STREAM_SEEK_SET: _virtPos = offset; break;
+    case STREAM_SEEK_CUR: _virtPos += offset; break;
+    case STREAM_SEEK_END: _virtPos = Extents.Back().Virt + offset; break;
+    default: return STG_E_INVALIDFUNCTION;
+  }
+  if (newPosition)
+    *newPosition = _virtPos;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+  *stream = 0;
+
+  const CRef2 &ref2 = _refs2[index];
+  const CLogVol &vol = _archive.LogVols[ref2.Vol];
+  const CRef &ref = vol.FileSets[ref2.Fs].Refs[ref2.Ref];
+  const CFile &file = _archive.Files[ref.FileIndex];
+  const CItem &item = _archive.Items[file.ItemIndex];
+  UInt64 size = item.Size;
+
+  if (!item.IsRecAndAlloc() || !item.CheckChunkSizes() || ! _archive.CheckItemExtents(ref2.Vol, item))
+    return E_NOTIMPL;
+
+  if (item.IsInline)
+  {
+    CBufInStream *inStreamSpec = new CBufInStream;
+    CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
+    CReferenceBuf *referenceBuf = new CReferenceBuf;
+    CMyComPtr<IUnknown> ref = referenceBuf;
+    referenceBuf->Buf = item.InlineData;
+    inStreamSpec->Init(referenceBuf);
+    *stream = inStream.Detach();
+    return S_OK;
+  }
+
+  CExtentsStream *extentStreamSpec = new CExtentsStream();
+  CMyComPtr<ISequentialInStream> extentStream = extentStreamSpec;
+  
+  extentStreamSpec->Stream = _inStream;
+
+  UInt64 virtOffset = 0;
+  for (int extentIndex = 0; extentIndex < item.Extents.Size(); extentIndex++)
+  {
+    const CMyExtent &extent = item.Extents[extentIndex];
+    UInt32 len = extent.GetLen();
+    if (len == 0)
+      continue;
+    if (size < len)
+      return S_FALSE;
+      
+    int partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex;
+    UInt32 logBlockNumber = extent.Pos;
+    const CPartition &partition = _archive.Partitions[partitionIndex];
+    UInt64 offset = ((UInt64)partition.Pos << _archive.SecLogSize) +
+      (UInt64)logBlockNumber * vol.BlockSize;
+      
+    CSeekExtent se;
+    se.Phy = offset;
+    se.Virt = virtOffset;
+    virtOffset += len;
+    extentStreamSpec->Extents.Add(se);
+
+    size -= len;
+  }
+  if (size != 0)
+    return S_FALSE;
+  CSeekExtent se;
+  se.Phy = 0;
+  se.Virt = virtOffset;
+  extentStreamSpec->Extents.Add(se);
+  extentStreamSpec->Init();
+  *stream = extentStream.Detach();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _refs2.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt64 totalSize = 0;
+  UInt32 i;
+
+  for (i = 0; i < numItems; i++)
+  {
+    UInt32 index = (allFilesMode ? i : indices[i]);
+    const CRef2 &ref2 = _refs2[index];
+    const CRef &ref = _archive.LogVols[ref2.Vol].FileSets[ref2.Fs].Refs[ref2.Ref];
+    const CFile &file = _archive.Files[ref.FileIndex];
+    const CItem &item = _archive.Items[file.ItemIndex];
+    if (!item.IsDir())
+      totalSize += item.Size;
+  }
+  extractCallback->SetTotal(totalSize);
+
+  UInt64 currentTotalSize = 0;
+  
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+
+  for (i = 0; i < numItems; i++)
+  {
+    lps->InSize = lps->OutSize = currentTotalSize;
+    RINOK(lps->SetCur());
+    CMyComPtr<ISequentialOutStream> realOutStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    UInt32 index = allFilesMode ? i : indices[i];
+    
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+    const CRef2 &ref2 = _refs2[index];
+    const CRef &ref = _archive.LogVols[ref2.Vol].FileSets[ref2.Fs].Refs[ref2.Ref];
+    const CFile &file = _archive.Files[ref.FileIndex];
+    const CItem &item = _archive.Items[file.ItemIndex];
+
+    if (item.IsDir())
+    {
+      RINOK(extractCallback->PrepareOperation(askMode));
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+      continue;
+    }
+    currentTotalSize += item.Size;
+
+    if (!testMode && !realOutStream)
+      continue;
+
+    RINOK(extractCallback->PrepareOperation(askMode));
+    outStreamSpec->SetStream(realOutStream);
+    realOutStream.Release();
+    outStreamSpec->Init(item.Size);
+    Int32 opRes;
+    CMyComPtr<ISequentialInStream> udfInStream;
+    HRESULT res = GetStream(index, &udfInStream);
+    if (res == E_NOTIMPL)
+      opRes = NExtract::NOperationResult::kUnSupportedMethod;
+    else if (res != S_OK)
+      opRes = NExtract::NOperationResult::kDataError;
+    else
+    {
+      RINOK(copyCoder->Code(udfInStream, outStream, NULL, NULL, progress));
+      opRes = outStreamSpec->IsFinishedOK() ?
+        NExtract::NOperationResult::kOK:
+        NExtract::NOperationResult::kDataError;
+    }
+    outStreamSpec->ReleaseStream();
+    RINOK(extractCallback->SetOperationResult(opRes));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfHandler.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfHandler.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfHandler.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfHandler.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,37 @@
+// Udf/Handler.h
+
+#ifndef __UDF_HANDLER_H
+#define __UDF_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+
+#include "UdfIn.h"
+
+namespace NArchive {
+namespace NUdf {
+
+struct CRef2
+{
+  int Vol;
+  int Fs;
+  int Ref;
+};
+
+class CHandler:
+  public IInArchive,
+  public IInArchiveGetStream,
+  public CMyUnknownImp
+{
+  CMyComPtr<IInStream> _inStream;
+  CInArchive _archive;
+  CRecordVector<CRef2> _refs2;
+public:
+  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
+  INTERFACE_IInArchive(;)
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfIn.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfIn.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfIn.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfIn.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,876 @@
+// Archive/UdfIn.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/CpuArch.h"
+
+#include "../../Common/StreamUtils.h"
+
+#include "UdfIn.h"
+
+#define Get16(p) GetUi16(p)
+#define Get32(p) GetUi32(p)
+#define Get64(p) GetUi64(p)
+
+namespace NArchive {
+namespace NUdf {
+
+const int kNumPartitionsMax = 64;
+const int kNumLogVolumesMax = 64;
+const int kNumRecureseLevelsMax = 1 << 10;
+const int kNumItemsMax = 1 << 27;
+const int kNumFilesMax = 1 << 28;
+const int kNumRefsMax = 1 << 28;
+const UInt32 kNumExtentsMax = (UInt32)1 << 30;
+const UInt64 kFileNameLengthTotalMax = (UInt64)1 << 33;
+const UInt64 kInlineExtentsSizeMax = (UInt64)1 << 33;
+
+void MY_FAST_CALL Crc16GenerateTable(void);
+
+#define CRC16_INIT_VAL 0
+#define CRC16_GET_DIGEST(crc) (crc)
+#define CRC16_UPDATE_BYTE(crc, b) (g_Crc16Table[(((crc) >> 8) ^ (b)) & 0xFF] ^ ((crc) << 8))
+
+#define kCrc16Poly 0x1021
+UInt16 g_Crc16Table[256];
+
+void MY_FAST_CALL Crc16GenerateTable(void)
+{
+  UInt32 i;
+  for (i = 0; i < 256; i++)
+  {
+    UInt32 r = (i << 8);
+    for (int j = 8; j > 0; j--)
+      r = ((r & 0x8000) ? ((r << 1) ^ kCrc16Poly) : (r << 1)) & 0xFFFF;
+    g_Crc16Table[i] = (UInt16)r;
+  }
+}
+
+UInt16 MY_FAST_CALL Crc16_Update(UInt16 v, const void *data, size_t size)
+{
+  const Byte *p = (const Byte *)data;
+  for (; size > 0 ; size--, p++)
+    v = CRC16_UPDATE_BYTE(v, *p);
+  return v;
+}
+
+UInt16 MY_FAST_CALL Crc16Calc(const void *data, size_t size)
+{
+  return Crc16_Update(CRC16_INIT_VAL, data, size);
+}
+
+struct CCrc16TableInit { CCrc16TableInit() { Crc16GenerateTable(); } } g_Crc16TableInit;
+
+void CDString128::Parse(const Byte *buf) { memcpy(Data, buf, sizeof(Data)); }
+
+void CDString::Parse(const Byte *p, unsigned size)
+{
+  Data.SetCapacity(size);
+  memcpy(Data, p, size);
+}
+
+static UString ParseDString(const Byte *data, int size)
+{
+  UString res;
+  wchar_t *p;
+  if (size > 0)
+  {
+    Byte type = data[0];
+    if (type == 8)
+    {
+      p = res.GetBuffer((int)size + 1);
+      for (int i = 1; i < size; i++)
+      {
+        wchar_t c = data[i];
+        if (c == 0)
+          break;
+        *p++ = c;
+      }
+    }
+    else if (type == 16)
+    {
+      p = res.GetBuffer((int)size / 2 + 1);
+      for (int i = 1; i + 2 <= size; i += 2)
+      {
+        wchar_t c = ((wchar_t)data[i] << 8) | data[i + 1];
+        if (c == 0)
+          break;
+        *p++ = c;
+      }
+    }
+    else
+      return L"[unknow]";
+    *p++ = 0;
+    res.ReleaseBuffer();
+  }
+  return res;
+}
+
+UString CDString::   GetString() const { return ParseDString(Data, (int)Data.GetCapacity()); }
+UString CDString128::GetString() const
+{
+  int size = Data[sizeof(Data) - 1];
+  return ParseDString(Data, MyMin(size, (int)(sizeof(Data) - 1)));
+}
+
+void CTime::Parse(const Byte *buf) { memcpy(Data, buf, sizeof(Data)); }
+
+/*
+void CRegId::Parse(const Byte *buf)
+{
+  Flags = buf[0];
+  memcpy(Id, buf + 1, sizeof(Id));
+  memcpy(Suffix, buf + 24, sizeof(Suffix));
+}
+*/
+
+// ECMA 3/7.1
+
+struct CExtent
+{
+  UInt32 Len;
+  UInt32 Pos;
+
+  void Parse(const Byte *buf);
+};
+
+void CExtent::Parse(const Byte *buf)
+{
+  Len = Get32(buf);
+  Pos = Get32(buf + 4);
+}
+
+// ECMA 3/7.2
+
+struct CTag
+{
+  UInt16 Id;
+  UInt16 Version;
+  // Byte Checksum;
+  // UInt16 SerialNumber;
+  // UInt16 Crc;
+  // UInt16 CrcLen;
+  // UInt32 TagLocation;
+  
+  HRESULT Parse(const Byte *buf, size_t size);
+};
+
+HRESULT CTag::Parse(const Byte *buf, size_t size)
+{
+  if (size < 16)
+    return S_FALSE;
+  Byte sum = 0;
+  int i;
+  for (i = 0; i <  4; i++) sum = sum + buf[i];
+  for (i = 5; i < 16; i++) sum = sum + buf[i];
+  if (sum != buf[4] || buf[5] != 0) return S_FALSE;
+
+  Id = Get16(buf);
+  Version = Get16(buf + 2);
+  // SerialNumber = Get16(buf + 6);
+  UInt16 crc = Get16(buf + 8);
+  UInt16 crcLen = Get16(buf + 10);
+  // TagLocation = Get32(buf + 12);
+
+  if (size >= 16 + (size_t)crcLen)
+    if (crc == Crc16Calc(buf + 16, crcLen))
+      return S_OK;
+  return S_FALSE;
+}
+
+// ECMA 3/7.2.1
+
+enum EDescriptorType
+{
+  DESC_TYPE_SpoaringTable = 0, // UDF
+  DESC_TYPE_PrimVol = 1,
+  DESC_TYPE_AnchorVolPtr = 2,
+  DESC_TYPE_VolPtr = 3,
+  DESC_TYPE_ImplUseVol = 4,
+  DESC_TYPE_Partition = 5,
+  DESC_TYPE_LogicalVol = 6,
+  DESC_TYPE_UnallocSpace = 7,
+  DESC_TYPE_Terminating = 8,
+  DESC_TYPE_LogicalVolIntegrity = 9,
+  DESC_TYPE_FileSet = 256,
+  DESC_TYPE_FileId  = 257,
+  DESC_TYPE_AllocationExtent = 258,
+  DESC_TYPE_Indirect = 259,
+  DESC_TYPE_Terminal = 260,
+  DESC_TYPE_File = 261,
+  DESC_TYPE_ExtendedAttrHeader = 262,
+  DESC_TYPE_UnallocatedSpace = 263,
+  DESC_TYPE_SpaceBitmap = 264,
+  DESC_TYPE_PartitionIntegrity = 265,
+  DESC_TYPE_ExtendedFile = 266
+};
+
+
+void CLogBlockAddr::Parse(const Byte *buf)
+{
+  Pos = Get32(buf);
+  PartitionRef = Get16(buf + 4);
+}
+
+void CShortAllocDesc::Parse(const Byte *buf)
+{
+  Len = Get32(buf);
+  Pos = Get32(buf + 4);
+}
+
+/*
+void CADImpUse::Parse(const Byte *buf)
+{
+  Flags = Get16(buf);
+  UdfUniqueId = Get32(buf + 2);
+}
+*/
+
+void CLongAllocDesc::Parse(const Byte *buf)
+{
+  Len = Get32(buf);
+  Location.Parse(buf + 4);
+  // memcpy(ImplUse, buf + 10, sizeof(ImplUse));
+  // adImpUse.Parse(ImplUse);
+}
+
+bool CInArchive::CheckExtent(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len) const
+{
+  const CLogVol &vol = LogVols[volIndex];
+  const CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex];
+  UInt64 offset = ((UInt64)partition.Pos << SecLogSize) + (UInt64)blockPos * vol.BlockSize;
+  return (offset + len) <= (((UInt64)partition.Pos + partition.Len) << SecLogSize);
+}
+
+bool CInArchive::CheckItemExtents(int volIndex, const CItem &item) const
+{
+  for (int i = 0; i < item.Extents.Size(); i++)
+  {
+    const CMyExtent &e = item.Extents[i];
+    if (!CheckExtent(volIndex, e.PartitionRef, e.Pos, e.GetLen()))
+      return false;
+  }
+  return true;
+}
+
+HRESULT CInArchive::Read(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len, Byte *buf)
+{
+  if (!CheckExtent(volIndex, partitionRef, blockPos, len))
+    return S_FALSE;
+  const CLogVol &vol = LogVols[volIndex];
+  const CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex];
+  RINOK(_stream->Seek(((UInt64)partition.Pos << SecLogSize) +
+      (UInt64)blockPos * vol.BlockSize, STREAM_SEEK_SET, NULL));
+  return ReadStream_FALSE(_stream, buf, len);
+}
+
+HRESULT CInArchive::Read(int volIndex, const CLongAllocDesc &lad, Byte *buf)
+{
+  return Read(volIndex, lad.Location.PartitionRef, lad.Location.Pos, lad.GetLen(), (Byte *)buf);
+}
+
+HRESULT CInArchive::ReadFromFile(int volIndex, const CItem &item, CByteBuffer &buf)
+{
+  if (item.Size >= (UInt32)1 << 30)
+    return S_FALSE;
+  if (item.IsInline)
+  {
+    buf = item.InlineData;
+    return S_OK;
+  }
+  buf.SetCapacity((size_t)item.Size);
+  size_t pos = 0;
+  for (int i = 0; i < item.Extents.Size(); i++)
+  {
+    const CMyExtent &e = item.Extents[i];
+    UInt32 len = e.GetLen();
+    RINOK(Read(volIndex, e.PartitionRef, e.Pos, len, (Byte *)buf + pos));
+    pos += len;
+  }
+  return S_OK;
+}
+
+
+void CIcbTag::Parse(const Byte *p)
+{
+  // PriorDirectNum = Get32(p);
+  // StrategyType = Get16(p + 4);
+  // StrategyParam = Get16(p + 6);
+  // MaxNumOfEntries = Get16(p + 8);
+  FileType = p[11];
+  // ParentIcb.Parse(p + 12);
+  Flags = Get16(p + 18);
+}
+
+void CItem::Parse(const Byte *p)
+{
+  // Uid = Get32(p + 36);
+  // Gid = Get32(p + 40);
+  // Permissions = Get32(p + 44);
+  // FileLinkCount = Get16(p + 48);
+  // RecordFormat = p[50];
+  // RecordDisplayAttr = p[51];
+  // RecordLen = Get32(p + 52);
+  Size = Get64(p + 56);
+  NumLogBlockRecorded = Get64(p + 64);
+  ATime.Parse(p + 72);
+  MTime.Parse(p + 84);
+  // AttrtTime.Parse(p + 96);
+  // CheckPoint = Get32(p + 108);
+  // ExtendedAttrIcb.Parse(p + 112);
+  // ImplId.Parse(p + 128);
+  // UniqueId = Get64(p + 160);
+}
+
+// 4/14.4
+struct CFileId
+{
+  // UInt16 FileVersion;
+  Byte FileCharacteristics;
+  // CByteBuffer ImplUse;
+  CDString Id;
+  CLongAllocDesc Icb;
+
+  bool IsItLinkParent() const { return (FileCharacteristics & FILEID_CHARACS_Parent) != 0; }
+  HRESULT Parse(const Byte *p, size_t size, size_t &processed);
+};
+
+HRESULT CFileId::Parse(const Byte *p, size_t size, size_t &processed)
+{
+  processed = 0;
+  if (size < 38)
+    return S_FALSE;
+  CTag tag;
+  RINOK(tag.Parse(p, size));
+  if (tag.Id != DESC_TYPE_FileId)
+    return S_FALSE;
+  // FileVersion = Get16(p + 16);
+  FileCharacteristics = p[18];
+  unsigned idLen = p[19];
+  Icb.Parse(p + 20);
+  unsigned impLen = Get16(p + 36);
+  if (size < 38 + idLen + impLen)
+    return S_FALSE;
+  // ImplUse.SetCapacity(impLen);
+  processed = 38;
+  // memcpy(ImplUse, p + processed, impLen);
+  processed += impLen;
+  Id.Parse(p + processed, idLen);
+  processed += idLen;
+  for (;(processed & 3) != 0; processed++)
+    if (p[processed] != 0)
+      return S_FALSE;
+  return (processed <= size) ? S_OK : S_FALSE;
+}
+
+HRESULT CInArchive::ReadFileItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed)
+{
+  if (Files.Size() % 100 == 0)
+    RINOK(_progress->SetCompleted(Files.Size(), _processedProgressBytes));
+  if (numRecurseAllowed-- == 0)
+    return S_FALSE;
+  CFile &file = Files.Back();
+  const CLogVol &vol = LogVols[volIndex];
+  CPartition &partition = Partitions[vol.PartitionMaps[lad.Location.PartitionRef].PartitionIndex];
+
+  UInt32 key = lad.Location.Pos;
+  UInt32 value;
+  const UInt32 kRecursedErrorValue = (UInt32)(Int32)-1;
+  if (partition.Map.Find(key, value))
+  {
+    if (value == kRecursedErrorValue)
+      return S_FALSE;
+    file.ItemIndex = value;
+  }
+  else
+  {
+    value = Items.Size();
+    file.ItemIndex = (int)value;
+    if (partition.Map.Set(key, kRecursedErrorValue))
+      return S_FALSE;
+    RINOK(ReadItem(volIndex, fsIndex, lad, numRecurseAllowed));
+    if (!partition.Map.Set(key, value))
+      return S_FALSE;
+  }
+  return S_OK;
+}
+
+HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed)
+{
+  if (Items.Size() > kNumItemsMax)
+    return S_FALSE;
+  Items.Add(CItem());
+  CItem &item = Items.Back();
+  
+  const CLogVol &vol = LogVols[volIndex];
+ 
+  if (lad.GetLen() != vol.BlockSize)
+    return S_FALSE;
+
+  CByteBuffer buf;
+  size_t size = lad.GetLen();
+  buf.SetCapacity(size);
+  RINOK(Read(volIndex, lad, buf));
+
+  CTag tag;
+  const Byte *p = buf;
+  RINOK(tag.Parse(p, size));
+  if (tag.Id != DESC_TYPE_File)
+    return S_FALSE;
+
+  item.IcbTag.Parse(p + 16);
+  if (item.IcbTag.FileType != ICB_FILE_TYPE_DIR &&
+      item.IcbTag.FileType != ICB_FILE_TYPE_FILE)
+    return S_FALSE;
+
+  item.Parse(p);
+
+  _processedProgressBytes += (UInt64)item.NumLogBlockRecorded * vol.BlockSize + size;
+
+  UInt32 extendedAttrLen = Get32(p + 168);
+  UInt32 allocDescriptorsLen = Get32(p + 172);
+
+  if ((extendedAttrLen & 3) != 0)
+    return S_FALSE;
+  int pos = 176;
+  if (extendedAttrLen > size - pos)
+    return S_FALSE;
+  /*
+  if (extendedAttrLen != 16)
+  {
+    if (extendedAttrLen < 24)
+      return S_FALSE;
+    CTag attrTag;
+    RINOK(attrTag.Parse(p + pos, size));
+    if (attrTag.Id != DESC_TYPE_ExtendedAttrHeader)
+      return S_FALSE;
+    // UInt32 implAttrLocation = Get32(p + pos + 16);
+    // UInt32 applicationlAttrLocation = Get32(p + pos + 20);
+  }
+  */
+  pos += extendedAttrLen;
+
+  int desctType = item.IcbTag.GetDescriptorType();
+  if (allocDescriptorsLen > size - pos)
+    return S_FALSE;
+  if (desctType == ICB_DESC_TYPE_INLINE)
+  {
+    item.IsInline = true;
+    item.InlineData.SetCapacity(allocDescriptorsLen);
+    memcpy(item.InlineData, p + pos, allocDescriptorsLen);
+  }
+  else
+  {
+    item.IsInline = false;
+    if (desctType != ICB_DESC_TYPE_SHORT && desctType != ICB_DESC_TYPE_LONG)
+      return S_FALSE;
+    for (UInt32 i = 0; i < allocDescriptorsLen;)
+    {
+      CMyExtent e;
+      if (desctType == ICB_DESC_TYPE_SHORT)
+      {
+        if (i + 8 > allocDescriptorsLen)
+          return S_FALSE;
+        CShortAllocDesc sad;
+        sad.Parse(p + pos + i);
+        e.Pos = sad.Pos;
+        e.Len = sad.Len;
+        e.PartitionRef = lad.Location.PartitionRef;
+        i += 8;
+      }
+      else
+      {
+        if (i + 16 > allocDescriptorsLen)
+          return S_FALSE;
+        CLongAllocDesc ladNew;
+        ladNew.Parse(p + pos + i);
+        e.Pos = ladNew.Location.Pos;
+        e.PartitionRef = ladNew.Location.PartitionRef;
+        e.Len = ladNew.Len;
+        i += 16;
+      }
+      item.Extents.Add(e);
+    }
+  }
+
+  if (item.IcbTag.IsDir())
+  {
+    if (!item.CheckChunkSizes() || !CheckItemExtents(volIndex, item))
+      return S_FALSE;
+    CByteBuffer buf;
+    RINOK(ReadFromFile(volIndex, item, buf));
+    item.Size = 0;
+    item.Extents.ClearAndFree();
+    item.InlineData.Free();
+
+    const Byte *p = buf;
+    size = buf.GetCapacity();
+    size_t processedTotal = 0;
+    for (; processedTotal < size;)
+    {
+      size_t processedCur;
+      CFileId fileId;
+      RINOK(fileId.Parse(p + processedTotal, size - processedTotal, processedCur));
+      if (!fileId.IsItLinkParent())
+      {
+        CFile file;
+        // file.FileVersion = fileId.FileVersion;
+        // file.FileCharacteristics = fileId.FileCharacteristics;
+        // file.ImplUse = fileId.ImplUse;
+        file.Id = fileId.Id;
+        
+        _fileNameLengthTotal += file.Id.Data.GetCapacity();
+        if (_fileNameLengthTotal > kFileNameLengthTotalMax)
+          return S_FALSE;
+        
+        item.SubFiles.Add(Files.Size());
+        if (Files.Size() > kNumFilesMax)
+          return S_FALSE;
+        Files.Add(file);
+        RINOK(ReadFileItem(volIndex, fsIndex, fileId.Icb, numRecurseAllowed));
+      }
+      processedTotal += processedCur;
+    }
+  }
+  else
+  {
+    if ((UInt32)item.Extents.Size() > kNumExtentsMax - _numExtents)
+      return S_FALSE;
+    _numExtents += item.Extents.Size();
+
+    if (item.InlineData.GetCapacity() > kInlineExtentsSizeMax - _inlineExtentsSize)
+      return S_FALSE;
+    _inlineExtentsSize += item.InlineData.GetCapacity();
+  }
+
+  return S_OK;
+}
+
+HRESULT CInArchive::FillRefs(CFileSet &fs, int fileIndex, int parent, int numRecurseAllowed)
+{
+  if (_numRefs % 10000 == 0)
+  {
+    RINOK(_progress->SetCompleted());
+  }
+  if (numRecurseAllowed-- == 0)
+    return S_FALSE;
+  if (_numRefs >= kNumRefsMax)
+    return S_FALSE;
+  _numRefs++;
+  CRef ref;
+  ref.FileIndex = fileIndex;
+  ref.Parent = parent;
+  parent = fs.Refs.Size();
+  fs.Refs.Add(ref);
+  const CItem &item = Items[Files[fileIndex].ItemIndex];
+  for (int i = 0; i < item.SubFiles.Size(); i++)
+  {
+    RINOK(FillRefs(fs, item.SubFiles[i], parent, numRecurseAllowed));
+  }
+  return S_OK;
+}
+
+HRESULT CInArchive::Open2()
+{
+  Clear();
+
+  UInt64 fileSize;
+  RINOK(_stream->Seek(0, STREAM_SEEK_END, &fileSize));
+
+  // Some UDFs contain additional 2 KB of zeros, so we also check 12, corrected to 11.
+  const int kSecLogSizeMax = 12;
+  Byte buf[1 << kSecLogSizeMax];
+  Byte kSizesLog[] = { 11, 8, 12 };
+
+  for (int i = 0;; i++)
+  {
+    if (i == sizeof(kSizesLog) / sizeof(kSizesLog[0]))
+      return S_FALSE;
+    SecLogSize = kSizesLog[i];
+    Int32 bufSize = 1 << SecLogSize;
+    if (bufSize > fileSize)
+      return S_FALSE;
+    RINOK(_stream->Seek(-bufSize, STREAM_SEEK_END, NULL));
+    RINOK(ReadStream_FALSE(_stream, buf, bufSize));
+    CTag tag;
+    if (tag.Parse(buf, bufSize) == S_OK)
+      if (tag.Id == DESC_TYPE_AnchorVolPtr)
+        break;
+  }
+  if (SecLogSize == 12)
+    SecLogSize = 11;
+
+  CExtent extentVDS;
+  extentVDS.Parse(buf + 16);
+
+  for (UInt32 location = extentVDS.Pos; ; location++)
+  {
+    size_t bufSize = 1 << SecLogSize;
+    size_t pos = 0;
+    RINOK(_stream->Seek((UInt64)location << SecLogSize, STREAM_SEEK_SET, NULL));
+    RINOK(ReadStream_FALSE(_stream, buf, bufSize));
+    CTag tag;
+    RINOK(tag.Parse(buf + pos, bufSize - pos));
+    if (tag.Id == DESC_TYPE_Terminating)
+      break;
+    if (tag.Id == DESC_TYPE_Partition)
+    {
+      if (Partitions.Size() >= kNumPartitionsMax)
+        return S_FALSE;
+      CPartition partition;
+      // UInt32 volDescSeqNumer = Get32(buf + 16);
+      // partition.Flags = Get16(buf + 20);
+      partition.Number = Get16(buf + 22);
+      // partition.ContentsId.Parse(buf + 24);
+      
+      // memcpy(partition.ContentsUse, buf + 56, sizeof(partition.ContentsUse));
+      // ContentsUse is Partition Header Description.
+
+      // partition.AccessType = Get32(buf + 184);
+      partition.Pos = Get32(buf + 188);
+      partition.Len = Get32(buf + 192);
+      // partition.ImplId.Parse(buf + 196);
+      // memcpy(partition.ImplUse, buf + 228, sizeof(partition.ImplUse));
+
+      Partitions.Add(partition);
+    }
+    else if (tag.Id == DESC_TYPE_LogicalVol)
+    {
+      if (LogVols.Size() >= kNumLogVolumesMax)
+        return S_FALSE;
+      CLogVol vol;
+      vol.Id.Parse(buf + 84);
+      vol.BlockSize = Get32(buf + 212);
+      // vol.DomainId.Parse(buf + 216);
+
+      if (vol.BlockSize < 512 || vol.BlockSize > ((UInt32)1 << 30))
+        return S_FALSE;
+      
+      // memcpy(vol.ContentsUse, buf + 248, sizeof(vol.ContentsUse));
+      vol.FileSetLocation.Parse(buf + 248);
+
+      // UInt32 mapTableLength = Get32(buf + 264);
+      UInt32 numPartitionMaps = Get32(buf + 268);
+      if (numPartitionMaps > kNumPartitionsMax)
+        return S_FALSE;
+      // vol.ImplId.Parse(buf + 272);
+      // memcpy(vol.ImplUse, buf + 128, sizeof(vol.ImplUse));
+      size_t pos = 440;
+      for (UInt32 i = 0; i < numPartitionMaps; i++)
+      {
+        if (pos + 2 > bufSize)
+          return S_FALSE;
+        CPartitionMap pm;
+        pm.Type = buf[pos];
+        // pm.Length = buf[pos + 1];
+        Byte len = buf[pos + 1];
+
+        if (pos + len > bufSize)
+          return S_FALSE;
+        
+        // memcpy(pm.Data, buf + pos + 2, pm.Length - 2);
+        if (pm.Type == 1)
+        {
+          if (pos + 6 > bufSize)
+            return S_FALSE;
+          // pm.VolSeqNumber = Get16(buf + pos + 2);
+          pm.PartitionNumber = Get16(buf + pos + 4);
+        }
+        else
+          return S_FALSE;
+        pos += len;
+        vol.PartitionMaps.Add(pm);
+      }
+      LogVols.Add(vol);
+    }
+  }
+
+  UInt64 totalSize = 0;
+
+  int volIndex;
+  for (volIndex = 0; volIndex < LogVols.Size(); volIndex++)
+  {
+    CLogVol &vol = LogVols[volIndex];
+    for (int pmIndex = 0; pmIndex < vol.PartitionMaps.Size(); pmIndex++)
+    {
+      CPartitionMap &pm = vol.PartitionMaps[pmIndex];
+      int i;
+      for (i = 0; i < Partitions.Size(); i++)
+      {
+        CPartition &part = Partitions[i];
+        if (part.Number == pm.PartitionNumber)
+        {
+          if (part.VolIndex >= 0)
+            return S_FALSE;
+          pm.PartitionIndex = i;
+          part.VolIndex = volIndex;
+
+          totalSize += (UInt64)part.Len << SecLogSize;
+          break;
+        }
+      }
+      if (i == Partitions.Size())
+        return S_FALSE;
+    }
+  }
+
+  RINOK(_progress->SetTotal(totalSize));
+
+  for (volIndex = 0; volIndex < LogVols.Size(); volIndex++)
+  {
+    CLogVol &vol = LogVols[volIndex];
+
+    CLongAllocDesc nextExtent = vol.FileSetLocation;
+    // while (nextExtent.ExtentLen != 0)
+    // for (int i = 0; i < 1; i++)
+    {
+      if (nextExtent.GetLen() < 512)
+        return S_FALSE;
+      CByteBuffer buf;
+      buf.SetCapacity(nextExtent.GetLen());
+      RINOK(Read(volIndex, nextExtent, buf));
+      const Byte *p = buf;
+      size_t size = nextExtent.GetLen();
+
+      CTag tag;
+      RINOK(tag.Parse(p, size));
+      if (tag.Id != DESC_TYPE_FileSet)
+        return S_FALSE;
+      
+      CFileSet fs;
+      fs.RecodringTime.Parse(p + 16);
+      // fs.InterchangeLevel = Get16(p + 18);
+      // fs.MaxInterchangeLevel = Get16(p + 20);
+      // fs.FileSetNumber = Get32(p + 40);
+      // fs.FileSetDescNumber = Get32(p + 44);
+      
+      // fs.Id.Parse(p + 304);
+      // fs.CopyrightId.Parse(p + 336);
+      // fs.AbstractId.Parse(p + 368);
+      
+      fs.RootDirICB.Parse(p + 400);
+      // fs.DomainId.Parse(p + 416);
+      
+      // fs.SystemStreamDirICB.Parse(p + 464);
+      
+      vol.FileSets.Add(fs);
+
+      // nextExtent.Parse(p + 448);
+    }
+
+    for (int fsIndex = 0; fsIndex < vol.FileSets.Size(); fsIndex++)
+    {
+      CFileSet &fs = vol.FileSets[fsIndex];
+      int fileIndex = Files.Size();
+      Files.Add(CFile());
+      RINOK(ReadFileItem(volIndex, fsIndex, fs.RootDirICB, kNumRecureseLevelsMax));
+      RINOK(FillRefs(fs, fileIndex, -1, kNumRecureseLevelsMax));
+    }
+  }
+
+  return S_OK;
+}
+
+HRESULT CInArchive::Open(IInStream *inStream, CProgressVirt *progress)
+{
+  _progress = progress;
+  _stream = inStream;
+  HRESULT res;
+  try { res = Open2(); }
+  catch(...) { Clear(); res = S_FALSE; }
+  _stream.Release();
+  return res;
+}
+
+void CInArchive::Clear()
+{
+  Partitions.Clear();
+  LogVols.Clear();
+  Items.Clear();
+  Files.Clear();
+  _fileNameLengthTotal = 0;
+  _numRefs = 0;
+  _numExtents = 0;
+  _inlineExtentsSize = 0;
+  _processedProgressBytes = 0;
+}
+
+UString CInArchive::GetComment() const
+{
+  UString res;
+  for (int i = 0; i < LogVols.Size(); i++)
+  {
+    if (i > 0)
+      res += L" ";
+    res += LogVols[i].GetName();
+  }
+  return res;
+}
+
+static UString GetSpecName(const UString &name)
+{
+  UString name2 = name;
+  name2.Trim();
+  if (name2.IsEmpty())
+  {
+    /*
+    wchar_t s[32];
+    ConvertUInt64ToString(id, s);
+    return L"[" + (UString)s + L"]";
+    */
+    return L"[]";
+  }
+  return name;
+}
+
+static void UpdateWithName(UString &res, const UString &addString)
+{
+  if (res.IsEmpty())
+    res = addString;
+  else
+    res = addString + WCHAR_PATH_SEPARATOR + res;
+}
+
+UString CInArchive::GetItemPath(int volIndex, int fsIndex, int refIndex,
+    bool showVolName, bool showFsName) const
+{
+  // showVolName = true;
+  const CLogVol &vol = LogVols[volIndex];
+  const CFileSet &fs = vol.FileSets[fsIndex];
+
+  UString name;
+
+  for (;;)
+  {
+    const CRef &ref = fs.Refs[refIndex];
+    refIndex = ref.Parent;
+    if (refIndex < 0)
+      break;
+    UpdateWithName(name, GetSpecName(Files[ref.FileIndex].GetName()));
+  }
+
+  if (showFsName)
+  {
+    wchar_t s[32];
+    ConvertUInt64ToString(fsIndex, s);
+    UString newName = L"File Set ";
+    newName += s;
+    UpdateWithName(name, newName);
+  }
+
+  if (showVolName)
+  {
+    wchar_t s[32];
+    ConvertUInt64ToString(volIndex, s);
+    UString newName = s;
+    UString newName2 = vol.GetName();
+    if (newName2.IsEmpty())
+      newName2 = L"Volume";
+    newName += L'-';
+    newName += newName2;
+    UpdateWithName(name, newName);
+  }
+  return name;
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfIn.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfIn.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfIn.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfIn.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,375 @@
+// Archive/UdfIn.h -- UDF / ECMA-167
+
+#ifndef __ARCHIVE_UDF_IN_H
+#define __ARCHIVE_UDF_IN_H
+
+#include "Common/MyCom.h"
+#include "Common/IntToString.h"
+#include "Common/Buffer.h"
+#include "Common/MyString.h"
+#include "Common/MyMap.h"
+
+#include "../../IStream.h"
+
+namespace NArchive {
+namespace NUdf {
+
+// ---------- ECMA Part 1 ----------
+
+// ECMA 1/7.2.12
+
+/*
+struct CDString32
+{
+  Byte Data[32];
+  void Parse(const Byte *buf);
+  // UString GetString() const;
+};
+*/
+
+struct CDString128
+{
+  Byte Data[128];
+  void Parse(const Byte *buf);
+  UString GetString() const;
+};
+
+struct CDString
+{
+  CByteBuffer Data;
+  void Parse(const Byte *p, unsigned size);
+  UString GetString() const;
+};
+
+
+// ECMA 1/7.3
+
+struct CTime
+{
+  Byte Data[12];
+
+  unsigned GetType() const { return Data[1] >> 4; }
+  bool IsLocal() const { return GetType() == 1; }
+  int GetMinutesOffset() const
+  {
+    int t = (Data[0] | ((UInt16)Data[1] << 8)) & 0xFFF;
+    if ((t >> 11) != 0)
+      t -= (1 << 12);
+    return (t > (60 * 24) || t < -(60 * 24)) ? 0 : t;
+  }
+  unsigned GetYear() const { return (Data[2] | ((UInt16)Data[3] << 8)); }
+  void Parse(const Byte *buf);
+};
+
+
+// ECMA 1/7.4
+
+/*
+struct CRegId
+{
+  Byte Flags;
+  char Id[23];
+  char Suffix[8];
+
+  void Parse(const Byte *buf);
+};
+*/
+
+// ---------- ECMA Part 3: Volume Structure ----------
+
+// ECMA 3/10.5
+
+struct CPartition
+{
+  // UInt16 Flags;
+  UInt16 Number;
+  // CRegId ContentsId;
+  // Byte ContentsUse[128];
+  // UInt32 AccessType;
+
+  UInt32 Pos;
+  UInt32 Len;
+
+  // CRegId ImplId;
+  // Byte ImplUse[128];
+
+  int VolIndex;
+  CMap32 Map;
+
+  CPartition(): VolIndex(-1) {}
+
+  // bool IsNsr() const { return (strncmp(ContentsId.Id, "+NSR0", 5) == 0); }
+  // bool IsAllocated() const { return ((Flags & 1) != 0); }
+};
+
+struct CLogBlockAddr
+{
+  UInt32 Pos;
+  UInt16 PartitionRef;
+  
+  void Parse(const Byte *buf);
+};
+
+enum EShortAllocDescType
+{
+  SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated = 0,
+  SHORT_ALLOC_DESC_TYPE_NotRecordedButAllocated = 1,
+  SHORT_ALLOC_DESC_TYPE_NotRecordedAndNotAllocated = 2,
+  SHORT_ALLOC_DESC_TYPE_NextExtent = 3
+};
+
+struct CShortAllocDesc
+{
+  UInt32 Len;
+  UInt32 Pos;
+
+  // 4/14.14.1
+  // UInt32 GetLen() const { return Len & 0x3FFFFFFF; }
+  // UInt32 GetType() const { return Len >> 30; }
+  // bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; }
+  void Parse(const Byte *buf);
+};
+
+/*
+struct CADImpUse
+{
+  UInt16 Flags;
+  UInt32 UdfUniqueId;
+  void Parse(const Byte *buf);
+};
+*/
+
+struct CLongAllocDesc
+{
+  UInt32 Len;
+  CLogBlockAddr Location;
+  
+  // Byte ImplUse[6];
+  // CADImpUse adImpUse; // UDF
+  
+  UInt32 GetLen() const { return Len & 0x3FFFFFFF; }
+  UInt32 GetType() const { return Len >> 30; }
+  bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; }
+  void Parse(const Byte *buf);
+};
+
+struct CPartitionMap
+{
+  Byte Type;
+  // Byte Len;
+
+  // Type - 1
+  // UInt16 VolSeqNumber;
+  UInt16 PartitionNumber;
+
+  // Byte Data[256];
+
+  int PartitionIndex;
+};
+
+// ECMA 4/14.6
+
+enum EIcbFileType
+{
+  ICB_FILE_TYPE_DIR = 4,
+  ICB_FILE_TYPE_FILE = 5
+};
+
+enum EIcbDescriptorType
+{
+  ICB_DESC_TYPE_SHORT = 0,
+  ICB_DESC_TYPE_LONG = 1,
+  ICB_DESC_TYPE_EXTENDED = 2,
+  ICB_DESC_TYPE_INLINE = 3
+};
+
+struct CIcbTag
+{
+  // UInt32 PriorDirectNum;
+  // UInt16 StrategyType;
+  // UInt16 StrategyParam;
+  // UInt16 MaxNumOfEntries;
+  Byte FileType;
+  // CLogBlockAddr ParentIcb;
+  UInt16 Flags;
+
+  bool IsDir() const { return FileType == ICB_FILE_TYPE_DIR; }
+  int GetDescriptorType() const { return Flags & 3; }
+  void Parse(const Byte *p);
+};
+
+// const Byte FILEID_CHARACS_Existance = (1 << 0);
+const Byte FILEID_CHARACS_Parent = (1 << 3);
+
+struct CFile
+{
+  // UInt16 FileVersion;
+  // Byte FileCharacteristics;
+  // CByteBuffer ImplUse;
+  CDString Id;
+
+  CFile(): /* FileVersion(0), FileCharacteristics(0), */ ItemIndex(-1) {}
+  int ItemIndex;
+  UString GetName() const { return Id.GetString(); }
+};
+
+struct CMyExtent
+{
+  UInt32 Pos;
+  UInt32 Len;
+  int PartitionRef;
+  
+  UInt32 GetLen() const { return Len & 0x3FFFFFFF; }
+  UInt32 GetType() const { return Len >> 30; }
+  bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; }
+};
+
+struct CItem
+{
+  CIcbTag IcbTag;
+
+  // UInt32 Uid;
+  // UInt32 Gid;
+  // UInt32 Permissions;
+  // UInt16 FileLinkCount;
+  // Byte RecordFormat;
+  // Byte RecordDisplayAttr;
+  // UInt32 RecordLen;
+  UInt64 Size;
+  UInt64 NumLogBlockRecorded;
+  CTime ATime;
+  CTime MTime;
+  // CTime AttrtTime;
+  // UInt32 CheckPoint;
+  // CLongAllocDesc ExtendedAttrIcb;
+  // CRegId ImplId;
+  // UInt64 UniqueId;
+
+  bool IsInline;
+  CByteBuffer InlineData;
+  CRecordVector<CMyExtent> Extents;
+  CRecordVector<int> SubFiles;
+
+  void Parse(const Byte *buf);
+
+  bool IsRecAndAlloc() const
+  {
+    for (int i = 0; i < Extents.Size(); i++)
+      if (!Extents[i].IsRecAndAlloc())
+        return false;
+    return true;
+  }
+
+  UInt64 GetChunksSumSize() const
+  {
+    if (IsInline)
+      return InlineData.GetCapacity();
+    UInt64 size = 0;
+    for (int i = 0; i < Extents.Size(); i++)
+      size += Extents[i].GetLen();
+    return size;
+  }
+
+  bool CheckChunkSizes() const  {  return GetChunksSumSize() == Size; }
+
+  bool IsDir() const { return IcbTag.IsDir(); }
+};
+ 
+struct CRef
+{
+  int Parent;
+  int FileIndex;
+};
+
+
+// ECMA 4 / 14.1
+struct CFileSet
+{
+  CTime RecodringTime;
+  // UInt16 InterchangeLevel;
+  // UInt16 MaxInterchangeLevel;
+  // UInt32 FileSetNumber;
+  // UInt32 FileSetDescNumber;
+  // CDString32 Id;
+  // CDString32 CopyrightId;
+  // CDString32 AbstractId;
+
+  CLongAllocDesc RootDirICB;
+  // CRegId DomainId;
+  // CLongAllocDesc SystemStreamDirICB;
+
+  CRecordVector<CRef> Refs;
+};
+
+
+// ECMA 3/10.6
+
+struct CLogVol
+{
+  CDString128 Id;
+  UInt32 BlockSize;
+  // CRegId DomainId;
+  
+  // Byte ContentsUse[16];
+  CLongAllocDesc FileSetLocation; // UDF
+
+  // CRegId ImplId;
+  // Byte ImplUse[128];
+
+  CObjectVector<CPartitionMap> PartitionMaps;
+  CObjectVector<CFileSet> FileSets;
+
+  UString GetName() const { return Id.GetString(); }
+};
+
+struct CProgressVirt
+{
+  virtual HRESULT SetTotal(UInt64 numBytes) PURE;
+  virtual HRESULT SetCompleted(UInt64 numFiles, UInt64 numBytes) PURE;
+  virtual HRESULT SetCompleted() PURE;
+};
+
+class CInArchive
+{
+  CMyComPtr<IInStream> _stream;
+  CProgressVirt *_progress;
+
+  HRESULT Read(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len, Byte *buf);
+  HRESULT Read(int volIndex, const CLongAllocDesc &lad, Byte *buf);
+  HRESULT ReadFromFile(int volIndex, const CItem &item, CByteBuffer &buf);
+
+  HRESULT ReadFileItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed);
+  HRESULT ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed);
+
+  HRESULT Open2();
+  HRESULT FillRefs(CFileSet &fs, int fileIndex, int parent, int numRecurseAllowed);
+
+  UInt64 _processedProgressBytes;
+
+  UInt64 _fileNameLengthTotal;
+  int _numRefs;
+  UInt32 _numExtents;
+  UInt64 _inlineExtentsSize;
+  bool CheckExtent(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len) const;
+public:
+  HRESULT Open(IInStream *inStream, CProgressVirt *progress);
+  void Clear();
+
+  CObjectVector<CPartition> Partitions;
+  CObjectVector<CLogVol> LogVols;
+
+  CObjectVector<CItem> Items;
+  CObjectVector<CFile> Files;
+
+  int SecLogSize;
+
+  UString GetComment() const;
+  UString GetItemPath(int volIndex, int fsIndex, int refIndex,
+      bool showVolName, bool showFsName) const;
+
+  bool CheckItemExtents(int volIndex, const CItem &item) const;
+};
+
+}}
+  
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfRegister.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfRegister.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfRegister.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Udf/UdfRegister.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,13 @@
+// UdfRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterArc.h"
+
+#include "UdfHandler.h"
+static IInArchive *CreateArc() { return new NArchive::NUdf::CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"Udf", L"iso img", 0, 0xE0, { 0, 'N', 'S', 'R', '0' }, 5, false, CreateArc, 0 };
+
+REGISTER_ARC(Udf)

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/VhdHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/VhdHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/VhdHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/VhdHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,734 @@
+// VhdHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/Buffer.h"
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+#include "Common/MyString.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../Common/LimitedStreams.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+
+#define Get16(p) GetBe16(p)
+#define Get32(p) GetBe32(p)
+#define Get64(p) GetBe64(p)
+
+#define G32(p, dest) dest = Get32(p);
+#define G64(p, dest) dest = Get64(p);
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NVhd {
+
+static const UInt32 kUnusedBlock = 0xFFFFFFFF;
+
+static const UInt32 kDiskType_Fixed = 2;
+static const UInt32 kDiskType_Dynamic = 3;
+static const UInt32 kDiskType_Diff = 4;
+
+static const char *kDiskTypes[] =
+{
+  "0",
+  "1",
+  "Fixed",
+  "Dynamic",
+  "Differencing"
+};
+
+struct CFooter
+{
+  // UInt32 Features;
+  // UInt32 FormatVersion;
+  UInt64 DataOffset;
+  UInt32 CTime;
+  UInt32 CreatorApp;
+  UInt32 CreatorVersion;
+  UInt32 CreatorHostOS;
+  // UInt64 OriginalSize;
+  UInt64 CurrentSize;
+  UInt32 DiskGeometry;
+  UInt32 Type;
+  Byte Id[16];
+  Byte SavedState;
+
+  bool IsFixed() const { return Type == kDiskType_Fixed; }
+  bool ThereIsDynamic() const { return Type == kDiskType_Dynamic || Type == kDiskType_Diff; }
+  // bool IsSupported() const { return Type == kDiskType_Fixed || Type == kDiskType_Dynamic || Type == kDiskType_Diff; }
+  UInt32 NumCyls() const { return DiskGeometry >> 16; }
+  UInt32 NumHeads() const { return (DiskGeometry >> 8) & 0xFF; }
+  UInt32 NumSectorsPerTrack() const { return DiskGeometry & 0xFF; }
+  AString GetTypeString() const;
+  bool Parse(const Byte *p);
+};
+
+AString CFooter::GetTypeString() const
+{
+  if (Type < sizeof(kDiskTypes) / sizeof(kDiskTypes[0]))
+    return kDiskTypes[Type];
+  char s[16];
+  ConvertUInt32ToString(Type, s);
+  return s;
+}
+
+static bool CheckBlock(const Byte *p, unsigned size, unsigned checkSumOffset, unsigned zeroOffset)
+{
+  UInt32 sum = 0;
+  unsigned i;
+  for (i = 0; i < checkSumOffset; i++)
+    sum += p[i];
+  for (i = checkSumOffset + 4; i < size; i++)
+    sum += p[i];
+  if (~sum != Get32(p + checkSumOffset))
+    return false;
+  for (i = zeroOffset; i < size; i++)
+    if (p[i] != 0)
+      return false;
+  return true;
+}
+
+bool CFooter::Parse(const Byte *p)
+{
+  if (memcmp(p, "conectix", 8) != 0)
+    return false;
+  // G32(p + 0x08, Features);
+  // G32(p + 0x0C, FormatVersion);
+  G64(p + 0x10, DataOffset);
+  G32(p + 0x18, CTime);
+  G32(p + 0x1C, CreatorApp);
+  G32(p + 0x20, CreatorVersion);
+  G32(p + 0x24, CreatorHostOS);
+  // G64(p + 0x28, OriginalSize);
+  G64(p + 0x30, CurrentSize);
+  G32(p + 0x38, DiskGeometry);
+  G32(p + 0x3C, Type);
+  memcpy(Id, p + 0x44, 16);
+  SavedState = p[0x54];
+  return CheckBlock(p, 512, 0x40, 0x55);
+}
+
+/*
+struct CParentLocatorEntry
+{
+  UInt32 Code;
+  UInt32 DataSpace;
+  UInt32 DataLen;
+  UInt64 DataOffset;
+
+  bool Parse(const Byte *p);
+};
+bool CParentLocatorEntry::Parse(const Byte *p)
+{
+  G32(p + 0x00, Code);
+  G32(p + 0x04, DataSpace);
+  G32(p + 0x08, DataLen);
+  G32(p + 0x10, DataOffset);
+  return (Get32(p + 0x0C) == 0); // Resrved
+}
+*/
+
+struct CDynHeader
+{
+  // UInt64 DataOffset;
+  UInt64 TableOffset;
+  // UInt32 HeaderVersion;
+  UInt32 NumBlocks;
+  int BlockSizeLog;
+  UInt32 ParentTime;
+  Byte ParentId[16];
+  UString ParentName;
+  // CParentLocatorEntry ParentLocators[8];
+
+  bool Parse(const Byte *p);
+  UInt32 NumBitMapSectors() const
+  {
+    UInt32 numSectorsInBlock = (1 << (BlockSizeLog - 9));
+    return (numSectorsInBlock + 512 * 8 - 1) / (512 * 8);
+  }
+};
+
+static int GetLog(UInt32 num)
+{
+  for (int i = 0; i < 31; i++)
+    if (((UInt32)1 << i) == num)
+      return i;
+  return -1;
+}
+
+bool CDynHeader::Parse(const Byte *p)
+{
+  if (memcmp(p, "cxsparse", 8) != 0)
+    return false;
+  // G64(p + 0x08, DataOffset);
+  G64(p + 0x10, TableOffset);
+  // G32(p + 0x18, HeaderVersion);
+  G32(p + 0x1C, NumBlocks);
+  BlockSizeLog = GetLog(Get32(p + 0x20));
+  if (BlockSizeLog < 9 || BlockSizeLog > 30)
+    return false;
+  G32(p + 0x38, ParentTime);
+  if (Get32(p + 0x3C) != 0) // reserved
+    return false;
+  memcpy(ParentId, p + 0x28, 16);
+  {
+    const int kNameLength = 256;
+    wchar_t *s = ParentName.GetBuffer(kNameLength);
+    for (unsigned i = 0; i < kNameLength; i++)
+      s[i] = Get16(p + 0x40 + i * 2);
+    s[kNameLength] = 0;
+    ParentName.ReleaseBuffer();
+  }
+  /*
+  for (int i = 0; i < 8; i++)
+    if (!ParentLocators[i].Parse(p + 0x240 + i * 24))
+      return false;
+  */
+  return CheckBlock(p, 1024, 0x24, 0x240 + 8 * 24);
+}
+
+class CHandler:
+  public IInStream,
+  public IInArchive,
+  public IInArchiveGetStream,
+  public CMyUnknownImp
+{
+  UInt64 _virtPos;
+  UInt64 _phyPos;
+  UInt64 _phyLimit;
+
+  CFooter Footer;
+  CDynHeader Dyn;
+  CRecordVector<UInt32> Bat;
+  CByteBuffer BitMap;
+  UInt32 BitMapTag;
+  UInt32 NumUsedBlocks;
+  CMyComPtr<IInStream> Stream;
+  CMyComPtr<IInStream> ParentStream;
+  CHandler *Parent;
+
+  HRESULT Seek(UInt64 offset);
+  HRESULT InitAndSeek();
+  HRESULT ReadPhy(UInt64 offset, void *data, UInt32 size);
+
+  bool NeedParent() const { return Footer.Type == kDiskType_Diff; }
+  UInt64 GetPackSize() const
+    { return Footer.ThereIsDynamic() ? ((UInt64)NumUsedBlocks << Dyn.BlockSizeLog) : Footer.CurrentSize; }
+
+  UString GetParentName() const
+  {
+    const CHandler *p = this;
+    UString res;
+    while (p && p->NeedParent())
+    {
+      if (!res.IsEmpty())
+        res += L" -> ";
+      res += p->Dyn.ParentName;
+      p = p->Parent;
+    }
+    return res;
+  }
+
+  bool IsOK() const
+  {
+    const CHandler *p = this;
+    while (p->NeedParent())
+    {
+      p = p->Parent;
+      if (p == 0)
+        return false;
+    }
+    return true;
+  }
+
+  HRESULT Open3();
+  HRESULT Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, int level);
+
+public:
+  MY_UNKNOWN_IMP3(IInArchive, IInArchiveGetStream, IInStream)
+
+  INTERFACE_IInArchive(;)
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+};
+
+HRESULT CHandler::Seek(UInt64 offset) { return Stream->Seek(offset, STREAM_SEEK_SET, NULL); }
+
+HRESULT CHandler::InitAndSeek()
+{
+  if (ParentStream)
+  {
+    RINOK(Parent->InitAndSeek());
+  }
+  _virtPos = _phyPos = 0;
+  BitMapTag = kUnusedBlock;
+  BitMap.SetCapacity(Dyn.NumBitMapSectors() << 9);
+  return Seek(0);
+}
+
+HRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size)
+{
+  if (offset + size > _phyLimit)
+    return S_FALSE;
+  if (offset != _phyPos)
+  {
+    _phyPos = offset;
+    RINOK(Seek(offset));
+  }
+  HRESULT res = ReadStream_FALSE(Stream, data, size);
+  _phyPos += size;
+  return res;
+}
+
+HRESULT CHandler::Open3()
+{
+  RINOK(Stream->Seek(0, STREAM_SEEK_END, &_phyPos));
+  if (_phyPos < 512)
+    return S_FALSE;
+  const UInt32 kDynSize = 1024;
+  Byte buf[kDynSize];
+
+  _phyLimit = _phyPos;
+  RINOK(ReadPhy(_phyLimit - 512, buf, 512));
+  if (!Footer.Parse(buf))
+    return S_FALSE;
+  _phyLimit -= 512;
+
+  if (!Footer.ThereIsDynamic())
+    return S_OK;
+
+  RINOK(ReadPhy(0, buf + 512, 512));
+  if (memcmp(buf, buf + 512, 512) != 0)
+    return S_FALSE;
+
+  RINOK(ReadPhy(Footer.DataOffset, buf, kDynSize));
+  if (!Dyn.Parse(buf))
+    return S_FALSE;
+  
+  if (Dyn.NumBlocks >= (UInt32)1 << 31)
+    return S_FALSE;
+  if (Footer.CurrentSize == 0)
+  {
+    if (Dyn.NumBlocks != 0)
+      return S_FALSE;
+  }
+  else if (((Footer.CurrentSize - 1) >> Dyn.BlockSizeLog) + 1 != Dyn.NumBlocks)
+    return S_FALSE;
+
+  Bat.Reserve(Dyn.NumBlocks);
+  while ((UInt32)Bat.Size() < Dyn.NumBlocks)
+  {
+    RINOK(ReadPhy(Dyn.TableOffset + (UInt64)Bat.Size() * 4, buf, 512));
+    for (UInt32 j = 0; j < 512; j += 4)
+    {
+      UInt32 v = Get32(buf + j);
+      if (v != kUnusedBlock)
+        NumUsedBlocks++;
+      Bat.Add(v);
+      if ((UInt32)Bat.Size() >= Dyn.NumBlocks)
+        break;
+    }
+  }
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  if (processedSize != NULL)
+    *processedSize = 0;
+  if (_virtPos >= Footer.CurrentSize)
+    return (Footer.CurrentSize == _virtPos) ? S_OK: E_FAIL;
+  UInt64 rem = Footer.CurrentSize - _virtPos;
+  if (size > rem)
+    size = (UInt32)rem;
+  if (size == 0)
+    return S_OK;
+  UInt32 blockIndex = (UInt32)(_virtPos >> Dyn.BlockSizeLog);
+  UInt32 blockSectIndex = Bat[blockIndex];
+  UInt32 blockSize = (UInt32)1 << Dyn.BlockSizeLog;
+  UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);
+  size = MyMin(blockSize - offsetInBlock, size);
+
+  HRESULT res = S_OK;
+  if (blockSectIndex == kUnusedBlock)
+  {
+    if (ParentStream)
+    {
+      RINOK(ParentStream->Seek(_virtPos, STREAM_SEEK_SET, NULL));
+      res = ParentStream->Read(data, size, &size);
+    }
+    else
+      memset(data, 0, size);
+  }
+  else
+  {
+    UInt64 newPos = (UInt64)blockSectIndex << 9;
+    if (BitMapTag != blockIndex)
+    {
+      RINOK(ReadPhy(newPos, BitMap, (UInt32)BitMap.GetCapacity()));
+      BitMapTag = blockIndex;
+    }
+    RINOK(ReadPhy(newPos + BitMap.GetCapacity() + offsetInBlock, data, size));
+    for (UInt32 cur = 0; cur < size;)
+    {
+      UInt32 rem = MyMin(0x200 - (offsetInBlock & 0x1FF), size - cur);
+      UInt32 bmi = offsetInBlock >> 9;
+      if (((BitMap[bmi >> 3] >> (7 - (bmi & 7))) & 1) == 0)
+      {
+        if (ParentStream)
+        {
+          RINOK(ParentStream->Seek(_virtPos + cur, STREAM_SEEK_SET, NULL));
+          RINOK(ReadStream_FALSE(ParentStream, (Byte *)data + cur, rem));
+        }
+        else
+        {
+          const Byte *p = (const Byte *)data + cur;
+          for (UInt32 i = 0; i < rem; i++)
+            if (p[i] != 0)
+              return S_FALSE;
+        }
+      }
+      offsetInBlock += rem;
+      cur += rem;
+    }
+  }
+  if (processedSize != NULL)
+    *processedSize = size;
+  _virtPos += size;
+  return res;
+}
+
+STDMETHODIMP CHandler::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+  switch(seekOrigin)
+  {
+    case STREAM_SEEK_SET: _virtPos = offset; break;
+    case STREAM_SEEK_CUR: _virtPos += offset; break;
+    case STREAM_SEEK_END: _virtPos = Footer.CurrentSize + offset; break;
+    default: return STG_E_INVALIDFUNCTION;
+  }
+  if (newPosition)
+    *newPosition = _virtPos;
+  return S_OK;
+}
+
+enum
+{
+  kpidParent = kpidUserDefined,
+  kpidSavedState
+};
+
+STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidCTime, VT_FILETIME},
+  { NULL, kpidClusterSize, VT_UI8},
+  { NULL, kpidMethod, VT_BSTR},
+  { L"Parent", kpidParent, VT_BSTR},
+  { NULL, kpidCreatorApp, VT_BSTR},
+  { NULL, kpidHostOS, VT_BSTR},
+  { L"Saved State", kpidSavedState, VT_BOOL},
+  { NULL, kpidId, VT_BSTR}
+ };
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidCTime, VT_FILETIME}
+  
+  /*
+  { NULL, kpidNumCyls, VT_UI4},
+  { NULL, kpidNumHeads, VT_UI4},
+  { NULL, kpidSectorsPerTrack, VT_UI4}
+  */
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_WITH_NAME
+
+// VHD start time: 2000-01-01
+static const UInt64 kVhdTimeStartValue = (UInt64)3600 * 24 * (399 * 365 + 24 * 4);
+
+static void VhdTimeToFileTime(UInt32 vhdTime, NCOM::CPropVariant &prop)
+{
+  FILETIME ft, utc;
+  UInt64 v = (kVhdTimeStartValue + vhdTime) * 10000000;
+  ft.dwLowDateTime = (DWORD)v;
+  ft.dwHighDateTime = (DWORD)(v >> 32);
+  // specification says that it's UTC time, but Virtual PC 6 writes local time. Why?
+  LocalFileTimeToFileTime(&ft, &utc);
+  prop = utc;
+}
+
+static void StringToAString(char *dest, UInt32 s)
+{
+  for (int i = 24; i >= 0; i -= 8)
+  {
+    Byte b = (Byte)((s >> i) & 0xFF);
+    if (b < 0x20 || b > 0x7F)
+      break;
+    *dest++ = b;
+  }
+  *dest = 0;
+}
+
+static void ConvertByteToHex(unsigned value, char *s)
+{
+  for (int i = 0; i < 2; i++)
+  {
+    unsigned t = value & 0xF;
+    value >>= 4;
+    s[1 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
+  }
+}
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidMainSubfile: prop = (UInt32)0; break;
+    case kpidCTime: VhdTimeToFileTime(Footer.CTime, prop); break;
+    case kpidClusterSize: if (Footer.ThereIsDynamic()) prop = (UInt32)1 << Dyn.BlockSizeLog; break;
+    case kpidMethod:
+    {
+      AString s = Footer.GetTypeString();
+      if (NeedParent())
+      {
+        s += " -> ";
+        const CHandler *p = this;
+        while (p != 0 && p->NeedParent())
+          p = p->Parent;
+        if (p == 0)
+          s += '?';
+        else
+          s += p->Footer.GetTypeString();
+      }
+      prop = s;
+      break;
+    }
+    case kpidCreatorApp:
+    {
+      char s[16];
+      StringToAString(s, Footer.CreatorApp);
+      AString res = s;
+      res.Trim();
+      ConvertUInt32ToString(Footer.CreatorVersion >> 16, s);
+      res += ' ';
+      res += s;
+      res += '.';
+      ConvertUInt32ToString(Footer.CreatorVersion & 0xFFFF, s);
+      res += s;
+      prop = res;
+      break;
+    }
+    case kpidHostOS:
+    {
+      if (Footer.CreatorHostOS == 0x5769326b)
+        prop = "Windows";
+      else
+      {
+        char s[16];
+        StringToAString(s, Footer.CreatorHostOS);
+        prop = s;
+      }
+      break;
+    }
+    case kpidId:
+    {
+      char s[32 + 4];
+      for (int i = 0; i < 16; i++)
+        ConvertByteToHex(Footer.Id[i], s + i * 2);
+      s[32] = 0;
+      prop = s;
+      break;
+    }
+    case kpidSavedState: prop = Footer.SavedState ? true : false; break;
+    case kpidParent: if (NeedParent()) prop = GetParentName(); break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+HRESULT CHandler::Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, int level)
+{
+  Close();
+  Stream = stream;
+  if (level > 32)
+    return S_FALSE;
+  RINOK(Open3());
+  if (child && memcmp(child->Dyn.ParentId, Footer.Id, 16) != 0)
+    return S_FALSE;
+  if (Footer.Type != kDiskType_Diff)
+    return S_OK;
+  CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
+  if (openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback) != S_OK)
+    return S_FALSE;
+  CMyComPtr<IInStream> nextStream;
+  HRESULT res = openVolumeCallback->GetStream(Dyn.ParentName, &nextStream);
+  if (res == S_FALSE)
+    return S_OK;
+  RINOK(res);
+
+  Parent = new CHandler;
+  ParentStream = Parent;
+  return Parent->Open2(nextStream, this, openArchiveCallback, level + 1);
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+    const UInt64 * /* maxCheckStartPosition */,
+    IArchiveOpenCallback * openArchiveCallback)
+{
+  COM_TRY_BEGIN
+  {
+    HRESULT res;
+    try
+    {
+      res = Open2(stream, NULL, openArchiveCallback, 0);
+      if (res == S_OK)
+        return S_OK;
+    }
+    catch(...)
+    {
+      Close();
+      throw;
+    }
+    Close();
+    return res;
+  }
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  Bat.Clear();
+  NumUsedBlocks = 0;
+  Parent = 0;
+  Stream.Release();
+  ParentStream.Release();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = 1;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+
+  switch(propID)
+  {
+    case kpidSize: prop = Footer.CurrentSize; break;
+    case kpidPackSize: prop = GetPackSize(); break;
+    case kpidCTime: VhdTimeToFileTime(Footer.CTime, prop); break;
+    /*
+    case kpidNumCyls: prop = Footer.NumCyls(); break;
+    case kpidNumHeads: prop = Footer.NumHeads(); break;
+    case kpidSectorsPerTrack: prop = Footer.NumSectorsPerTrack(); break;
+    */
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  if (numItems == 0)
+    return S_OK;
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
+    return E_INVALIDARG;
+
+  RINOK(extractCallback->SetTotal(Footer.CurrentSize));
+  CMyComPtr<ISequentialOutStream> outStream;
+  Int32 askMode = testMode ?
+      NExtract::NAskMode::kTest :
+      NExtract::NAskMode::kExtract;
+  RINOK(extractCallback->GetStream(0, &outStream, askMode));
+  if (!testMode && !outStream)
+    return S_OK;
+  RINOK(extractCallback->PrepareOperation(askMode));
+
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  int res = NExtract::NOperationResult::kDataError;
+  CMyComPtr<ISequentialInStream> inStream;
+  HRESULT hres = GetStream(0, &inStream);
+  if (hres == S_FALSE)
+    res = NExtract::NOperationResult::kUnSupportedMethod;
+  else
+  {
+    RINOK(hres);
+    HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
+    if (hres == S_OK)
+    {
+      if (copyCoderSpec->TotalSize == Footer.CurrentSize)
+        res = NExtract::NOperationResult::kOK;
+    }
+    else
+    {
+      if (hres != S_FALSE)
+      {
+        RINOK(hres);
+      }
+    }
+  }
+  outStream.Release();
+  return extractCallback->SetOperationResult(res);
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream)
+{
+  COM_TRY_BEGIN
+  *stream = 0;
+  if (Footer.IsFixed())
+  {
+    CLimitedInStream *streamSpec = new CLimitedInStream;
+    CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
+    streamSpec->SetStream(Stream);
+    streamSpec->InitAndSeek(0, Footer.CurrentSize);
+    RINOK(streamSpec->SeekToStart());
+    *stream = streamTemp.Detach();
+    return S_OK;
+  }
+  if (!Footer.ThereIsDynamic() || !IsOK())
+    return S_FALSE;
+  CMyComPtr<ISequentialInStream> streamTemp = this;
+  RINOK(InitAndSeek());
+  *stream = streamTemp.Detach();
+  return S_OK;
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"VHD", L"vhd", L".mbr", 0xDC, { 'c', 'o', 'n', 'e', 'c', 't', 'i', 'x', 0, 0 }, 10, false, CreateArc, 0 };
+
+REGISTER_ARC(Vhd)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,660 @@
+// WimHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/CpuArch.h"
+
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+#include "Common/StringToInt.h"
+#include "Common/UTFConvert.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/StreamUtils.h"
+
+#include "WimHandler.h"
+
+#define Get16(p) GetUi16(p)
+#define Get32(p) GetUi32(p)
+#define Get64(p) GetUi64(p)
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NWim {
+
+#define WIM_DETAILS
+
+static STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidIsDir, VT_BOOL},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMTime, VT_FILETIME},
+  { NULL, kpidCTime, VT_FILETIME},
+  { NULL, kpidATime, VT_FILETIME},
+  { NULL, kpidAttrib, VT_UI4},
+  { NULL, kpidMethod, VT_BSTR},
+  { NULL, kpidShortName, VT_BSTR}
+  
+  #ifdef WIM_DETAILS
+  , { NULL, kpidVolume, VT_UI4}
+  , { NULL, kpidOffset, VT_UI8}
+  , { NULL, kpidLinks, VT_UI4}
+  #endif
+};
+
+static STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMethod, VT_BSTR},
+  { NULL, kpidCTime, VT_FILETIME},
+  { NULL, kpidMTime, VT_FILETIME},
+  { NULL, kpidComment, VT_BSTR},
+  { NULL, kpidUnpackVer, VT_BSTR},
+  { NULL, kpidIsVolume, VT_BOOL},
+  { NULL, kpidVolume, VT_UI4},
+  { NULL, kpidNumVolumes, VT_UI4}
+};
+
+static bool ParseNumber64(const AString &s, UInt64 &res)
+{
+  const char *end;
+  if (s.Left(2) == "0x")
+  {
+    if (s.Length() == 2)
+      return false;
+    res = ConvertHexStringToUInt64((const char *)s + 2, &end);
+  }
+  else
+  {
+    if (s.IsEmpty())
+      return false;
+    res = ConvertStringToUInt64(s, &end);
+  }
+  return *end == 0;
+}
+
+static bool ParseNumber32(const AString &s, UInt32 &res)
+{
+  UInt64 res64;
+  if (!ParseNumber64(s, res64) || res64 >= ((UInt64)1 << 32))
+    return false;
+  res = (UInt32)res64;
+  return true;
+}
+
+bool ParseTime(const CXmlItem &item, FILETIME &ft, const char *tag)
+{
+  int index = item.FindSubTag(tag);
+  if (index >= 0)
+  {
+    const CXmlItem &timeItem = item.SubItems[index];
+    UInt32 low = 0, high = 0;
+    if (ParseNumber32(timeItem.GetSubStringForTag("LOWPART"), low) &&
+        ParseNumber32(timeItem.GetSubStringForTag("HIGHPART"), high))
+    {
+      ft.dwLowDateTime = low;
+      ft.dwHighDateTime = high;
+      return true;
+    }
+  }
+  return false;
+}
+
+void CImageInfo::Parse(const CXmlItem &item)
+{
+  CTimeDefined = ParseTime(item, CTime, "CREATIONTIME");
+  MTimeDefined = ParseTime(item, MTime, "LASTMODIFICATIONTIME");
+  NameDefined = ConvertUTF8ToUnicode(item.GetSubStringForTag("NAME"), Name);
+  // IndexDefined = ParseNumber32(item.GetPropertyValue("INDEX"), Index);
+}
+
+void CXml::ToUnicode(UString &s)
+{
+  size_t size = Data.GetCapacity();
+  if (size < 2 || (size & 1) != 0 || size > (1 << 24))
+    return;
+  const Byte *p = Data;
+  if (Get16(p) != 0xFEFF)
+    return;
+  wchar_t *chars = s.GetBuffer((int)size / 2);
+  for (size_t i = 2; i < size; i += 2)
+    *chars++ = (wchar_t)Get16(p + i);
+  *chars = 0;
+  s.ReleaseBuffer();
+}
+
+void CXml::Parse()
+{
+  UString s;
+  ToUnicode(s);
+  AString utf;
+  if (!ConvertUnicodeToUTF8(s, utf))
+    return;
+  ::CXml xml;
+  if (!xml.Parse(utf))
+    return;
+  if (xml.Root.Name != "WIM")
+    return;
+
+  for (int i = 0; i < xml.Root.SubItems.Size(); i++)
+  {
+    const CXmlItem &item = xml.Root.SubItems[i];
+    if (item.IsTagged("IMAGE"))
+    {
+      CImageInfo imageInfo;
+      imageInfo.Parse(item);
+      Images.Add(imageInfo);
+    }
+  }
+}
+
+static const char *kMethodLZX = "LZX";
+static const char *kMethodXpress = "XPress";
+static const char *kMethodCopy = "Copy";
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+
+  const CImageInfo *image = NULL;
+  if (_xmls.Size() == 1)
+  {
+    const CXml &xml = _xmls[0];
+    if (xml.Images.Size() == 1)
+      image = &xml.Images[0];
+  }
+
+  switch(propID)
+  {
+    case kpidSize: prop = _db.GetUnpackSize(); break;
+    case kpidPackSize: prop = _db.GetPackSize(); break;
+    
+    case kpidCTime:
+      if (_xmls.Size() == 1)
+      {
+        const CXml &xml = _xmls[0];
+        int index = -1;
+        for (int i = 0; i < xml.Images.Size(); i++)
+        {
+          const CImageInfo &image = xml.Images[i];
+          if (image.CTimeDefined)
+            if (index < 0 || ::CompareFileTime(&image.CTime, &xml.Images[index].CTime) < 0)
+              index = i;
+        }
+        if (index >= 0)
+          prop = xml.Images[index].CTime;
+      }
+      break;
+
+    case kpidMTime:
+      if (_xmls.Size() == 1)
+      {
+        const CXml &xml = _xmls[0];
+        int index = -1;
+        for (int i = 0; i < xml.Images.Size(); i++)
+        {
+          const CImageInfo &image = xml.Images[i];
+          if (image.MTimeDefined)
+            if (index < 0 || ::CompareFileTime(&image.MTime, &xml.Images[index].MTime) > 0)
+              index = i;
+        }
+        if (index >= 0)
+          prop = xml.Images[index].MTime;
+      }
+      break;
+
+    case kpidComment:
+      if (image != NULL)
+      {
+        if (_xmlInComments)
+        {
+          UString s;
+          _xmls[0].ToUnicode(s);
+          prop = s;
+        }
+        else if (image->NameDefined)
+          prop = image->Name;
+      }
+      break;
+
+    case kpidUnpackVer:
+    {
+      UInt32 ver1 = _version >> 16;
+      UInt32 ver2 = (_version >> 8) & 0xFF;
+      UInt32 ver3 = (_version) & 0xFF;
+
+      char s[16];
+      ConvertUInt32ToString(ver1, s);
+      AString res = s;
+      res += '.';
+      ConvertUInt32ToString(ver2, s);
+      res += s;
+      if (ver3 != 0)
+      {
+        res += '.';
+        ConvertUInt32ToString(ver3, s);
+        res += s;
+      }
+      prop = res;
+      break;
+    }
+
+    case kpidIsVolume:
+      if (_xmls.Size() > 0)
+      {
+        UInt16 volIndex = _xmls[0].VolIndex;
+        if (volIndex < _volumes.Size())
+          prop = (_volumes[volIndex].Header.NumParts > 1);
+      }
+      break;
+    case kpidVolume:
+      if (_xmls.Size() > 0)
+      {
+        UInt16 volIndex = _xmls[0].VolIndex;
+        if (volIndex < _volumes.Size())
+          prop = (UInt32)_volumes[volIndex].Header.PartNumber;
+      }
+      break;
+    case kpidNumVolumes: if (_volumes.Size() > 0) prop = (UInt32)(_volumes.Size() - 1); break;
+    case kpidMethod:
+    {
+      bool lzx = false, xpress = false, copy = false;
+      for (int i = 0; i < _xmls.Size(); i++)
+      {
+        const CHeader &header = _volumes[_xmls[i].VolIndex].Header;
+        if (header.IsCompressed())
+          if (header.IsLzxMode())
+            lzx = true;
+          else
+            xpress = true;
+        else
+          copy = true;
+      }
+      AString res;
+      if (lzx)
+        res = kMethodLZX;
+      if (xpress)
+      {
+        if (!res.IsEmpty())
+          res += ' ';
+        res += kMethodXpress;
+      }
+      if (copy)
+      {
+        if (!res.IsEmpty())
+          res += ' ';
+        res += kMethodCopy;
+      }
+      prop = res;
+    }
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  if (index < (UInt32)_db.SortedItems.Size())
+  {
+    int realIndex = _db.SortedItems[index];
+    const CItem &item = _db.Items[realIndex];
+    const CStreamInfo *si = NULL;
+    const CVolume *vol = NULL;
+    if (item.StreamIndex >= 0)
+    {
+      si = &_db.Streams[item.StreamIndex];
+      vol = &_volumes[si->PartNumber];
+    }
+
+    switch(propID)
+    {
+      case kpidPath:
+        if (item.HasMetadata)
+          prop = _db.GetItemPath(realIndex);
+        else
+        {
+          char sz[16];
+          ConvertUInt32ToString(item.StreamIndex, sz);
+          AString s = sz;
+          while (s.Length() < _nameLenForStreams)
+            s = '0' + s;
+          /*
+          if (si->Resource.IsFree())
+            prefix = "[Free]";
+          */
+          s = "[Files]" STRING_PATH_SEPARATOR + s;
+          prop = s;
+        }
+        break;
+      case kpidShortName: if (item.HasMetadata) prop = item.ShortName; break;
+
+      case kpidIsDir: prop = item.IsDir(); break;
+      case kpidAttrib: if (item.HasMetadata) prop = item.Attrib; break;
+      case kpidCTime: if (item.HasMetadata) prop = item.CTime; break;
+      case kpidATime: if (item.HasMetadata) prop = item.ATime; break;
+      case kpidMTime: if (item.HasMetadata) prop = item.MTime; break;
+      case kpidPackSize: prop = si ? si->Resource.PackSize : (UInt64)0; break;
+      case kpidSize: prop = si ? si->Resource.UnpackSize : (UInt64)0; break;
+      case kpidMethod: if (si) prop = si->Resource.IsCompressed() ?
+          (vol->Header.IsLzxMode() ? kMethodLZX : kMethodXpress) : kMethodCopy; break;
+      #ifdef WIM_DETAILS
+      case kpidVolume: if (si) prop = (UInt32)si->PartNumber; break;
+      case kpidOffset: if (si)  prop = (UInt64)si->Resource.Offset; break;
+      case kpidLinks: prop = si ? (UInt32)si->RefCount : (UInt32)0; break;
+      #endif
+    }
+  }
+  else
+  {
+    index -= _db.SortedItems.Size();
+    {
+      switch(propID)
+      {
+        case kpidPath:
+        {
+          char sz[16];
+          ConvertUInt32ToString(_xmls[index].VolIndex, sz);
+          prop = (AString)"[" + (AString)sz + "].xml";
+          break;
+        }
+        case kpidIsDir: prop = false; break;
+        case kpidPackSize:
+        case kpidSize: prop = (UInt64)_xmls[index].Data.GetCapacity(); break;
+        case kpidMethod: prop = kMethodCopy; break;
+      }
+    }
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+class CVolumeName
+{
+  // UInt32 _volIndex;
+  UString _before;
+  UString _after;
+public:
+  CVolumeName() {};
+
+  void InitName(const UString &name)
+  {
+    // _volIndex = 1;
+    int dotPos = name.ReverseFind('.');
+    if (dotPos < 0)
+      dotPos = name.Length();
+    _before = name.Left(dotPos);
+    _after = name.Mid(dotPos);
+  }
+
+  UString GetNextName(UInt32 index)
+  {
+    wchar_t s[16];
+    ConvertUInt32ToString(index, s);
+    return _before + (UString)s + _after;
+  }
+};
+
+STDMETHODIMP CHandler::Open(IInStream *inStream,
+    const UInt64 * /* maxCheckStartPosition */,
+    IArchiveOpenCallback *openArchiveCallback)
+{
+  COM_TRY_BEGIN
+  Close();
+  {
+    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
+    
+    CVolumeName seqName;
+    if (openArchiveCallback != NULL)
+      openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
+
+    UInt32 numVolumes = 1;
+    int firstVolumeIndex = -1;
+    for (UInt32 i = 1; i <= numVolumes; i++)
+    {
+      CMyComPtr<IInStream> curStream;
+      if (i != 1)
+      {
+        UString fullName = seqName.GetNextName(i);
+        HRESULT result = openVolumeCallback->GetStream(fullName, &curStream);
+        if (result == S_FALSE)
+          continue;
+        if (result != S_OK)
+          return result;
+        if (!curStream)
+          break;
+      }
+      else
+        curStream = inStream;
+      CHeader header;
+      HRESULT res = NWim::ReadHeader(curStream, header);
+      if (res != S_OK)
+      {
+        if (i == 1)
+          return res;
+        if (res == S_FALSE)
+          continue;
+        return res;
+      }
+      _version = header.Version;
+      _isOldVersion = header.IsOldVersion();
+      if (firstVolumeIndex >= 0)
+        if (!header.AreFromOnArchive(_volumes[firstVolumeIndex].Header))
+          break;
+      if (_volumes.Size() > header.PartNumber && _volumes[header.PartNumber].Stream)
+        break;
+      CXml xml;
+      xml.VolIndex = header.PartNumber;
+      res = _db.Open(curStream, header, xml.Data, openArchiveCallback);
+      if (res != S_OK)
+      {
+        if (i == 1)
+          return res;
+        if (res == S_FALSE)
+          continue;
+        return res;
+      }
+      
+      while (_volumes.Size() <= header.PartNumber)
+        _volumes.Add(CVolume());
+      CVolume &volume = _volumes[header.PartNumber];
+      volume.Header = header;
+      volume.Stream = curStream;
+      
+      firstVolumeIndex = header.PartNumber;
+      
+      bool needAddXml = true;
+      if (_xmls.Size() != 0)
+        if (xml.Data == _xmls[0].Data)
+          needAddXml = false;
+      if (needAddXml)
+      {
+        xml.Parse();
+        _xmls.Add(xml);
+      }
+      
+      if (i == 1)
+      {
+        if (header.PartNumber != 1)
+          break;
+        if (!openVolumeCallback)
+          break;
+        numVolumes = header.NumParts;
+        {
+          NCOM::CPropVariant prop;
+          RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
+          if (prop.vt != VT_BSTR)
+            break;
+          seqName.InitName(prop.bstrVal);
+        }
+      }
+    }
+
+    _db.DetectPathMode();
+    RINOK(_db.Sort(_db.SkipRoot));
+
+    wchar_t sz[16];
+    ConvertUInt32ToString(_db.Streams.Size(), sz);
+    _nameLenForStreams = MyStringLen(sz);
+
+    _xmlInComments = (_xmls.Size() == 1 && !_db.ShowImageNumber);
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _db.Clear();
+  _volumes.Clear();
+  _xmls.Clear();
+  _nameLenForStreams = 0;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+
+  if (allFilesMode)
+    numItems = _db.SortedItems.Size() + _xmls.Size();
+  if (numItems == 0)
+    return S_OK;
+
+  UInt32 i;
+  UInt64 totalSize = 0;
+  for (i = 0; i < numItems; i++)
+  {
+    UInt32 index = allFilesMode ? i : indices[i];
+    if (index < (UInt32)_db.SortedItems.Size())
+    {
+      int streamIndex = _db.Items[_db.SortedItems[index]].StreamIndex;
+      if (streamIndex >= 0)
+      {
+        const CStreamInfo &si = _db.Streams[streamIndex];
+        totalSize += si.Resource.UnpackSize;
+      }
+    }
+    else
+      totalSize += _xmls[index - (UInt32)_db.SortedItems.Size()].Data.GetCapacity();
+  }
+
+  RINOK(extractCallback->SetTotal(totalSize));
+
+  UInt64 currentTotalPacked = 0;
+  UInt64 currentTotalUnPacked = 0;
+  UInt64 currentItemUnPacked, currentItemPacked;
+  
+  int prevSuccessStreamIndex = -1;
+
+  CUnpacker unpacker;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  for (i = 0; i < numItems; currentTotalUnPacked += currentItemUnPacked,
+      currentTotalPacked += currentItemPacked)
+  {
+    currentItemUnPacked = 0;
+    currentItemPacked = 0;
+
+    lps->InSize = currentTotalPacked;
+    lps->OutSize = currentTotalUnPacked;
+
+    RINOK(lps->SetCur());
+    UInt32 index = allFilesMode ? i : indices[i];
+    i++;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+
+    CMyComPtr<ISequentialOutStream> realOutStream;
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+    if (index >= (UInt32)_db.SortedItems.Size())
+    {
+      if (!testMode && !realOutStream)
+        continue;
+      RINOK(extractCallback->PrepareOperation(askMode));
+      const CByteBuffer &data = _xmls[index - (UInt32)_db.SortedItems.Size()].Data;
+      currentItemUnPacked = data.GetCapacity();
+      if (realOutStream)
+      {
+        RINOK(WriteStream(realOutStream, (const Byte *)data, data.GetCapacity()));
+        realOutStream.Release();
+      }
+      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+      continue;
+    }
+
+    const CItem &item = _db.Items[_db.SortedItems[index]];
+    int streamIndex = item.StreamIndex;
+    if (streamIndex < 0)
+    {
+      if (!testMode && !realOutStream)
+        continue;
+      RINOK(extractCallback->PrepareOperation(askMode));
+      realOutStream.Release();
+      RINOK(extractCallback->SetOperationResult(item.HasStream() ?
+            NExtract::NOperationResult::kDataError :
+            NExtract::NOperationResult::kOK));
+      continue;
+    }
+
+    const CStreamInfo &si = _db.Streams[streamIndex];
+    currentItemUnPacked = si.Resource.UnpackSize;
+    currentItemPacked = si.Resource.PackSize;
+
+    if (!testMode && !realOutStream)
+      continue;
+    RINOK(extractCallback->PrepareOperation(askMode));
+    Int32 opRes = NExtract::NOperationResult::kOK;
+    if (streamIndex != prevSuccessStreamIndex || realOutStream)
+    {
+      Byte digest[20];
+      const CVolume &vol = _volumes[si.PartNumber];
+      HRESULT res = unpacker.Unpack(vol.Stream, si.Resource, vol.Header.IsLzxMode(),
+          realOutStream, progress, digest);
+      if (res == S_OK)
+      {
+        if (memcmp(digest, si.Hash, kHashSize) == 0)
+          prevSuccessStreamIndex = streamIndex;
+        else
+          opRes = NExtract::NOperationResult::kCRCError;
+      }
+      else if (res == S_FALSE)
+        opRes = NExtract::NOperationResult::kDataError;
+      else
+        return res;
+    }
+    realOutStream.Release();
+    RINOK(extractCallback->SetOperationResult(opRes));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _db.SortedItems.Size();
+  if (!_xmlInComments)
+    *numItems += _xmls.Size();
+  return S_OK;
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimHandler.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimHandler.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimHandler.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimHandler.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,77 @@
+// WimHandler.h
+
+#ifndef __ARCHIVE_WIM_HANDLER_H
+#define __ARCHIVE_WIM_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "Common/MyXml.h"
+
+#include "WimIn.h"
+
+namespace NArchive {
+namespace NWim {
+
+struct CVolume
+{
+  CHeader Header;
+  CMyComPtr<IInStream> Stream;
+};
+
+struct CImageInfo
+{
+  bool CTimeDefined;
+  bool MTimeDefined;
+  bool NameDefined;
+  // bool IndexDefined;
+  
+  FILETIME CTime;
+  FILETIME MTime;
+  UString Name;
+  // UInt32 Index;
+  
+  CImageInfo(): CTimeDefined(false), MTimeDefined(false), NameDefined(false)
+      // , IndexDefined(false)
+      {}
+  void Parse(const CXmlItem &item);
+};
+
+struct CXml
+{
+  CByteBuffer Data;
+  UInt16 VolIndex;
+  CObjectVector<CImageInfo> Images;
+
+  void ToUnicode(UString &s);
+  void Parse();
+};
+
+
+class CHandler:
+  public IInArchive,
+  public CMyUnknownImp
+{
+  CDatabase _db;
+  UInt32 _version;
+  bool _isOldVersion;
+  CObjectVector<CVolume> _volumes;
+  CObjectVector<CXml> _xmls;
+  int _nameLenForStreams;
+  bool _xmlInComments;
+
+public:
+  MY_UNKNOWN_IMP1(IInArchive)
+  INTERFACE_IInArchive(;)
+};
+
+class COutHandler:
+  public IOutArchive,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP1(IOutArchive)
+  INTERFACE_IOutArchive(;)
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimHandlerOut.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimHandlerOut.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimHandlerOut.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,639 @@
+// WimHandlerOut.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/CpuArch.h"
+
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/StreamUtils.h"
+
+#include "../../Crypto/RandGen.h"
+#include "../../Crypto/Sha1.h"
+
+#include "WimHandler.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NWim {
+
+struct CSha1Hash
+{
+  Byte Hash[kHashSize];
+};
+
+struct CHashList
+{
+  CRecordVector<CSha1Hash> Digests;
+  CIntVector Sorted;
+
+  int AddUnique(const CSha1Hash &h);
+};
+
+int CHashList::AddUnique(const CSha1Hash &h)
+{
+  int left = 0, right = Sorted.Size();
+  while (left != right)
+  {
+    int mid = (left + right) / 2;
+    int index = Sorted[mid];
+    UInt32 i;
+    const Byte *hash2 = Digests[index].Hash;
+    for (i = 0; i < kHashSize; i++)
+      if (h.Hash[i] != hash2[i])
+        break;
+    if (i == kHashSize)
+      return index;
+    if (h.Hash[i] < hash2[i])
+      right = mid;
+    else
+      left = mid + 1;
+  }
+  Sorted.Insert(left, Digests.Add(h));
+  return -1;
+}
+
+struct CUpdateItem
+{
+  UString Name;
+  UInt64 Size;
+  FILETIME CTime;
+  FILETIME ATime;
+  FILETIME MTime;
+  UInt32 Attrib;
+  bool IsDir;
+  int HashIndex;
+
+  CUpdateItem(): HashIndex(-1) {}
+};
+
+struct CDir
+{
+  int Index;
+  UString Name;
+  CObjectVector<CDir> Dirs;
+  CIntVector Files;
+  
+  CDir(): Index(-1) {}
+  bool IsLeaf() const { return Index >= 0; }
+  UInt64 GetNumDirs() const;
+  UInt64 GetNumFiles() const;
+  CDir* AddDir(CObjectVector<CUpdateItem> &items, const UString &name, int index);
+};
+
+UInt64 CDir::GetNumDirs() const
+{
+  UInt64 num = Dirs.Size();
+  for (int i = 0; i < Dirs.Size(); i++)
+    num += Dirs[i].GetNumDirs();
+  return num;
+}
+
+UInt64 CDir::GetNumFiles() const
+{
+  UInt64 num = Files.Size();
+  for (int i = 0; i < Dirs.Size(); i++)
+    num += Dirs[i].GetNumFiles();
+  return num;
+}
+
+CDir* CDir::AddDir(CObjectVector<CUpdateItem> &items, const UString &name, int index)
+{
+  int left = 0, right = Dirs.Size();
+  while (left != right)
+  {
+    int mid = (left + right) / 2;
+    CDir &d = Dirs[mid];
+    int compare = name.CompareNoCase(d.IsLeaf() ? items[Dirs[mid].Index].Name : d.Name);
+    if (compare == 0)
+    {
+      if (index >= 0)
+        d.Index = index;
+      return &d;
+    }
+    if (compare < 0)
+      right = mid;
+    else
+      left = mid + 1;
+  }
+  Dirs.Insert(left, CDir());
+  CDir &d = Dirs[left];
+  d.Index = index;
+  if (index < 0)
+    d.Name = name;
+  return &d;
+}
+
+
+STDMETHODIMP COutHandler::GetFileTimeType(UInt32 *type)
+{
+  *type = NFileTimeType::kWindows;
+  return S_OK;
+}
+
+static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propID, FILETIME &ft)
+{
+  ft.dwLowDateTime = ft.dwHighDateTime = 0;
+  NCOM::CPropVariant prop;
+  RINOK(callback->GetProperty(index, propID, &prop));
+  if (prop.vt == VT_FILETIME)
+    ft = prop.filetime;
+  else if (prop.vt != VT_EMPTY)
+    return E_INVALIDARG;
+  return S_OK;
+}
+
+#define Set16(p, d) SetUi16(p, d)
+#define Set32(p, d) SetUi32(p, d)
+#define Set64(p, d) SetUi64(p, d)
+
+void CResource::WriteTo(Byte *p) const
+{
+  Set64(p, PackSize);
+  p[7] = Flags;
+  Set64(p + 8, Offset);
+  Set64(p + 16, UnpackSize);
+}
+
+void CHeader::WriteTo(Byte *p) const
+{
+  memcpy(p, kSignature, kSignatureSize);
+  Set32(p + 8, kHeaderSizeMax);
+  Set32(p + 0xC, Version);
+  Set32(p + 0x10, Flags);
+  Set32(p + 0x14, ChunkSize);
+  memcpy(p + 0x18, Guid, 16);
+  Set16(p + 0x28, PartNumber);
+  Set16(p + 0x2A, NumParts);
+  Set32(p + 0x2C, NumImages);
+  OffsetResource.WriteTo(p + 0x30);
+  XmlResource.WriteTo(p + 0x48);
+  MetadataResource.WriteTo(p + 0x60);
+  IntegrityResource.WriteTo(p + 0x7C);
+  Set32(p + 0x78, BootIndex);
+  memset(p + 0x94, 0, 60);
+}
+
+void CStreamInfo::WriteTo(Byte *p) const
+{
+  Resource.WriteTo(p);
+  Set16(p + 0x18, PartNumber);
+  Set32(p + 0x1A, RefCount);
+  memcpy(p + 0x1E, Hash, kHashSize);
+}
+
+class CInStreamWithSha1:
+  public ISequentialInStream,
+  public CMyUnknownImp
+{
+  CMyComPtr<ISequentialInStream> _stream;
+  UInt64 _size;
+  NCrypto::NSha1::CContext _sha;
+public:
+  MY_UNKNOWN_IMP1(IInStream)
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+  void SetStream(ISequentialInStream *stream) { _stream = stream;  }
+  void Init()
+  {
+    _size = 0;
+    _sha.Init();
+  }
+  void ReleaseStream() { _stream.Release(); }
+  UInt64 GetSize() const { return _size; }
+  void Final(Byte *digest) { _sha.Final(digest); }
+};
+
+STDMETHODIMP CInStreamWithSha1::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 realProcessedSize;
+  HRESULT result = _stream->Read(data, size, &realProcessedSize);
+  _size += realProcessedSize;
+  _sha.Update((const Byte *)data, realProcessedSize);
+  if (processedSize != NULL)
+    *processedSize = realProcessedSize;
+  return result;
+}
+
+static void SetFileTimeToMem(Byte *p, const FILETIME &ft)
+{
+  Set32(p, ft.dwLowDateTime);
+  Set32(p + 4, ft.dwHighDateTime);
+}
+
+static size_t WriteItem(const CUpdateItem &item, Byte *p, const Byte *hash)
+{
+  int fileNameLen = item.Name.Length() * 2;
+  int fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);
+
+  size_t totalLen = ((kDirRecordSize + fileNameLen2 + 6) & ~7);
+  if (p)
+  {
+    memset(p, 0, totalLen);
+    Set64(p, totalLen);
+    Set64(p + 8, item.Attrib);
+    Set32(p + 0xC, (UInt32)(Int32)-1); // item.SecurityId
+    // Set64(p + 0x10, 0); // subdirOffset
+    SetFileTimeToMem(p + 0x28, item.CTime);
+    SetFileTimeToMem(p + 0x30, item.ATime);
+    SetFileTimeToMem(p + 0x38, item.MTime);
+    if (hash)
+      memcpy(p + 0x40, hash, kHashSize);
+    /*
+    else
+      memset(p + 0x40, 0, kHashSize);
+    */
+    // Set16(p + 98, 0); // shortNameLen
+    Set16(p + 100, (UInt16)fileNameLen);
+    for (int i = 0; i * 2 < fileNameLen; i++)
+      Set16(p + kDirRecordSize + i * 2, item.Name[i]);
+  }
+  return totalLen;
+}
+
+static void WriteTree(const CDir &tree, CRecordVector<CSha1Hash> &digests,
+    CUpdateItem &defaultDirItem,
+    CObjectVector<CUpdateItem> &updateItems, Byte *dest, size_t &pos)
+{
+  int i;
+  for (i = 0; i < tree.Files.Size(); i++)
+  {
+    const CUpdateItem &ui = updateItems[tree.Files[i]];
+    pos += WriteItem(ui, dest ? dest + pos : NULL,
+        ui.HashIndex >= 0 ? digests[ui.HashIndex].Hash : NULL);
+  }
+
+  size_t posStart = pos;
+  for (i = 0; i < tree.Dirs.Size(); i++)
+  {
+    const CDir &subfolder = tree.Dirs[i];
+    CUpdateItem *item = &defaultDirItem;
+    if (subfolder.IsLeaf())
+      item = &updateItems[subfolder.Index];
+    else
+      defaultDirItem.Name = subfolder.Name;
+    pos += WriteItem(*item, NULL, NULL);
+  }
+
+  if (dest)
+    Set64(dest + pos, 0);
+
+  pos += 8;
+
+  for (i = 0; i < tree.Dirs.Size(); i++)
+  {
+    const CDir &subfolder = tree.Dirs[i];
+    if (dest)
+    {
+      CUpdateItem *item = &defaultDirItem;
+      if (subfolder.IsLeaf())
+        item = &updateItems[subfolder.Index];
+      else
+        defaultDirItem.Name = subfolder.Name;
+      size_t len = WriteItem(*item, dest + posStart, NULL);
+      Set64(dest + posStart + 0x10, pos);
+      posStart += len;
+    }
+    WriteTree(subfolder, digests, defaultDirItem, updateItems, dest, pos);
+  }
+}
+
+static void AddTag(AString &s, const char *name, const AString &value)
+{
+  s += "<";
+  s += name;
+  s += ">";
+  s += value;
+  s += "</";
+  s += name;
+  s += ">";
+}
+
+static void AddTagUInt64(AString &s, const char *name, UInt64 value)
+{
+  char temp[32];
+  ConvertUInt64ToString(value, temp);
+  AddTag(s, name, temp);
+}
+
+static AString TimeToXml(FILETIME &ft)
+{
+  AString res;
+  char temp[16] = { '0', 'x' };
+  ConvertUInt32ToHexWithZeros(ft.dwHighDateTime, temp + 2);
+  AddTag(res, "HIGHPART", temp);
+  ConvertUInt32ToHexWithZeros(ft.dwLowDateTime, temp + 2);
+  AddTag(res, "LOWPART", temp);
+  return res;
+}
+
+void CHeader::SetDefaultFields(bool useLZX)
+{
+  Version = kWimVersion;
+  Flags = NHeaderFlags::kRpFix;
+  ChunkSize = 0;
+  if (useLZX)
+  {
+    Flags |= NHeaderFlags::kCompression | NHeaderFlags::kLZX;
+    ChunkSize = kChunkSize;
+  }
+  g_RandomGenerator.Generate(Guid, 16);
+  PartNumber = 1;
+  NumParts = 1;
+  NumImages = 1;
+  BootIndex = 0;
+  OffsetResource.Clear();
+  XmlResource.Clear();
+  MetadataResource.Clear();
+  IntegrityResource.Clear();
+}
+
+static HRESULT UpdateArchive(ISequentialOutStream *seqOutStream,
+    CDir &rootFolder,
+    CObjectVector<CUpdateItem> &updateItems,
+    IArchiveUpdateCallback *callback)
+{
+  CMyComPtr<IOutStream> outStream;
+  RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));
+  if (!outStream)
+    return E_NOTIMPL;
+
+  UInt64 complexity = 0;
+
+  int i;
+  for (i = 0; i < updateItems.Size(); i++)
+    complexity += updateItems[i].Size;
+
+  RINOK(callback->SetTotal(complexity));
+
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(callback, true);
+
+  complexity = 0;
+
+  bool useCompression = false;
+
+  CHeader header;
+  header.SetDefaultFields(useCompression);
+  Byte buf[kHeaderSizeMax];
+  header.WriteTo(buf);
+  RINOK(WriteStream(outStream, buf, kHeaderSizeMax));
+
+  CHashList hashes;
+  CObjectVector<CStreamInfo> streams;
+
+  UInt64 curPos = kHeaderSizeMax;
+  UInt64 unpackTotalSize = 0;
+  for (i = 0; i < updateItems.Size(); i++)
+  {
+    lps->InSize = lps->OutSize = complexity;
+    RINOK(lps->SetCur());
+
+    CUpdateItem &ui = updateItems[i];
+    if (ui.IsDir || ui.Size == 0)
+      continue;
+
+    CInStreamWithSha1 *inShaStreamSpec = new CInStreamWithSha1;
+    CMyComPtr<ISequentialInStream> inShaStream = inShaStreamSpec;
+
+    {
+      CMyComPtr<ISequentialInStream> fileInStream;
+      HRESULT res = callback->GetStream(i, &fileInStream);
+      if (res != S_FALSE)
+      {
+        RINOK(res);
+        inShaStreamSpec->SetStream(fileInStream);
+        fileInStream.Release();
+        inShaStreamSpec->Init();
+        UInt64 offsetBlockSize = 0;
+        if (useCompression)
+        {
+          for (UInt64 t = kChunkSize; t < ui.Size; t += kChunkSize)
+          {
+            Byte buf[8];
+            SetUi32(buf, (UInt32)t);
+            RINOK(WriteStream(outStream, buf, 4));
+            offsetBlockSize += 4;
+          }
+        }
+
+        RINOK(copyCoder->Code(inShaStream, outStream, NULL, NULL, progress));
+        ui.Size = copyCoderSpec->TotalSize;
+
+        CSha1Hash hash;
+        unpackTotalSize += ui.Size;
+        UInt64 packSize = offsetBlockSize + ui.Size;
+        inShaStreamSpec->Final(hash.Hash);
+        int index = hashes.AddUnique(hash);
+        if (index >= 0)
+        {
+          ui.HashIndex = index;
+          streams[index].RefCount++;
+          outStream->Seek(-(Int64)packSize, STREAM_SEEK_CUR, &curPos);
+          outStream->SetSize(curPos);
+        }
+        else
+        {
+          ui.HashIndex = hashes.Digests.Size() - 1;
+          CStreamInfo s;
+          s.Resource.PackSize = packSize;
+          s.Resource.Offset = curPos;
+          s.Resource.UnpackSize = ui.Size;
+          s.Resource.Flags = 0;
+          if (useCompression)
+            s.Resource.Flags = NResourceFlags::Compressed;
+          s.PartNumber = 1;
+          s.RefCount = 1;
+          memcpy(s.Hash, hash.Hash, kHashSize);
+          streams.Add(s);
+          curPos += packSize;
+        }
+      }
+      fileInStream.Release();
+      complexity += ui.Size;
+      RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+    }
+  }
+
+
+  CUpdateItem ri;
+  FILETIME ft;
+  NTime::GetCurUtcFileTime(ft);
+  ri.MTime = ri.ATime = ri.CTime = ft;
+  ri.Attrib = FILE_ATTRIBUTE_DIRECTORY;
+
+  const UInt32 kSecuritySize = 8;
+  size_t pos = kSecuritySize;
+  WriteTree(rootFolder, hashes.Digests, ri, updateItems, NULL, pos);
+  
+  CByteBuffer meta;
+  meta.SetCapacity(pos);
+  
+  // we can write 0 here only if there is no security data, imageX does it,
+  // but some programs expect size = 8
+  Set32((Byte *)meta, 8); // size of security data
+  Set32((Byte *)meta + 4, 0); // num security entries
+  
+  pos = kSecuritySize;
+  WriteTree(rootFolder, hashes.Digests, ri, updateItems, (Byte *)meta, pos);
+
+  {
+    NCrypto::NSha1::CContext sha;
+    sha.Init();
+    sha.Update((const Byte *)meta, pos);
+    CSha1Hash digest;
+    sha.Final(digest.Hash);
+
+    CStreamInfo s;
+    s.Resource.PackSize = pos;
+    s.Resource.Offset = curPos;
+    s.Resource.UnpackSize = pos;
+    s.Resource.Flags = NResourceFlags::kMetadata;
+    s.PartNumber = 1;
+    s.RefCount = 1;
+    memcpy(s.Hash, digest.Hash, kHashSize);
+    streams.Add(s);
+    RINOK(WriteStream(outStream, (const Byte *)meta, pos));
+    meta.Free();
+    curPos += pos;
+  }
+
+
+  header.OffsetResource.UnpackSize = header.OffsetResource.PackSize = (UInt64)streams.Size() * kStreamInfoSize;
+  header.OffsetResource.Offset = curPos;
+  header.OffsetResource.Flags = NResourceFlags::kMetadata;
+
+  for (i = 0; i < streams.Size(); i++)
+  {
+    Byte buf[kStreamInfoSize];
+    streams[i].WriteTo(buf);
+    RINOK(WriteStream(outStream, buf, kStreamInfoSize));
+    curPos += kStreamInfoSize;
+  }
+
+  AString xml = "<WIM>";
+  AddTagUInt64(xml, "TOTALBYTES", curPos);
+  xml += "<IMAGE INDEX=\"1\"><NAME>1</NAME>";
+  AddTagUInt64(xml, "DIRCOUNT", rootFolder.GetNumDirs());
+  AddTagUInt64(xml, "FILECOUNT", rootFolder.GetNumFiles());
+  AddTagUInt64(xml, "TOTALBYTES", unpackTotalSize);
+  NTime::GetCurUtcFileTime(ft);
+  AddTag(xml, "CREATIONTIME", TimeToXml(ft));
+  AddTag(xml, "LASTMODIFICATIONTIME", TimeToXml(ft));
+  xml += "</IMAGE></WIM>";
+
+  size_t xmlSize = (xml.Length() + 1) * 2;
+  meta.SetCapacity(xmlSize);
+  Set16((Byte *)meta, 0xFEFF);
+  for (i = 0; i < xml.Length(); i++)
+    Set16((Byte *)meta + 2 + i * 2, xml[i]);
+  RINOK(WriteStream(outStream, (const Byte *)meta, xmlSize));
+  meta.Free();
+  
+  header.XmlResource.UnpackSize = header.XmlResource.PackSize = xmlSize;
+  header.XmlResource.Offset = curPos;
+  header.XmlResource.Flags = NResourceFlags::kMetadata;
+
+  outStream->Seek(0, STREAM_SEEK_SET, NULL);
+  header.WriteTo(buf);
+  return WriteStream(outStream, buf, kHeaderSizeMax);
+}
+
+STDMETHODIMP COutHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+    IArchiveUpdateCallback *callback)
+{
+  COM_TRY_BEGIN
+  CObjectVector<CUpdateItem> updateItems;
+  CDir tree;
+  tree.Dirs.Add(CDir());
+  CDir &rootFolder = tree.Dirs.Back();
+
+  for (UInt32 i = 0; i < numItems; i++)
+  {
+    CUpdateItem ui;
+    Int32 newData, newProps;
+    UInt32 indexInArchive;
+    if (!callback)
+      return E_FAIL;
+    RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
+
+    {
+      NCOM::CPropVariant prop;
+      RINOK(callback->GetProperty(i, kpidIsDir, &prop));
+      if (prop.vt == VT_EMPTY)
+        ui.IsDir = false;
+      else if (prop.vt != VT_BOOL)
+        return E_INVALIDARG;
+      else
+        ui.IsDir = (prop.boolVal != VARIANT_FALSE);
+    }
+    
+    {
+      NCOM::CPropVariant prop;
+      RINOK(callback->GetProperty(i, kpidAttrib, &prop));
+      if (prop.vt == VT_EMPTY)
+        ui.Attrib = (ui.IsDir ? FILE_ATTRIBUTE_DIRECTORY : 0);
+      else if (prop.vt != VT_UI4)
+        return E_INVALIDARG;
+      else
+        ui.Attrib = prop.ulVal;
+    }
+    
+    RINOK(GetTime(callback, i, kpidCTime, ui.CTime));
+    RINOK(GetTime(callback, i, kpidATime, ui.ATime));
+    RINOK(GetTime(callback, i, kpidMTime, ui.MTime));
+
+    {
+      NCOM::CPropVariant prop;
+      RINOK(callback->GetProperty(i, kpidSize, &prop));
+      if (prop.vt != VT_UI8)
+        return E_INVALIDARG;
+      ui.Size = prop.uhVal.QuadPart;
+    }
+
+    UString path;
+    NCOM::CPropVariant prop;
+    RINOK(callback->GetProperty(i, kpidPath, &prop));
+    if (prop.vt == VT_BSTR)
+      path = prop.bstrVal;
+    else if (prop.vt != VT_EMPTY)
+      return E_INVALIDARG;
+
+    CDir *curItem = &rootFolder;
+    int len = path.Length();
+    UString fileName;
+    for (int j = 0; j < len; j++)
+    {
+      wchar_t c = path[j];
+      if (c == WCHAR_PATH_SEPARATOR || c == L'/')
+      {
+        curItem = curItem->AddDir(updateItems, fileName, -1);
+        fileName.Empty();
+      }
+      else
+        fileName += c;
+    }
+
+    ui.Name = fileName;
+    updateItems.Add(ui);
+    if (ui.IsDir)
+      curItem->AddDir(updateItems, fileName, (int)i);
+    else
+      curItem->Files.Add(i);
+  }
+  return UpdateArchive(outStream, tree, updateItems, callback);
+  COM_TRY_END
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimIn.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimIn.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimIn.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimIn.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,855 @@
+// Archive/WimIn.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/CpuArch.h"
+
+#include "Common/IntToString.h"
+
+#include "../../Common/StreamUtils.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/LimitedStreams.h"
+
+#include "../Common/OutStreamWithSha1.h"
+
+#include "WimIn.h"
+
+#define Get16(p) GetUi16(p)
+#define Get32(p) GetUi32(p)
+#define Get64(p) GetUi64(p)
+
+namespace NArchive {
+namespace NWim {
+
+namespace NXpress {
+
+class CDecoderFlusher
+{
+  CDecoder *m_Decoder;
+public:
+  bool NeedFlush;
+  CDecoderFlusher(CDecoder *decoder): m_Decoder(decoder), NeedFlush(true) {}
+  ~CDecoderFlusher()
+  {
+    if (NeedFlush)
+      m_Decoder->Flush();
+    m_Decoder->ReleaseStreams();
+  }
+};
+
+HRESULT CDecoder::CodeSpec(UInt32 outSize)
+{
+  {
+    Byte levels[kMainTableSize];
+    for (unsigned i = 0; i < kMainTableSize; i += 2)
+    {
+      Byte b = m_InBitStream.DirectReadByte();
+      levels[i] = b & 0xF;
+      levels[i + 1] = b >> 4;
+    }
+    if (!m_MainDecoder.SetCodeLengths(levels))
+      return S_FALSE;
+  }
+
+  while (outSize > 0)
+  {
+    UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
+    if (number < 256)
+    {
+      m_OutWindowStream.PutByte((Byte)number);
+      outSize--;
+    }
+    else
+    {
+      if (number >= kMainTableSize)
+        return S_FALSE;
+      UInt32 posLenSlot = number - 256;
+      UInt32 posSlot = posLenSlot / kNumLenSlots;
+      UInt32 len = posLenSlot % kNumLenSlots;
+      UInt32 distance = (1 << posSlot) - 1 + m_InBitStream.ReadBits(posSlot);
+      
+      if (len == kNumLenSlots - 1)
+      {
+        len = m_InBitStream.DirectReadByte();
+        if (len == 0xFF)
+        {
+          len = m_InBitStream.DirectReadByte();
+          len |= (UInt32)m_InBitStream.DirectReadByte() << 8;
+        }
+        else
+          len += kNumLenSlots - 1;
+      }
+      
+      len += kMatchMinLen;
+      UInt32 locLen = (len <= outSize ? len : outSize);
+
+      if (!m_OutWindowStream.CopyBlock(distance, locLen))
+        return S_FALSE;
+      
+      len -= locLen;
+      outSize -= locLen;
+      if (len != 0)
+        return S_FALSE;
+    }
+  }
+  return S_OK;
+}
+
+const UInt32 kDictSize = (1 << kNumPosSlots);
+
+HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt32 outSize)
+{
+  if (!m_OutWindowStream.Create(kDictSize) || !m_InBitStream.Create(1 << 16))
+    return E_OUTOFMEMORY;
+
+  CDecoderFlusher flusher(this);
+
+  m_InBitStream.SetStream(inStream);
+  m_OutWindowStream.SetStream(outStream);
+  m_InBitStream.Init();
+  m_OutWindowStream.Init(false);
+
+  RINOK(CodeSpec(outSize));
+
+  flusher.NeedFlush = false;
+  return Flush();
+}
+
+HRESULT CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt32 outSize)
+{
+  try { return CodeReal(inStream, outStream, outSize); }
+  catch(const CInBufferException &e) { return e.ErrorCode; } \
+  catch(const CLzOutWindowException &e) { return e.ErrorCode; }
+  catch(...) { return S_FALSE; }
+}
+
+}
+
+HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource, bool lzxMode,
+    ISequentialOutStream *outStream, ICompressProgressInfo *progress)
+{
+  RINOK(inStream->Seek(resource.Offset, STREAM_SEEK_SET, NULL));
+
+  CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream();
+  CMyComPtr<ISequentialInStream> limitedStream = limitedStreamSpec;
+  limitedStreamSpec->SetStream(inStream);
+
+  if (!copyCoder)
+  {
+    copyCoderSpec = new NCompress::CCopyCoder;
+    copyCoder = copyCoderSpec;
+  }
+  if (!resource.IsCompressed())
+  {
+    if (resource.PackSize != resource.UnpackSize)
+      return S_FALSE;
+    limitedStreamSpec->Init(resource.PackSize);
+    return copyCoder->Code(limitedStreamSpec, outStream, NULL, NULL, progress);
+  }
+  if (resource.UnpackSize == 0)
+    return S_OK;
+  UInt64 numChunks = (resource.UnpackSize + kChunkSize - 1) >> kChunkSizeBits;
+  unsigned entrySize = ((resource.UnpackSize > (UInt64)1 << 32) ? 8 : 4);
+  UInt64 sizesBufSize64 = entrySize * (numChunks - 1);
+  size_t sizesBufSize = (size_t)sizesBufSize64;
+  if (sizesBufSize != sizesBufSize64)
+    return E_OUTOFMEMORY;
+  if (sizesBufSize > sizesBuf.GetCapacity())
+  {
+    sizesBuf.Free();
+    sizesBuf.SetCapacity(sizesBufSize);
+  }
+  RINOK(ReadStream_FALSE(inStream, (Byte *)sizesBuf, sizesBufSize));
+  const Byte *p = (const Byte *)sizesBuf;
+  
+  if (lzxMode && !lzxDecoder)
+  {
+    lzxDecoderSpec = new NCompress::NLzx::CDecoder(true);
+    lzxDecoder = lzxDecoderSpec;
+    RINOK(lzxDecoderSpec->SetParams(kChunkSizeBits));
+  }
+  
+  UInt64 baseOffset = resource.Offset + sizesBufSize64;
+  UInt64 outProcessed = 0;
+  for (UInt32 i = 0; i < (UInt32)numChunks; i++)
+  {
+    UInt64 offset = 0;
+    if (i > 0)
+    {
+      offset = (entrySize == 4) ? Get32(p): Get64(p);
+      p += entrySize;
+    }
+    UInt64 nextOffset = resource.PackSize - sizesBufSize64;
+    if (i + 1 < (UInt32)numChunks)
+      nextOffset = (entrySize == 4) ? Get32(p): Get64(p);
+    if (nextOffset < offset)
+      return S_FALSE;
+
+    RINOK(inStream->Seek(baseOffset + offset, STREAM_SEEK_SET, NULL));
+    UInt64 inSize = nextOffset - offset;
+    limitedStreamSpec->Init(inSize);
+
+    if (progress)
+    {
+      RINOK(progress->SetRatioInfo(&offset, &outProcessed));
+    }
+    
+    UInt32 outSize = kChunkSize;
+    if (outProcessed + outSize > resource.UnpackSize)
+      outSize = (UInt32)(resource.UnpackSize - outProcessed);
+    UInt64 outSize64 = outSize;
+    if (inSize == outSize)
+    {
+      RINOK(copyCoder->Code(limitedStreamSpec, outStream, NULL, &outSize64, NULL));
+    }
+    else
+    {
+      if (lzxMode)
+      {
+        lzxDecoderSpec->SetKeepHistory(false);
+        RINOK(lzxDecoder->Code(limitedStreamSpec, outStream, NULL, &outSize64, NULL));
+      }
+      else
+      {
+        RINOK(xpressDecoder.Code(limitedStreamSpec, outStream, outSize));
+      }
+    }
+    outProcessed += outSize;
+  }
+  return S_OK;
+}
+
+HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource, bool lzxMode,
+    ISequentialOutStream *outStream, ICompressProgressInfo *progress, Byte *digest)
+{
+  COutStreamWithSha1 *shaStreamSpec = new COutStreamWithSha1();
+  CMyComPtr<ISequentialOutStream> shaStream = shaStreamSpec;
+  shaStreamSpec->SetStream(outStream);
+  shaStreamSpec->Init(digest != NULL);
+  HRESULT result = Unpack(inStream, resource, lzxMode, shaStream, progress);
+  if (digest)
+    shaStreamSpec->Final(digest);
+  return result;
+}
+
+static HRESULT UnpackData(IInStream *inStream, const CResource &resource, bool lzxMode, CByteBuffer &buf, Byte *digest)
+{
+  size_t size = (size_t)resource.UnpackSize;
+  if (size != resource.UnpackSize)
+    return E_OUTOFMEMORY;
+  buf.Free();
+  buf.SetCapacity(size);
+
+  CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream();
+  CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
+  outStreamSpec->Init((Byte *)buf, size);
+
+  CUnpacker unpacker;
+  return unpacker.Unpack(inStream, resource, lzxMode, outStream, NULL, digest);
+}
+
+void CResource::Parse(const Byte *p)
+{
+  Flags = p[7];
+  PackSize = Get64(p) & (((UInt64)1 << 56) - 1);
+  Offset = Get64(p + 8);
+  UnpackSize = Get64(p + 16);
+}
+
+#define GetResource(p, res) res.Parse(p)
+
+static void GetStream(bool oldVersion, const Byte *p, CStreamInfo &s)
+{
+  s.Resource.Parse(p);
+  if (oldVersion)
+  {
+    s.PartNumber = 1;
+    s.Id = Get32(p + 24);
+    s.RefCount = Get32(p + 28);
+    memcpy(s.Hash, p + 32, kHashSize);
+  }
+  else
+  {
+    s.PartNumber = Get16(p + 24);
+    s.RefCount = Get32(p + 26);
+    memcpy(s.Hash, p + 30, kHashSize);
+  }
+}
+
+static const wchar_t *kLongPath = L"[LongPath]";
+
+UString CDatabase::GetItemPath(const int index1) const
+{
+  int size = 0;
+  int index = index1;
+  int newLevel;
+  for (newLevel = 0;; newLevel = 1)
+  {
+    const CItem &item = Items[index];
+    index = item.Parent;
+    if (index >= 0 || !SkipRoot)
+      size += item.Name.Length() + newLevel;
+    if (index < 0)
+      break;
+    if ((UInt32)size >= ((UInt32)1 << 16))
+      return kLongPath;
+  }
+
+  wchar_t temp[16];
+  int imageLen = 0;
+  if (ShowImageNumber)
+  {
+    ConvertUInt32ToString(-1 - index, temp);
+    imageLen = MyStringLen(temp);
+    size += imageLen + 1;
+  }
+  if ((UInt32)size >= ((UInt32)1 << 16))
+    return kLongPath;
+  
+  UString path;
+  wchar_t *s = path.GetBuffer(size);
+  s[size] = 0;
+  if (ShowImageNumber)
+  {
+    memcpy(s, temp, imageLen * sizeof(wchar_t));
+    s[imageLen] = WCHAR_PATH_SEPARATOR;
+  }
+
+  index = index1;
+  
+  for (newLevel = 0;; newLevel = 1)
+  {
+    const CItem &item = Items[index];
+    index = item.Parent;
+    if (index >= 0 || !SkipRoot)
+    {
+      if (newLevel)
+        s[--size] = WCHAR_PATH_SEPARATOR;
+      size -= item.Name.Length();
+      memcpy(s + size, item.Name, sizeof(wchar_t) * item.Name.Length());
+    }
+    if (index < 0)
+    {
+      path.ReleaseBuffer();
+      return path;
+    }
+  }
+}
+
+static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)
+{
+  ft->dwLowDateTime = Get32(p);
+  ft->dwHighDateTime = Get32(p + 4);
+}
+
+static HRESULT ReadName(const Byte *p, int size, UString &dest)
+{
+  if (size == 0)
+    return S_OK;
+  if (Get16(p + size) != 0)
+    return S_FALSE;
+  wchar_t *s = dest.GetBuffer(size / 2);
+  for (int i = 0; i <= size; i += 2)
+    *s++ = Get16(p + i);
+  dest.ReleaseBuffer();
+  return S_OK;
+}
+
+HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
+{
+  if ((pos & 7) != 0)
+    return S_FALSE;
+  
+  int prevIndex = -1;
+  for (int numItems = 0;; numItems++)
+  {
+    if (OpenCallback)
+    {
+      UInt64 numFiles = Items.Size();
+      if ((numFiles & 0x3FF) == 0)
+      {
+        RINOK(OpenCallback->SetCompleted(&numFiles, NULL));
+      }
+    }
+    size_t rem = DirSize - pos;
+    if (pos < DirStartOffset || pos > DirSize || rem < 8)
+      return S_FALSE;
+    const Byte *p = DirData + pos;
+    UInt64 len = Get64(p);
+    if (len == 0)
+    {
+      if (parent < 0 && numItems != 1)
+        SkipRoot = false;
+      DirProcessed += 8;
+      return S_OK;
+    }
+    if ((len & 7) != 0 || rem < len)
+      return S_FALSE;
+    if (!IsOldVersion)
+      if (len < 0x28)
+        return S_FALSE;
+    DirProcessed += (size_t)len;
+    if (DirProcessed > DirSize)
+      return S_FALSE;
+    int extraOffset = 0;
+    if (IsOldVersion)
+    {
+      if (len < 0x40 || (/* Get32(p + 12) == 0 && */ Get32(p + 0x14) != 0))
+      {
+        extraOffset = 0x10;
+      }
+    }
+    else if (Get64(p + 8) == 0)
+      extraOffset = 0x24;
+    if (extraOffset)
+    {
+      if (prevIndex == -1)
+        return S_FALSE;
+      UInt32 fileNameLen = Get16(p + extraOffset);
+      if ((fileNameLen & 1) != 0)
+        return S_FALSE;
+      /* Probably different versions of ImageX can use different number of
+         additional ZEROs. So we don't use exact check. */
+      UInt32 fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);
+      if (((extraOffset + 2 + fileNameLen2 + 6) & ~7) > len)
+        return S_FALSE;
+      
+      UString name;
+      RINOK(ReadName(p + extraOffset + 2, fileNameLen, name));
+
+      CItem &prevItem = Items[prevIndex];
+      if (name.IsEmpty() && !prevItem.HasStream())
+      {
+        if (IsOldVersion)
+          prevItem.Id = Get32(p + 8);
+        else
+          memcpy(prevItem.Hash, p + 0x10, kHashSize);
+      }
+      else
+      {
+        CItem item;
+        item.Name = prevItem.Name + L':' + name;
+        item.CTime = prevItem.CTime;
+        item.ATime = prevItem.ATime;
+        item.MTime = prevItem.MTime;
+        if (IsOldVersion)
+        {
+          item.Id = Get32(p + 8);
+          memset(item.Hash, 0, kHashSize);
+        }
+        else
+          memcpy(item.Hash, p + 0x10, kHashSize);
+        item.Attrib = 0;
+        item.Order = Order++;
+        item.Parent = parent;
+        Items.Add(item);
+      }
+      pos += (size_t)len;
+      continue;
+    }
+
+    UInt32 dirRecordSize = IsOldVersion ? kDirRecordSizeOld : kDirRecordSize;
+    if (len < dirRecordSize)
+      return S_FALSE;
+
+    CItem item;
+    item.Attrib = Get32(p + 8);
+    // item.SecurityId = Get32(p + 0xC);
+    UInt64 subdirOffset = Get64(p + 0x10);
+    UInt32 timeOffset = IsOldVersion ? 0x18: 0x28;
+    GetFileTimeFromMem(p + timeOffset,      &item.CTime);
+    GetFileTimeFromMem(p + timeOffset + 8,  &item.ATime);
+    GetFileTimeFromMem(p + timeOffset + 16, &item.MTime);
+    if (IsOldVersion)
+    {
+      item.Id = Get32(p + 0x10);
+      memset(item.Hash, 0, kHashSize);
+    }
+    else
+    {
+      memcpy(item.Hash, p + 0x40, kHashSize);
+    }
+    // UInt32 numStreams = Get16(p + dirRecordSize - 6);
+    UInt32 shortNameLen = Get16(p + dirRecordSize - 4);
+    UInt32 fileNameLen = Get16(p + dirRecordSize - 2);
+
+    if ((shortNameLen & 1) != 0 || (fileNameLen & 1) != 0)
+      return S_FALSE;
+
+    UInt32 shortNameLen2 = (shortNameLen == 0 ? shortNameLen : shortNameLen + 2);
+    UInt32 fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);
+
+    if (((dirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7) > len)
+      return S_FALSE;
+    p += dirRecordSize;
+    
+    RINOK(ReadName(p, fileNameLen, item.Name));
+    RINOK(ReadName(p + fileNameLen2, shortNameLen, item.ShortName));
+
+    if (parent < 0 && (shortNameLen || fileNameLen || !item.IsDir()))
+      SkipRoot = false;
+
+    /*
+    // there are some extra data for some files.
+    p -= dirRecordSize;
+    p += ((dirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7);
+    if (((dirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7) != len)
+      p = p;
+    */
+
+    /*
+    if (parent >= 0)
+    {
+      UString s = GetItemPath(parent) + L"\\" + item.Name;
+      printf("\n%s %8x %S", item.IsDir() ? "D" : " ", (int)subdirOffset, (const wchar_t *)s);
+    }
+    */
+
+    if (fileNameLen == 0 && item.IsDir() && !item.HasStream())
+      item.Attrib = 0x10; // some swm archives have system/hidden attributes for root
+
+    item.Parent = parent;
+    prevIndex = Items.Add(item);
+    if (item.IsDir() && subdirOffset != 0)
+    {
+      RINOK(ParseDirItem((size_t)subdirOffset, prevIndex));
+    }
+    Items[prevIndex].Order = Order++;
+    pos += (size_t)len;
+  }
+}
+
+HRESULT CDatabase::ParseImageDirs(const CByteBuffer &buf, int parent)
+{
+  DirData = buf;
+  DirSize = buf.GetCapacity();
+
+  size_t pos = 0;
+  if (DirSize < 8)
+    return S_FALSE;
+  const Byte *p = DirData;
+  UInt32 totalLength = Get32(p);
+  if (IsOldVersion)
+  {
+    for (pos = 4;; pos += 8)
+    {
+      if (pos + 4 > DirSize)
+        return S_FALSE;
+      UInt32 n = Get32(p + pos);
+      if (n == 0)
+        break;
+      if (pos + 8 > DirSize)
+        return S_FALSE;
+      totalLength += Get32(p + pos + 4);
+      if (totalLength > DirSize)
+        return S_FALSE;
+    }
+    pos += totalLength + 4;
+    pos = (pos + 7) & ~(size_t)7;
+    if (pos > DirSize)
+      return S_FALSE;
+  }
+  else
+  {
+
+  // UInt32 numEntries = Get32(p + 4);
+  pos += 8;
+  {
+    /*
+    CRecordVector<UInt64> entryLens;
+    UInt64 sum = 0;
+    for (UInt32 i = 0; i < numEntries; i++)
+    {
+      if (pos + 8 > DirSize)
+        return S_FALSE;
+      UInt64 len = Get64(p + pos);
+      entryLens.Add(len);
+      sum += len;
+      pos += 8;
+    }
+    pos += (size_t)sum; // skip security descriptors
+    while ((pos & 7) != 0)
+      pos++;
+    if (pos != totalLength)
+      return S_FALSE;
+    */
+    if (totalLength == 0)
+      pos = 8;
+    else if (totalLength < 8)
+      return S_FALSE;
+    else
+      pos = totalLength;
+  }
+  }
+  DirStartOffset = DirProcessed = pos;
+  RINOK(ParseDirItem(pos, parent));
+  if (DirProcessed == DirSize)
+    return S_OK;
+  /* Original program writes additional 8 bytes (END_OF_ROOT_FOLDER), but
+     reference to that folder is empty */
+  if (DirProcessed == DirSize - 8 && DirProcessed - DirStartOffset == 112 &&
+      Get64(p + DirSize - 8) == 0)
+    return S_OK;
+  return S_FALSE;
+}
+
+HRESULT CHeader::Parse(const Byte *p)
+{
+  UInt32 headerSize = Get32(p + 8);
+  Version = Get32(p + 0x0C);
+  Flags = Get32(p + 0x10);
+  if (!IsSupported())
+    return S_FALSE;
+  ChunkSize = Get32(p + 0x14);
+  if (ChunkSize != kChunkSize && ChunkSize != 0)
+    return S_FALSE;
+  int offset;
+  if (IsOldVersion())
+  {
+    if (headerSize != 0x60)
+      return S_FALSE;
+    memset(Guid, 0, 16);
+    offset = 0x18;
+    PartNumber = 1;
+    NumParts = 1;
+  }
+  else
+  {
+    if (headerSize < 0x74)
+      return S_FALSE;
+    memcpy(Guid, p + 0x18, 16);
+    PartNumber = Get16(p + 0x28);
+    NumParts = Get16(p + 0x2A);
+    offset = 0x2C;
+    if (IsNewVersion())
+    {
+      NumImages = Get32(p + offset);
+      offset += 4;
+    }
+  }
+  GetResource(p + offset, OffsetResource);
+  GetResource(p + offset + 0x18, XmlResource);
+  GetResource(p + offset + 0x30, MetadataResource);
+  if (IsNewVersion())
+  {
+    if (headerSize < 0xD0)
+      return S_FALSE;
+    BootIndex = Get32(p + 0x48);
+    IntegrityResource.Parse(p + offset + 0x4C);
+  }
+  return S_OK;
+}
+
+const Byte kSignature[kSignatureSize] = { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 };
+
+HRESULT ReadHeader(IInStream *inStream, CHeader &h)
+{
+  Byte p[kHeaderSizeMax];
+  RINOK(ReadStream_FALSE(inStream, p, kHeaderSizeMax));
+  if (memcmp(p, kSignature, kSignatureSize) != 0)
+    return S_FALSE;
+  return h.Parse(p);
+}
+
+static HRESULT ReadStreams(bool oldVersion, IInStream *inStream, const CHeader &h, CDatabase &db)
+{
+  CByteBuffer offsetBuf;
+  RINOK(UnpackData(inStream, h.OffsetResource, h.IsLzxMode(), offsetBuf, NULL));
+  size_t i;
+  size_t streamInfoSize = oldVersion ? kStreamInfoSize + 2 : kStreamInfoSize;
+  for (i = 0; offsetBuf.GetCapacity() - i >= streamInfoSize; i += streamInfoSize)
+  {
+    CStreamInfo s;
+    GetStream(oldVersion, (const Byte *)offsetBuf + i, s);
+    if (s.PartNumber == h.PartNumber)
+      db.Streams.Add(s);
+  }
+  return (i == offsetBuf.GetCapacity()) ? S_OK : S_FALSE;
+}
+
+static bool IsEmptySha(const Byte *data)
+{
+  for (int i = 0; i < kHashSize; i++)
+    if (data[i] != 0)
+      return false;
+  return true;
+}
+
+HRESULT CDatabase::Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml, IArchiveOpenCallback *openCallback)
+{
+  OpenCallback = openCallback;
+  IsOldVersion = h.IsOldVersion();
+  RINOK(UnpackData(inStream, h.XmlResource, h.IsLzxMode(), xml, NULL));
+  RINOK(ReadStreams(h.IsOldVersion(), inStream, h, *this));
+  bool needBootMetadata = !h.MetadataResource.IsEmpty();
+  Order = 0;
+  if (h.PartNumber == 1)
+  {
+    int imageIndex = 1;
+    for (int i = 0; i < Streams.Size(); i++)
+    {
+      // if (imageIndex > 1) break;
+      const CStreamInfo &si = Streams[i];
+      if (!si.Resource.IsMetadata() || si.PartNumber != h.PartNumber)
+        continue;
+      Byte hash[kHashSize];
+      CByteBuffer metadata;
+      RINOK(UnpackData(inStream, si.Resource, h.IsLzxMode(), metadata, hash));
+      if (memcmp(hash, si.Hash, kHashSize) != 0 &&
+          !(h.IsOldVersion() && IsEmptySha(si.Hash)))
+        return S_FALSE;
+      NumImages++;
+      RINOK(ParseImageDirs(metadata, -(int)(++imageIndex)));
+      if (needBootMetadata)
+        if (h.MetadataResource.Offset == si.Resource.Offset)
+          needBootMetadata = false;
+    }
+  }
+  
+  if (needBootMetadata)
+  {
+    CByteBuffer metadata;
+    RINOK(UnpackData(inStream, h.MetadataResource, h.IsLzxMode(), metadata, NULL));
+    RINOK(ParseImageDirs(metadata, -1));
+    NumImages++;
+  }
+  return S_OK;
+}
+
+
+static int CompareStreamsByPos(const CStreamInfo *p1, const CStreamInfo *p2, void * /* param */)
+{
+  int res = MyCompare(p1->PartNumber, p2->PartNumber);
+  if (res != 0)
+    return res;
+  return MyCompare(p1->Resource.Offset, p2->Resource.Offset);
+}
+
+static int CompareIDs(const int *p1, const int *p2, void *param)
+{
+  const CRecordVector<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param;
+  return MyCompare(streams[*p1].Id, streams[*p2].Id);
+}
+
+static int CompareHashRefs(const int *p1, const int *p2, void *param)
+{
+  const CRecordVector<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param;
+  return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize);
+}
+
+static int FindId(const CRecordVector<CStreamInfo> &streams,
+    const CIntVector &sortedByHash, UInt32 id)
+{
+  int left = 0, right = streams.Size();
+  while (left != right)
+  {
+    int mid = (left + right) / 2;
+    int streamIndex = sortedByHash[mid];
+    UInt32 id2 = streams[streamIndex].Id;
+    if (id == id2)
+      return streamIndex;
+    if (id < id2)
+      right = mid;
+    else
+      left = mid + 1;
+  }
+  return -1;
+}
+
+static int FindHash(const CRecordVector<CStreamInfo> &streams,
+    const CIntVector &sortedByHash, const Byte *hash)
+{
+  int left = 0, right = streams.Size();
+  while (left != right)
+  {
+    int mid = (left + right) / 2;
+    int streamIndex = sortedByHash[mid];
+    UInt32 i;
+    const Byte *hash2 = streams[streamIndex].Hash;
+    for (i = 0; i < kHashSize; i++)
+      if (hash[i] != hash2[i])
+        break;
+    if (i == kHashSize)
+      return streamIndex;
+    if (hash[i] < hash2[i])
+      right = mid;
+    else
+      left = mid + 1;
+  }
+  return -1;
+}
+
+static int CompareItems(const int *a1, const int *a2, void *param)
+{
+  const CObjectVector<CItem> &items = ((CDatabase *)param)->Items;
+  const CItem &i1 = items[*a1];
+  const CItem &i2 = items[*a2];
+
+  if (i1.IsDir() != i2.IsDir())
+    return i1.IsDir() ? 1 : -1;
+  int res = MyCompare(i1.StreamIndex, i2.StreamIndex);
+  if (res != 0)
+    return res;
+  return MyCompare(i1.Order, i2.Order);
+}
+
+HRESULT CDatabase::Sort(bool skipRootDir)
+{
+  Streams.Sort(CompareStreamsByPos, NULL);
+
+  {
+    CIntVector sortedByHash;
+    {
+      for (int i = 0; i < Streams.Size(); i++)
+        sortedByHash.Add(i);
+      if (IsOldVersion)
+        sortedByHash.Sort(CompareIDs, &Streams);
+      else
+        sortedByHash.Sort(CompareHashRefs, &Streams);
+    }
+    
+    for (int i = 0; i < Items.Size(); i++)
+    {
+      CItem &item = Items[i];
+      item.StreamIndex = -1;
+      if (item.HasStream())
+        if (IsOldVersion)
+          item.StreamIndex = FindId(Streams, sortedByHash, item.Id);
+        else
+          item.StreamIndex = FindHash(Streams, sortedByHash, item.Hash);
+    }
+  }
+
+  {
+    CRecordVector<bool> used;
+    int i;
+    for (i = 0; i < Streams.Size(); i++)
+    {
+      const CStreamInfo &s = Streams[i];
+      used.Add(s.Resource.IsMetadata() && s.PartNumber == 1);
+      // used.Add(false);
+    }
+    for (i = 0; i < Items.Size(); i++)
+    {
+      CItem &item = Items[i];
+      if (item.StreamIndex >= 0)
+        used[item.StreamIndex] = true;
+    }
+    for (i = 0; i < Streams.Size(); i++)
+      if (!used[i])
+      {
+        CItem item;
+        item.StreamIndex = i;
+        item.HasMetadata = false;
+        Items.Add(item);
+      }
+  }
+
+  SortedItems.Reserve(Items.Size());
+  for (int i = (skipRootDir ? 1 : 0); i < Items.Size(); i++)
+    SortedItems.Add(i);
+  SortedItems.Sort(CompareItems, this);
+  return S_OK;
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimIn.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimIn.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimIn.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimIn.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,297 @@
+// Archive/WimIn.h
+
+#ifndef __ARCHIVE_WIM_IN_H
+#define __ARCHIVE_WIM_IN_H
+
+#include "Common/Buffer.h"
+#include "Common/MyString.h"
+
+#include "../../Compress/CopyCoder.h"
+#include "../../Compress/LzxDecoder.h"
+
+#include "../IArchive.h"
+
+namespace NArchive {
+namespace NWim {
+
+namespace NXpress {
+
+class CBitStream
+{
+  CInBuffer m_Stream;
+  UInt32 m_Value;
+  unsigned m_BitPos;
+public:
+  bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }
+  void SetStream(ISequentialInStream *s) { m_Stream.SetStream(s); }
+  void ReleaseStream() { m_Stream.ReleaseStream(); }
+
+  void Init() { m_Stream.Init(); m_BitPos = 0; }
+  // UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() - m_BitPos / 8; }
+  Byte DirectReadByte() { return m_Stream.ReadByte(); }
+
+  void Normalize()
+  {
+    if (m_BitPos < 16)
+    {
+      Byte b0 = m_Stream.ReadByte();
+      Byte b1 = m_Stream.ReadByte();
+      m_Value = (m_Value << 8) | b1;
+      m_Value = (m_Value << 8) | b0;
+      m_BitPos += 16;
+    }
+  }
+
+  UInt32 GetValue(unsigned numBits)
+  {
+    Normalize();
+    return (m_Value >> (m_BitPos - numBits)) & ((1 << numBits) - 1);
+  }
+  
+  void MovePos(unsigned numBits) { m_BitPos -= numBits; }
+  
+  UInt32 ReadBits(unsigned numBits)
+  {
+    UInt32 res = GetValue(numBits);
+    m_BitPos -= numBits;
+    return res;
+  }
+};
+
+const unsigned kNumHuffmanBits = 16;
+const UInt32 kMatchMinLen = 3;
+const UInt32 kNumLenSlots = 16;
+const UInt32 kNumPosSlots = 16;
+const UInt32 kNumPosLenSlots = kNumPosSlots * kNumLenSlots;
+const UInt32 kMainTableSize = 256 + kNumPosLenSlots;
+
+class CDecoder
+{
+  CBitStream m_InBitStream;
+  CLzOutWindow m_OutWindowStream;
+  NCompress::NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder;
+
+  HRESULT CodeSpec(UInt32 size);
+  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt32 outSize);
+public:
+  void ReleaseStreams()
+  {
+    m_OutWindowStream.ReleaseStream();
+    m_InBitStream.ReleaseStream();
+  }
+  HRESULT Flush() { return m_OutWindowStream.Flush(); }
+  HRESULT Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt32 outSize);
+};
+
+}
+
+namespace NResourceFlags
+{
+  const Byte kFree = 1;
+  const Byte kMetadata = 2;
+  const Byte Compressed = 4;
+  const Byte Spanned = 4;
+}
+
+struct CResource
+{
+  UInt64 PackSize;
+  UInt64 Offset;
+  UInt64 UnpackSize;
+  Byte Flags;
+
+  void Clear()
+  {
+    PackSize = 0;
+    Offset = 0;
+    UnpackSize = 0;
+    Flags = 0;
+  }
+  void Parse(const Byte *p);
+  void WriteTo(Byte *p) const;
+  bool IsFree() const { return (Flags & NResourceFlags::kFree) != 0; }
+  bool IsMetadata() const { return (Flags & NResourceFlags::kMetadata) != 0; }
+  bool IsCompressed() const { return (Flags & NResourceFlags::Compressed) != 0; }
+  bool IsEmpty() const { return (UnpackSize == 0); }
+};
+
+namespace NHeaderFlags
+{
+  const UInt32 kCompression = 2;
+  const UInt32 kSpanned = 8;
+  const UInt32 kRpFix = 0x80;
+  const UInt32 kXPRESS = 0x20000;
+  const UInt32 kLZX = 0x40000;
+}
+
+const UInt32 kWimVersion = 0x010D00;
+const UInt32 kHeaderSizeMax = 0xD0;
+const UInt32 kSignatureSize = 8;
+extern const Byte kSignature[kSignatureSize];
+const unsigned kChunkSizeBits = 15;
+const UInt32 kChunkSize = (1 << kChunkSizeBits);
+
+struct CHeader
+{
+  UInt32 Version;
+  UInt32 Flags;
+  UInt32 ChunkSize;
+  Byte Guid[16];
+  UInt16 PartNumber;
+  UInt16 NumParts;
+  UInt32 NumImages;
+  
+  CResource OffsetResource;
+  CResource XmlResource;
+  CResource MetadataResource;
+  CResource IntegrityResource;
+  UInt32 BootIndex;
+
+  void SetDefaultFields(bool useLZX);
+
+  void WriteTo(Byte *p) const;
+  HRESULT Parse(const Byte *p);
+  bool IsCompressed() const { return (Flags & NHeaderFlags::kCompression) != 0; }
+  bool IsSupported() const { return (!IsCompressed() || (Flags & NHeaderFlags::kLZX) != 0 || (Flags & NHeaderFlags::kXPRESS) != 0 ) ; }
+  bool IsLzxMode() const { return (Flags & NHeaderFlags::kLZX) != 0; }
+  bool IsSpanned() const { return (!IsCompressed() || (Flags & NHeaderFlags::kSpanned) != 0); }
+  bool IsOldVersion() const { return (Version <= 0x010A00); }
+  bool IsNewVersion() const { return (Version > 0x010C00); }
+
+  bool AreFromOnArchive(const CHeader &h)
+  {
+    return (memcmp(Guid, h.Guid, sizeof(Guid)) == 0) && (h.NumParts == NumParts);
+  }
+};
+
+const UInt32 kHashSize = 20;
+const UInt32 kStreamInfoSize = 24 + 2 + 4 + kHashSize;
+
+struct CStreamInfo
+{
+  CResource Resource;
+  UInt16 PartNumber;
+  UInt32 RefCount;
+  UInt32 Id;
+  BYTE Hash[kHashSize];
+
+  void WriteTo(Byte *p) const;
+};
+
+const UInt32 kDirRecordSizeOld = 62;
+const UInt32 kDirRecordSize = 102;
+
+struct CItem
+{
+  UString Name;
+  UString ShortName;
+  UInt32 Attrib;
+  // UInt32 SecurityId;
+  BYTE Hash[kHashSize];
+  UInt32 Id;
+  FILETIME CTime;
+  FILETIME ATime;
+  FILETIME MTime;
+  // UInt32 ReparseTag;
+  // UInt64 HardLink;
+  // UInt16 NumStreams;
+  int StreamIndex;
+  int Parent;
+  unsigned Order;
+  bool HasMetadata;
+  CItem(): HasMetadata(true), StreamIndex(-1), Id(0) {}
+  bool IsDir() const { return HasMetadata && ((Attrib & 0x10) != 0); }
+  bool HasStream() const
+  {
+    for (unsigned i = 0; i < kHashSize; i++)
+      if (Hash[i] != 0)
+        return true;
+    return Id != 0;
+  }
+};
+
+class CDatabase
+{
+  const Byte *DirData;
+  size_t DirSize;
+  size_t DirProcessed;
+  size_t DirStartOffset;
+  int Order;
+  IArchiveOpenCallback *OpenCallback;
+  
+  HRESULT ParseDirItem(size_t pos, int parent);
+  HRESULT ParseImageDirs(const CByteBuffer &buf, int parent);
+
+public:
+  CRecordVector<CStreamInfo> Streams;
+  CObjectVector<CItem> Items;
+  CIntVector SortedItems;
+  int NumImages;
+  bool SkipRoot;
+  bool ShowImageNumber;
+
+  bool IsOldVersion;
+
+  UInt64 GetUnpackSize() const
+  {
+    UInt64 res = 0;
+    for (int i = 0; i < Streams.Size(); i++)
+      res += Streams[i].Resource.UnpackSize;
+    return res;
+  }
+
+  UInt64 GetPackSize() const
+  {
+    UInt64 res = 0;
+    for (int i = 0; i < Streams.Size(); i++)
+      res += Streams[i].Resource.PackSize;
+    return res;
+  }
+
+  void Clear()
+  {
+    Streams.Clear();
+    Items.Clear();
+    SortedItems.Clear();
+    NumImages = 0;
+
+    SkipRoot = true;
+    ShowImageNumber = true;
+    IsOldVersion = false;
+  }
+
+  UString GetItemPath(int index) const;
+
+  HRESULT Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml, IArchiveOpenCallback *openCallback);
+
+  void DetectPathMode()
+  {
+    ShowImageNumber = (NumImages != 1);
+  }
+
+  HRESULT Sort(bool skipRootDir);
+};
+
+HRESULT ReadHeader(IInStream *inStream, CHeader &header);
+
+class CUnpacker
+{
+  NCompress::CCopyCoder *copyCoderSpec;
+  CMyComPtr<ICompressCoder> copyCoder;
+
+  NCompress::NLzx::CDecoder *lzxDecoderSpec;
+  CMyComPtr<ICompressCoder> lzxDecoder;
+
+  NXpress::CDecoder xpressDecoder;
+
+  CByteBuffer sizesBuf;
+  HRESULT Unpack(IInStream *inStream, const CResource &res, bool lzxMode,
+      ISequentialOutStream *outStream, ICompressProgressInfo *progress);
+public:
+  HRESULT Unpack(IInStream *inStream, const CResource &res, bool lzxMode,
+      ISequentialOutStream *outStream, ICompressProgressInfo *progress, Byte *digest);
+};
+
+}}
+  
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimRegister.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimRegister.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimRegister.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Wim/WimRegister.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,18 @@
+// WimRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterArc.h"
+
+#include "WimHandler.h"
+static IInArchive *CreateArc() { return new NArchive::NWim::CHandler; }
+#ifndef EXTRACT_ONLY
+static IOutArchive *CreateArcOut() { return new NArchive::NWim::COutHandler; }
+#else
+#define CreateArcOut 0
+#endif
+
+static CArcInfo g_ArcInfo =
+  { L"wim", L"wim swm", 0, 0xE6, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 }, 8, false, CreateArc, CreateArcOut };
+
+REGISTER_ARC(Wim)

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/XarHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/XarHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/XarHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/XarHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,588 @@
+// XarHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/CpuArch.h"
+
+#include "Common/ComTry.h"
+#include "Common/MyXml.h"
+#include "Common/StringToInt.h"
+#include "Common/UTFConvert.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../Common/LimitedStreams.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamObjects.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/BZip2Decoder.h"
+#include "../Compress/CopyCoder.h"
+#include "../Compress/ZlibDecoder.h"
+
+#include "Common/OutStreamWithSha1.h"
+
+#define XAR_SHOW_RAW
+
+#define Get16(p) GetBe16(p)
+#define Get32(p) GetBe32(p)
+#define Get64(p) GetBe64(p)
+
+namespace NArchive {
+namespace NXar {
+
+struct CFile
+{
+  AString Name;
+  AString Method;
+  UInt64 Size;
+  UInt64 PackSize;
+  UInt64 Offset;
+  
+  // UInt32 mode;
+  UInt64 CTime;
+  UInt64 MTime;
+  UInt64 ATime;
+  
+  bool IsDir;
+  bool HasData;
+
+  bool Sha1IsDefined;
+  Byte Sha1[20];
+  // bool packSha1IsDefined;
+  // Byte packSha1[20];
+
+  int Parent;
+
+  CFile(): IsDir(false), HasData(false), Sha1IsDefined(false),
+    /* packSha1IsDefined(false), */
+    Parent(-1), Size(0), PackSize(0), CTime(0), MTime(0), ATime(0) {}
+};
+
+class CHandler:
+  public IInArchive,
+  public CMyUnknownImp
+{
+  UInt64 _dataStartPos;
+  CMyComPtr<IInStream> _inStream;
+  AString _xml;
+  CObjectVector<CFile> _files;
+
+  HRESULT Open2(IInStream *stream);
+  HRESULT Extract(IInStream *stream);
+public:
+  MY_UNKNOWN_IMP1(IInArchive)
+  INTERFACE_IInArchive(;)
+};
+
+const UInt32 kXmlSizeMax = ((UInt32)1 << 30) - (1 << 14);
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMTime, VT_FILETIME},
+  { NULL, kpidCTime, VT_FILETIME},
+  { NULL, kpidATime, VT_FILETIME},
+  { NULL, kpidMethod, VT_BSTR}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_NO
+
+static bool ParseNumber(const char *s, int size, UInt32 &res)
+{
+  const char *end;
+  res = (UInt32)ConvertStringToUInt64(s, &end);
+  return (end - s == size);
+}
+
+static bool ParseUInt64(const CXmlItem &item, const char *name, UInt64 &res)
+{
+  AString s = item.GetSubStringForTag(name);
+  const char *end;
+  res = ConvertStringToUInt64(s, &end);
+  return (end - (const char *)s == s.Length());
+}
+
+static UInt64 ParseTime(const CXmlItem &item, const char *name)
+{
+  AString s = item.GetSubStringForTag(name);
+  if (s.Length() < 20)
+    return 0;
+  const char *p = s;
+  if (p[ 4] != '-' || p[ 7] != '-' || p[10] != 'T' ||
+      p[13] != ':' || p[16] != ':' || p[19] != 'Z')
+    return 0;
+  UInt32 year, month, day, hour, min, sec;
+  if (!ParseNumber(p,      4, year )) return 0;
+  if (!ParseNumber(p + 5,  2, month)) return 0;
+  if (!ParseNumber(p + 8,  2, day  )) return 0;
+  if (!ParseNumber(p + 11, 2, hour )) return 0;
+  if (!ParseNumber(p + 14, 2, min  )) return 0;
+  if (!ParseNumber(p + 17, 2, sec  )) return 0;
+  
+  UInt64 numSecs;
+  if (!NWindows::NTime::GetSecondsSince1601(year, month, day, hour, min, sec, numSecs))
+    return 0;
+  return numSecs * 10000000;
+}
+
+static bool HexToByte(char c, Byte &res)
+{
+  if      (c >= '0' && c <= '9') res = c - '0';
+  else if (c >= 'A' && c <= 'F') res = c - 'A' + 10;
+  else if (c >= 'a' && c <= 'f') res = c - 'a' + 10;
+  else return false;
+  return true;
+}
+
+#define METHOD_NAME_ZLIB "zlib"
+
+static bool ParseSha1(const CXmlItem &item, const char *name, Byte *digest)
+{
+  int index = item.FindSubTag(name);
+  if (index  < 0)
+    return false;
+  const CXmlItem &checkItem = item.SubItems[index];
+  AString style = checkItem.GetPropertyValue("style");
+  if (style == "SHA1")
+  {
+    AString s = checkItem.GetSubString();
+    if (s.Length() != 40)
+      return false;
+    for (int i = 0; i < s.Length(); i += 2)
+    {
+      Byte b0, b1;
+      if (!HexToByte(s[i], b0) || !HexToByte(s[i + 1], b1))
+        return false;
+      digest[i / 2] = (b0 << 4) | b1;
+    }
+    return true;
+  }
+  return false;
+}
+
+static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int parent)
+{
+  if (!item.IsTag)
+    return true;
+  if (item.Name == "file")
+  {
+    CFile file;
+    file.Parent = parent;
+    parent = files.Size();
+    file.Name = item.GetSubStringForTag("name");
+    AString type = item.GetSubStringForTag("type");
+    if (type == "directory")
+      file.IsDir = true;
+    else if (type == "file")
+      file.IsDir = false;
+    else
+      return false;
+
+    int dataIndex = item.FindSubTag("data");
+    if (dataIndex >= 0 && !file.IsDir)
+    {
+      file.HasData = true;
+      const CXmlItem &dataItem = item.SubItems[dataIndex];
+      if (!ParseUInt64(dataItem, "size", file.Size))
+        return false;
+      if (!ParseUInt64(dataItem, "length", file.PackSize))
+        return false;
+      if (!ParseUInt64(dataItem, "offset", file.Offset))
+        return false;
+      file.Sha1IsDefined = ParseSha1(dataItem, "extracted-checksum", file.Sha1);
+      // file.packSha1IsDefined = ParseSha1(dataItem, "archived-checksum",  file.packSha1);
+      int encodingIndex = dataItem.FindSubTag("encoding");
+      if (encodingIndex >= 0)
+      {
+        const CXmlItem &encodingItem = dataItem.SubItems[encodingIndex];
+        if (encodingItem.IsTag)
+        {
+          AString s = encodingItem.GetPropertyValue("style");
+          if (s.Length() >= 0)
+          {
+            AString appl = "application/";
+            if (s.Left(appl.Length()) == appl)
+            {
+              s = s.Mid(appl.Length());
+              AString xx = "x-";
+              if (s.Left(xx.Length()) == xx)
+              {
+                s = s.Mid(xx.Length());
+                if (s == "gzip")
+                  s = METHOD_NAME_ZLIB;
+              }
+            }
+            file.Method = s;
+          }
+        }
+      }
+    }
+
+    file.CTime = ParseTime(item, "ctime");
+    file.MTime = ParseTime(item, "mtime");
+    file.ATime = ParseTime(item, "atime");
+    files.Add(file);
+  }
+  for (int i = 0; i < item.SubItems.Size(); i++)
+    if (!AddItem(item.SubItems[i], files, parent))
+      return false;
+  return true;
+}
+
+HRESULT CHandler::Open2(IInStream *stream)
+{
+  UInt64 archiveStartPos;
+  RINOK(stream->Seek(0, STREAM_SEEK_SET, &archiveStartPos));
+
+  const UInt32 kHeaderSize = 0x1C;
+  Byte buf[kHeaderSize];
+  RINOK(ReadStream_FALSE(stream, buf, kHeaderSize));
+
+  UInt32 size = Get16(buf + 4);
+  // UInt32 ver = Get16(buf + 6); // == 0
+  if (Get32(buf) != 0x78617221 || size != kHeaderSize)
+    return S_FALSE;
+
+  UInt64 packSize = Get64(buf + 8);
+  UInt64 unpackSize = Get64(buf + 0x10);
+  // UInt32 checkSumAlogo = Get32(buf + 0x18);
+
+  if (unpackSize >= kXmlSizeMax)
+    return S_FALSE;
+
+  _dataStartPos = archiveStartPos + kHeaderSize + packSize;
+
+  char *ss = _xml.GetBuffer((int)unpackSize + 1);
+
+  NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder();
+  CMyComPtr<ICompressCoder> zlibCoder = zlibCoderSpec;
+
+  CLimitedSequentialInStream *inStreamLimSpec = new CLimitedSequentialInStream;
+  CMyComPtr<ISequentialInStream> inStreamLim(inStreamLimSpec);
+  inStreamLimSpec->SetStream(stream);
+  inStreamLimSpec->Init(packSize);
+
+  CBufPtrSeqOutStream *outStreamLimSpec = new CBufPtrSeqOutStream;
+  CMyComPtr<ISequentialOutStream> outStreamLim(outStreamLimSpec);
+  outStreamLimSpec->Init((Byte *)ss, (size_t)unpackSize);
+
+  RINOK(zlibCoder->Code(inStreamLim, outStreamLim, NULL, NULL, NULL));
+
+  if (outStreamLimSpec->GetPos() != (size_t)unpackSize)
+    return S_FALSE;
+
+  ss[(size_t)unpackSize] = 0;
+  _xml.ReleaseBuffer();
+
+  CXml xml;
+  if (!xml.Parse(_xml))
+    return S_FALSE;
+  
+  if (!xml.Root.IsTagged("xar") || xml.Root.SubItems.Size() != 1)
+    return S_FALSE;
+  const CXmlItem &toc = xml.Root.SubItems[0];
+  if (!toc.IsTagged("toc"))
+    return S_FALSE;
+  if (!AddItem(toc, _files, -1))
+    return S_FALSE;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+    const UInt64 * /* maxCheckStartPosition */,
+    IArchiveOpenCallback * /* openArchiveCallback */)
+{
+  COM_TRY_BEGIN
+  {
+    Close();
+    if (Open2(stream) != S_OK)
+      return S_FALSE;
+    _inStream = stream;
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _inStream.Release();
+  _files.Clear();
+  _xml.Empty();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = _files.Size()
+    #ifdef XAR_SHOW_RAW
+    + 1
+    #endif
+  ;
+  return S_OK;
+}
+
+static void TimeToProp(UInt64 t, NWindows::NCOM::CPropVariant &prop)
+{
+  if (t != 0)
+  {
+    FILETIME ft;
+    ft.dwLowDateTime = (UInt32)(t);
+    ft.dwHighDateTime = (UInt32)(t >> 32);
+    prop = ft;
+  }
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  
+  #ifdef XAR_SHOW_RAW
+  if ((int)index == _files.Size())
+  {
+    switch(propID)
+    {
+      case kpidPath: prop = L"[TOC].xml"; break;
+      case kpidSize:
+      case kpidPackSize: prop = (UInt64)_xml.Length(); break;
+    }
+  }
+  else
+  #endif
+  {
+    const CFile &item = _files[index];
+    switch(propID)
+    {
+      case kpidMethod:
+      {
+        UString name;
+        if (!item.Method.IsEmpty() && ConvertUTF8ToUnicode(item.Method, name))
+          prop = name;
+        break;
+      }
+      case kpidPath:
+      {
+        AString path;
+        int cur = index;
+        do
+        {
+          const CFile &item = _files[cur];
+          AString s = item.Name;
+          if (s.IsEmpty())
+            s = "unknown";
+          if (path.IsEmpty())
+            path = s;
+          else
+            path = s + CHAR_PATH_SEPARATOR + path;
+          cur = item.Parent;
+        }
+        while (cur >= 0);
+
+        UString name;
+        if (ConvertUTF8ToUnicode(path, name))
+          prop = name;
+        break;
+      }
+      
+      case kpidIsDir:  prop = item.IsDir; break;
+      case kpidSize:      if (!item.IsDir) prop = item.Size; break;
+      case kpidPackSize:  if (!item.IsDir) prop = item.PackSize; break;
+      
+      case kpidMTime:  TimeToProp(item.MTime, prop); break;
+      case kpidCTime:  TimeToProp(item.CTime, prop); break;
+      case kpidATime:  TimeToProp(item.ATime, prop); break;
+    }
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = _files.Size();
+  if (numItems == 0)
+    return S_OK;
+  UInt64 totalSize = 0;
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+  {
+    int index = (int)(allFilesMode ? i : indices[i]);
+    #ifdef XAR_SHOW_RAW
+    if (index == _files.Size())
+      totalSize += _xml.Length();
+    else
+    #endif
+      totalSize += _files[index].Size;
+  }
+  extractCallback->SetTotal(totalSize);
+
+  UInt64 currentPackTotal = 0;
+  UInt64 currentUnpTotal = 0;
+  UInt64 currentPackSize = 0;
+  UInt64 currentUnpSize = 0;
+
+  const UInt32 kZeroBufSize = (1 << 14);
+  CByteBuffer zeroBuf;
+  zeroBuf.SetCapacity(kZeroBufSize);
+  memset(zeroBuf, 0, kZeroBufSize);
+  
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+  NCompress::NZlib::CDecoder *zlibCoderSpec = new NCompress::NZlib::CDecoder();
+  CMyComPtr<ICompressCoder> zlibCoder = zlibCoderSpec;
+  
+  NCompress::NBZip2::CDecoder *bzip2CoderSpec = new NCompress::NBZip2::CDecoder();
+  CMyComPtr<ICompressCoder> bzip2Coder = bzip2CoderSpec;
+
+  NCompress::NDeflate::NDecoder::CCOMCoder *deflateCoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder();
+  CMyComPtr<ICompressCoder> deflateCoder = deflateCoderSpec;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  CLimitedSequentialInStream *inStreamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<ISequentialInStream> inStream(inStreamSpec);
+  inStreamSpec->SetStream(_inStream);
+
+  
+  CLimitedSequentialOutStream *outStreamLimSpec = new CLimitedSequentialOutStream;
+  CMyComPtr<ISequentialOutStream> outStream(outStreamLimSpec);
+
+  COutStreamWithSha1 *outStreamSha1Spec = new COutStreamWithSha1;
+  {
+    CMyComPtr<ISequentialOutStream> outStreamSha1(outStreamSha1Spec);
+    outStreamLimSpec->SetStream(outStreamSha1);
+  }
+
+  for (i = 0; i < numItems; i++, currentPackTotal += currentPackSize, currentUnpTotal += currentUnpSize)
+  {
+    lps->InSize = currentPackTotal;
+    lps->OutSize = currentUnpTotal;
+    currentPackSize = 0;
+    currentUnpSize = 0;
+    RINOK(lps->SetCur());
+    CMyComPtr<ISequentialOutStream> realOutStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    Int32 index = allFilesMode ? i : indices[i];
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+    
+    if (index < _files.Size())
+    {
+      const CFile &item = _files[index];
+      if (item.IsDir)
+      {
+        RINOK(extractCallback->PrepareOperation(askMode));
+        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+        continue;
+      }
+    }
+
+    if (!testMode && !realOutStream)
+      continue;
+    RINOK(extractCallback->PrepareOperation(askMode));
+
+    outStreamSha1Spec->SetStream(realOutStream);
+    realOutStream.Release();
+
+    Int32 opRes = NExtract::NOperationResult::kOK;
+    #ifdef XAR_SHOW_RAW
+    if (index == _files.Size())
+    {
+      outStreamSha1Spec->Init(false);
+      outStreamLimSpec->Init(_xml.Length());
+      RINOK(WriteStream(outStream, (const char *)_xml, _xml.Length()));
+      currentPackSize = currentUnpSize = _xml.Length();
+    }
+    else
+    #endif
+    {
+      const CFile &item = _files[index];
+      if (item.HasData)
+      {
+        currentPackSize = item.PackSize;
+        currentUnpSize = item.Size;
+        
+        RINOK(_inStream->Seek(_dataStartPos + item.Offset, STREAM_SEEK_SET, NULL));
+        inStreamSpec->Init(item.PackSize);
+        outStreamSha1Spec->Init(item.Sha1IsDefined);
+        outStreamLimSpec->Init(item.Size);
+        HRESULT res = S_OK;
+        
+        ICompressCoder *coder = NULL;
+        if (item.Method.IsEmpty() || item.Method == "octet-stream")
+          if (item.PackSize == item.Size)
+            coder = copyCoder;
+          else
+            opRes = NExtract::NOperationResult::kUnSupportedMethod;
+        else if (item.Method == METHOD_NAME_ZLIB)
+          coder = zlibCoder;
+        else if (item.Method == "bzip2")
+          coder = bzip2Coder;
+        else
+          opRes = NExtract::NOperationResult::kUnSupportedMethod;
+        
+        if (coder)
+          res = coder->Code(inStream, outStream, NULL, NULL, progress);
+        
+        if (res != S_OK)
+        {
+          if (!outStreamLimSpec->IsFinishedOK())
+            opRes = NExtract::NOperationResult::kDataError;
+          else if (res != S_FALSE)
+            return res;
+          if (opRes == NExtract::NOperationResult::kOK)
+            opRes = NExtract::NOperationResult::kDataError;
+        }
+
+        if (opRes == NExtract::NOperationResult::kOK)
+        {
+          if (outStreamLimSpec->IsFinishedOK() &&
+              outStreamSha1Spec->GetSize() == item.Size)
+          {
+            if (!outStreamLimSpec->IsFinishedOK())
+            {
+              opRes = NExtract::NOperationResult::kDataError;
+            }
+            else if (item.Sha1IsDefined)
+            {
+              Byte digest[NCrypto::NSha1::kDigestSize];
+              outStreamSha1Spec->Final(digest);
+              if (memcmp(digest, item.Sha1, NCrypto::NSha1::kDigestSize) != 0)
+                opRes = NExtract::NOperationResult::kCRCError;
+            }
+          }
+          else
+            opRes = NExtract::NOperationResult::kDataError;
+        }
+      }
+    }
+    outStreamSha1Spec->ReleaseStream();
+    RINOK(extractCallback->SetOperationResult(opRes));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new NArchive::NXar::CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"Xar", L"xar", 0, 0xE1, { 'x', 'a', 'r', '!', 0, 0x1C }, 6, false, CreateArc, 0 };
+
+REGISTER_ARC(Xar)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/XzHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/XzHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/XzHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/XzHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,707 @@
+// XzHandler.cpp
+
+#include "StdAfx.h"
+
+#include "../../../C/Alloc.h"
+#include "../../../C/XzCrc64.h"
+#include "../../../C/XzEnc.h"
+
+#include "../../Common/ComTry.h"
+#include "../../Common/IntToString.h"
+
+#include "../ICoder.h"
+
+#include "../Common/CWrappers.h"
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/CopyCoder.h"
+
+#include "IArchive.h"
+
+#include "Common/HandlerOut.h"
+
+using namespace NWindows;
+
+namespace NCompress {
+namespace NLzma2 {
+
+HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props);
+
+}}
+
+static void *SzAlloc(void *, size_t size) { return MyAlloc(size); }
+static void SzFree(void *, void *address) { MyFree(address); }
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };
+
+namespace NArchive {
+namespace NXz {
+
+struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit;
+
+class CHandler:
+  public IInArchive,
+  public IArchiveOpenSeq,
+  #ifndef EXTRACT_ONLY
+  public IOutArchive,
+  public ISetProperties,
+  public COutHandler,
+  #endif
+  public CMyUnknownImp
+{
+  Int64 _startPosition;
+  UInt64 _packSize;
+  UInt64 _unpackSize;
+  UInt64 _numBlocks;
+  AString _methodsString;
+  bool _useSeq;
+  UInt64 _unpackSizeDefined;
+  UInt64 _packSizeDefined;
+  
+  CMyComPtr<IInStream> _stream;
+  CMyComPtr<ISequentialInStream> _seqStream;
+
+  UInt32 _crcSize;
+
+  void Init()
+  {
+    _crcSize = 4;
+    COutHandler::Init();
+  }
+
+  HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback);
+
+public:
+  MY_QUERYINTERFACE_BEGIN2(IInArchive)
+  MY_QUERYINTERFACE_ENTRY(IArchiveOpenSeq)
+  #ifndef EXTRACT_ONLY
+  MY_QUERYINTERFACE_ENTRY(IOutArchive)
+  MY_QUERYINTERFACE_ENTRY(ISetProperties)
+  #endif
+  MY_QUERYINTERFACE_END
+  MY_ADDREF_RELEASE
+
+  INTERFACE_IInArchive(;)
+  STDMETHOD(OpenSeq)(ISequentialInStream *stream);
+
+  #ifndef EXTRACT_ONLY
+  INTERFACE_IOutArchive(;)
+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);
+  #endif
+
+  CHandler();
+};
+
+CHandler::CHandler()
+{
+  Init();
+}
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMethod, VT_BSTR}
+};
+
+STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidMethod, VT_BSTR},
+  { NULL, kpidNumBlocks, VT_UI4}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+static char GetHex(Byte value)
+{
+  return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+}
+
+static inline void AddHexToString(AString &res, Byte value)
+{
+  res += GetHex((Byte)(value >> 4));
+  res += GetHex((Byte)(value & 0xF));
+}
+
+static AString ConvertUInt32ToString(UInt32 value)
+{
+  char temp[32];
+  ::ConvertUInt32ToString(value, temp);
+  return temp;
+}
+
+static AString Lzma2PropToString(int prop)
+{
+  if ((prop & 1) == 0)
+    return ConvertUInt32ToString(prop / 2 + 12);
+  AString res;
+  char c;
+
+  UInt32 size = (2 | ((prop) & 1)) << ((prop) / 2 + 1);
+
+  if (prop > 17)
+  {
+    res = ConvertUInt32ToString(size >> 10);
+    c = 'm';
+  }
+  else
+  {
+    res = ConvertUInt32ToString(size);
+    c = 'k';
+  }
+  return res + c;
+}
+
+struct CMethodNamePair
+{
+  UInt32 Id;
+  const char *Name;
+};
+
+static CMethodNamePair g_NamePairs[] =
+{
+  { XZ_ID_Subblock, "SB" },
+  { XZ_ID_Delta, "Delta" },
+  { XZ_ID_X86, "x86" },
+  { XZ_ID_PPC, "PPC" },
+  { XZ_ID_IA64, "IA64" },
+  { XZ_ID_ARM, "ARM" },
+  { XZ_ID_ARMT, "ARMT" },
+  { XZ_ID_SPARC, "SPARC" },
+  { XZ_ID_LZMA2, "LZMA2" }
+};
+
+static AString GetMethodString(const CXzFilter &f)
+{
+  AString s;
+
+  for (int i = 0; i < sizeof(g_NamePairs) / sizeof(g_NamePairs[i]); i++)
+    if (g_NamePairs[i].Id == f.id)
+      s = g_NamePairs[i].Name;
+  if (s.IsEmpty())
+  {
+    char temp[32];
+    ::ConvertUInt64ToString(f.id, temp);
+    s = temp;
+  }
+
+  if (f.propsSize > 0)
+  {
+    s += ':';
+    if (f.id == XZ_ID_LZMA2 && f.propsSize == 1)
+      s += Lzma2PropToString(f.props[0]);
+    else if (f.id == XZ_ID_Delta && f.propsSize == 1)
+      s += ConvertUInt32ToString((UInt32)f.props[0] + 1);
+    else
+    {
+      s += '[';
+      for (UInt32 bi = 0; bi < f.propsSize; bi++)
+        AddHexToString(s, f.props[bi]);
+      s += ']';
+    }
+  }
+  return s;
+}
+
+static void AddString(AString &dest, const AString &src)
+{
+  if (!dest.IsEmpty())
+    dest += ' ';
+  dest += src;
+}
+
+static const char *kChecks[] =
+{
+  "NoCheck",
+  "CRC32",
+  NULL,
+  NULL,
+  "CRC64",
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  "SHA256",
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL
+};
+
+static AString GetCheckString(const CXzs &xzs)
+{
+  size_t i;
+  UInt32 mask = 0;
+  for (i = 0; i < xzs.num; i++)
+    mask |= ((UInt32)1 << XzFlags_GetCheckType(xzs.streams[i].flags));
+  AString s;
+  for (i = 0; i <= XZ_CHECK_MASK; i++)
+    if (((mask >> i) & 1) != 0)
+    {
+      AString s2;
+      if (kChecks[i])
+        s2 = kChecks[i];
+      else
+        s2 = "Check-" + ConvertUInt32ToString((UInt32)i);
+      AddString(s, s2);
+    }
+  return s;
+}
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidNumBlocks: if (!_useSeq) prop = _numBlocks; break;
+    case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;
+    case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = 1;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID,  PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidSize: if (_unpackSizeDefined) prop = _unpackSize; break;
+    case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;
+    case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+
+struct COpenCallbackWrap
+{
+  ICompressProgress p;
+  IArchiveOpenCallback *OpenCallback;
+  HRESULT Res;
+  COpenCallbackWrap(IArchiveOpenCallback *progress);
+};
+
+static SRes OpenCallbackProgress(void *pp, UInt64 inSize, UInt64 /* outSize */)
+{
+  COpenCallbackWrap *p = (COpenCallbackWrap *)pp;
+  p->Res = p->OpenCallback->SetCompleted(NULL, &inSize);
+  return (SRes)p->Res;
+}
+
+COpenCallbackWrap::COpenCallbackWrap(IArchiveOpenCallback *callback)
+{
+  p.Progress = OpenCallbackProgress;
+  OpenCallback = callback;
+  Res = SZ_OK;
+}
+
+struct CXzsCPP
+{
+  CXzs p;
+  CXzsCPP() { Xzs_Construct(&p); }
+  ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); }
+};
+
+HRESULT CHandler::Open2(IInStream *inStream, IArchiveOpenCallback *callback)
+{
+  CSeekInStreamWrap inStreamImp(inStream);
+
+  CLookToRead lookStream;
+  LookToRead_CreateVTable(&lookStream, True);
+  lookStream.realStream = &inStreamImp.p;
+  LookToRead_Init(&lookStream);
+
+  COpenCallbackWrap openWrap(callback);
+  RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize));
+  RINOK(callback->SetTotal(NULL, &_packSize));
+
+  CXzsCPP xzs;
+  SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.s, &_startPosition, &openWrap.p, &g_Alloc);
+  if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0)
+    res = SZ_OK;
+  if (res == SZ_OK)
+  {
+    _packSize -= _startPosition;
+    _unpackSize = Xzs_GetUnpackSize(&xzs.p);
+    _unpackSizeDefined = _packSizeDefined = true;
+    _numBlocks = (UInt64)Xzs_GetNumBlocks(&xzs.p);
+
+    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
+    CXzStreamFlags st;
+    CSeqInStreamWrap inStreamWrap(inStream);
+    SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p);
+
+    if (res2 == SZ_OK)
+    {
+      CXzBlock block;
+      Bool isIndex;
+      UInt32 headerSizeRes;
+      res2 = XzBlock_ReadHeader(&block, &inStreamWrap.p, &isIndex, &headerSizeRes);
+      if (res2 == SZ_OK && !isIndex)
+      {
+        int numFilters = XzBlock_GetNumFilters(&block);
+        for (int i = 0; i < numFilters; i++)
+          AddString(_methodsString, GetMethodString(block.filters[i]));
+      }
+    }
+    AddString(_methodsString, GetCheckString(xzs.p));
+  }
+
+  if (res != SZ_OK || _startPosition != 0)
+  {
+    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
+    CXzStreamFlags st;
+    CSeqInStreamWrap inStreamWrap(inStream);
+    SRes res2 = Xz_ReadHeader(&st, &inStreamWrap.p);
+    if (res2 == SZ_OK)
+    {
+      res = res2;
+      _startPosition = 0;
+      _useSeq = True;
+      _unpackSizeDefined = _packSizeDefined = false;
+    }
+  }
+  if (res == SZ_ERROR_NO_ARCHIVE)
+    return S_FALSE;
+  RINOK(SResToHRESULT(res));
+  _stream = inStream;
+  _seqStream = inStream;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback)
+{
+  COM_TRY_BEGIN
+  try
+  {
+    Close();
+    return Open2(inStream, callback);
+  }
+  catch(...) { return S_FALSE; }
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
+{
+  Close();
+  _seqStream = stream;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _numBlocks = 0;
+  _useSeq = true;
+  _unpackSizeDefined = _packSizeDefined = false;
+  _methodsString.Empty();
+  _stream.Release();
+  _seqStream.Release();
+  return S_OK;
+}
+
+class CSeekToSeqStream:
+  public IInStream,
+  public CMyUnknownImp
+{
+public:
+  CMyComPtr<ISequentialInStream> Stream;
+  MY_UNKNOWN_IMP1(IInStream)
+
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+};
+
+STDMETHODIMP CSeekToSeqStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  return Stream->Read(data, size, processedSize);
+}
+
+STDMETHODIMP CSeekToSeqStream::Seek(Int64, UInt32, UInt64 *) { return E_NOTIMPL; }
+
+struct CXzUnpackerCPP
+{
+  Byte *InBuf;
+  Byte *OutBuf;
+  CXzUnpacker p;
+  CXzUnpackerCPP(): InBuf(0), OutBuf(0) {}
+  ~CXzUnpackerCPP()
+  {
+    XzUnpacker_Free(&p);
+    MyFree(InBuf);
+    MyFree(OutBuf);
+  }
+};
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  if (numItems == 0)
+    return S_OK;
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
+    return E_INVALIDARG;
+
+  extractCallback->SetTotal(_packSize);
+  UInt64 currentTotalPacked = 0;
+  RINOK(extractCallback->SetCompleted(&currentTotalPacked));
+  CMyComPtr<ISequentialOutStream> realOutStream;
+  Int32 askMode = testMode ?
+      NExtract::NAskMode::kTest :
+      NExtract::NAskMode::kExtract;
+  
+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
+  
+  if (!testMode && !realOutStream)
+    return S_OK;
+
+  extractCallback->PrepareOperation(askMode);
+
+  if (_stream)
+  {
+    RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));
+  }
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, true);
+
+  CCompressProgressWrap progressWrap(progress);
+
+  SRes res;
+
+  const UInt32 kInBufSize = 1 << 15;
+  const UInt32 kOutBufSize = 1 << 21;
+
+  UInt32 inPos = 0;
+  UInt32 inSize = 0;
+  UInt32 outPos = 0;
+  CXzUnpackerCPP xzu;
+  res = XzUnpacker_Create(&xzu.p, &g_Alloc);
+  if (res == SZ_OK)
+  {
+    xzu.InBuf = (Byte *)MyAlloc(kInBufSize);
+    xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize);
+    if (xzu.InBuf == 0 || xzu.OutBuf == 0)
+      res = SZ_ERROR_MEM;
+  }
+  if (res == SZ_OK)
+  for (;;)
+  {
+    if (inPos == inSize)
+    {
+      inPos = inSize = 0;
+      RINOK(_seqStream->Read(xzu.InBuf, kInBufSize, &inSize));
+    }
+
+    SizeT inLen = inSize - inPos;
+    SizeT outLen = kOutBufSize - outPos;
+    ECoderStatus status;
+    res = XzUnpacker_Code(&xzu.p,
+        xzu.OutBuf + outPos, &outLen,
+        xzu.InBuf + inPos, &inLen,
+        (inSize == 0 ? CODER_FINISH_END : CODER_FINISH_ANY), &status);
+
+    // printf("\n_inPos = %6d  inLen = %5d, outLen = %5d", inPos, inLen, outLen);
+
+    inPos += (UInt32)inLen;
+    outPos += (UInt32)outLen;
+    lps->InSize += inLen;
+    lps->OutSize += outLen;
+
+    bool finished = (((inLen == 0) && (outLen == 0)) || res != SZ_OK);
+
+    if (outPos == kOutBufSize || finished)
+    {
+      if (realOutStream && outPos > 0)
+      {
+        RINOK(WriteStream(realOutStream, xzu.OutBuf, outPos));
+      }
+      outPos = 0;
+    }
+    if (finished)
+    {
+      _packSize = lps->InSize;
+      _unpackSize = lps->OutSize;
+      _packSizeDefined = _unpackSizeDefined = true;
+      if (res == SZ_OK)
+      {
+        if (status == CODER_STATUS_NEEDS_MORE_INPUT)
+        {
+          if (XzUnpacker_IsStreamWasFinished(&xzu.p))
+            _packSize -= xzu.p.padSize;
+          else
+            res = SZ_ERROR_DATA;
+        }
+        else
+          res = SZ_ERROR_DATA;
+      }
+      break;
+    }
+    RINOK(lps->SetCur());
+  }
+
+  Int32 opRes;
+  switch(res)
+  {
+    case SZ_OK:
+      opRes = NExtract::NOperationResult::kOK; break;
+    case SZ_ERROR_UNSUPPORTED:
+      opRes = NExtract::NOperationResult::kUnSupportedMethod; break;
+    case SZ_ERROR_CRC:
+      opRes = NExtract::NOperationResult::kCRCError; break;
+    case SZ_ERROR_DATA:
+    case SZ_ERROR_ARCHIVE:
+    case SZ_ERROR_NO_ARCHIVE:
+      opRes = NExtract::NOperationResult::kDataError; break;
+    default:
+      return SResToHRESULT(res);
+  }
+  realOutStream.Release();
+  RINOK(extractCallback->SetOperationResult(opRes));
+  return S_OK;
+  COM_TRY_END
+}
+
+#ifndef EXTRACT_ONLY
+
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
+{
+  *timeType = NFileTimeType::kUnix;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+    IArchiveUpdateCallback *updateCallback)
+{
+  CSeqOutStreamWrap seqOutStream(outStream);
+  
+  if (numItems == 0)
+  {
+    SRes res = Xz_EncodeEmpty(&seqOutStream.p);
+    return SResToHRESULT(res);
+  }
+  
+  if (numItems != 1)
+    return E_INVALIDARG;
+
+  Int32 newData, newProps;
+  UInt32 indexInArchive;
+  if (!updateCallback)
+    return E_FAIL;
+  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));
+
+  if (IntToBool(newProps))
+  {
+    {
+      NCOM::CPropVariant prop;
+      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));
+      if (prop.vt != VT_EMPTY)
+        if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)
+          return E_INVALIDARG;
+    }
+  }
+
+  if (IntToBool(newData))
+  {
+    {
+      UInt64 size;
+      NCOM::CPropVariant prop;
+      RINOK(updateCallback->GetProperty(0, kpidSize, &prop));
+      if (prop.vt != VT_UI8)
+        return E_INVALIDARG;
+      size = prop.uhVal.QuadPart;
+      RINOK(updateCallback->SetTotal(size));
+    }
+
+    CLzma2EncProps lzma2Props;
+    Lzma2EncProps_Init(&lzma2Props);
+
+    lzma2Props.lzmaProps.level = _level;
+
+    CMyComPtr<ISequentialInStream> fileInStream;
+    RINOK(updateCallback->GetStream(0, &fileInStream));
+
+    CSeqInStreamWrap seqInStream(fileInStream);
+
+    for (int i = 0; i < _methods.Size(); i++)
+    {
+      COneMethodInfo &m = _methods[i];
+      SetCompressionMethod2(m
+      #ifndef _7ZIP_ST
+      , _numThreads
+      #endif
+      );
+      if (m.IsLzma())
+      {
+        for (int j = 0; j < m.Props.Size(); j++)
+        {
+          const CProp &prop = m.Props[j];
+          RINOK(NCompress::NLzma2::SetLzma2Prop(prop.Id, prop.Value, lzma2Props));
+        }
+      }
+    }
+
+    #ifndef _7ZIP_ST
+    lzma2Props.numTotalThreads = _numThreads;
+    #endif
+
+    CLocalProgress *lps = new CLocalProgress;
+    CMyComPtr<ICompressProgressInfo> progress = lps;
+    lps->Init(updateCallback, true);
+
+    CCompressProgressWrap progressWrap(progress);
+    SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &lzma2Props, False, &progressWrap.p);
+    if (res == SZ_OK)
+      return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
+    return SResToHRESULT(res);
+  }
+  if (indexInArchive != 0)
+    return E_INVALIDARG;
+  if (_stream)
+    RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));
+  return NCompress::CopyStream(_stream, outStream, 0);
+}
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
+{
+  COM_TRY_BEGIN
+  BeforeSetProperty();
+  for (int i = 0; i < numProps; i++)
+  {
+    RINOK(SetProperty(names[i], values[i]));
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+#endif
+
+static IInArchive *CreateArc() { return new NArchive::NXz::CHandler; }
+#ifndef EXTRACT_ONLY
+static IOutArchive *CreateArcOut() { return new NArchive::NXz::CHandler; }
+#else
+#define CreateArcOut 0
+#endif
+
+static CArcInfo g_ArcInfo =
+  { L"xz", L"xz txz", L"* .tar", 0xC, {0xFD, '7' , 'z', 'X', 'Z', '\0'}, 6, true, CreateArc, CreateArcOut };
+
+REGISTER_ARC(xz)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/ZHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/ZHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/ZHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/ZHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,161 @@
+// ZHandler.cpp
+
+#include "StdAfx.h"
+
+#include "Common/ComTry.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../Common/ProgressUtils.h"
+#include "../Common/RegisterArc.h"
+#include "../Common/StreamUtils.h"
+
+#include "../Compress/ZDecoder.h"
+
+#include "Common/DummyOutStream.h"
+
+namespace NArchive {
+namespace NZ {
+
+class CHandler:
+  public IInArchive,
+  public CMyUnknownImp
+{
+  CMyComPtr<IInStream> _stream;
+  UInt64 _streamStartPosition;
+  UInt64 _packSize;
+  Byte _properties;
+public:
+  MY_UNKNOWN_IMP1(IInArchive)
+  INTERFACE_IInArchive(;)
+};
+
+STATPROPSTG kProps[] =
+{
+  { NULL, kpidPackSize, VT_UI8}
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_NO
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = 1;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID,  PROPVARIANT *value)
+{
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidPackSize: prop = _packSize; break;
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+static const int kSignatureSize = 3;
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+    const UInt64 * /* maxCheckStartPosition */,
+    IArchiveOpenCallback * /* openArchiveCallback */)
+{
+  COM_TRY_BEGIN
+  {
+    RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_streamStartPosition));
+    Byte buffer[kSignatureSize];
+    RINOK(ReadStream_FALSE(stream, buffer, kSignatureSize));
+    if (buffer[0] != 0x1F || buffer[1] != 0x9D)
+      return S_FALSE;
+    _properties = buffer[2];
+
+    UInt64 endPosition;
+    RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition));
+    _packSize = endPosition - _streamStartPosition - kSignatureSize;
+    
+    _stream = stream;
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  _stream.Release();
+  return S_OK;
+}
+
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  if (numItems == 0)
+    return S_OK;
+  if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0))
+    return E_INVALIDARG;
+
+  extractCallback->SetTotal(_packSize);
+
+  UInt64 currentTotalPacked = 0;
+  
+  RINOK(extractCallback->SetCompleted(&currentTotalPacked));
+  
+  CMyComPtr<ISequentialOutStream> realOutStream;
+  Int32 askMode = testMode ?
+      NExtract::NAskMode::kTest :
+      NExtract::NAskMode::kExtract;
+  
+  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
+    
+  if (!testMode && !realOutStream)
+    return S_OK;
+
+  extractCallback->PrepareOperation(askMode);
+
+  CDummyOutStream *outStreamSpec = new CDummyOutStream;
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+  outStreamSpec->SetStream(realOutStream);
+  outStreamSpec->Init();
+  realOutStream.Release();
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, true);
+  
+  RINOK(_stream->Seek(_streamStartPosition + kSignatureSize, STREAM_SEEK_SET, NULL));
+
+  CMyComPtr<ICompressCoder> decoder;
+  NCompress::NZ::CDecoder *decoderSpec = new NCompress::NZ::CDecoder;
+  decoder = decoderSpec;
+
+  HRESULT result = decoderSpec->SetDecoderProperties2(&_properties, 1);
+
+  int opResult;
+  if (result != S_OK)
+    opResult = NExtract::NOperationResult::kUnSupportedMethod;
+  else
+  {
+    result = decoder->Code(_stream, outStream, NULL, NULL, progress);
+    if (result == S_FALSE)
+      opResult = NExtract::NOperationResult::kDataError;
+    else
+    {
+      RINOK(result);
+      opResult = NExtract::NOperationResult::kOK;
+    }
+  }
+  outStream.Release();
+  return extractCallback->SetOperationResult(opResult);
+  COM_TRY_END
+}
+
+static IInArchive *CreateArc() { return new CHandler; }
+
+static CArcInfo g_ArcInfo =
+  { L"Z", L"z taz", L"* .tar", 5, { 0x1F, 0x9D }, 2, false, CreateArc, 0 };
+
+REGISTER_ARC(Z)
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipAddCommon.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipAddCommon.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipAddCommon.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,379 @@
+// ZipAddCommon.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/7zCrc.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../../ICoder.h"
+#include "../../IPassword.h"
+#include "../../MyVersion.h"
+
+#include "../../Common/CreateCoder.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/StreamUtils.h"
+
+#include "../../Compress/LzmaEncoder.h"
+#include "../../Compress/PpmdZip.h"
+
+#include "../Common/InStreamWithCRC.h"
+
+#include "ZipAddCommon.h"
+#include "ZipHeader.h"
+
+namespace NArchive {
+namespace NZip {
+
+static const CMethodId kMethodId_ZipBase   = 0x040100;
+static const CMethodId kMethodId_BZip2     = 0x040202;
+
+static const UInt32 kLzmaPropsSize = 5;
+static const UInt32 kLzmaHeaderSize = 4 + kLzmaPropsSize;
+
+class CLzmaEncoder:
+  public ICompressCoder,
+  public CMyUnknownImp
+{
+  NCompress::NLzma::CEncoder *EncoderSpec;
+  CMyComPtr<ICompressCoder> Encoder;
+  Byte Header[kLzmaHeaderSize];
+public:
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+  HRESULT SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
+
+  MY_UNKNOWN_IMP
+};
+
+HRESULT CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)
+{
+  if (!Encoder)
+  {
+    EncoderSpec = new NCompress::NLzma::CEncoder;
+    Encoder = EncoderSpec;
+  }
+  CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;
+  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+  outStreamSpec->Init(Header + 4, kLzmaPropsSize);
+  RINOK(EncoderSpec->SetCoderProperties(propIDs, props, numProps));
+  RINOK(EncoderSpec->WriteCoderProperties(outStream));
+  if (outStreamSpec->GetPos() != kLzmaPropsSize)
+    return E_FAIL;
+  Header[0] = MY_VER_MAJOR;
+  Header[1] = MY_VER_MINOR;
+  Header[2] = kLzmaPropsSize;
+  Header[3] = 0;
+  return S_OK;
+}
+
+HRESULT CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
+{
+  RINOK(WriteStream(outStream, Header, kLzmaHeaderSize));
+  return Encoder->Code(inStream, outStream, inSize, outSize, progress);
+}
+
+
+CAddCommon::CAddCommon(const CCompressionMethodMode &options):
+  _options(options),
+  _copyCoderSpec(NULL),
+  _cryptoStreamSpec(0)
+  {}
+
+static HRESULT GetStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC)
+{
+  UInt32 crc = CRC_INIT_VAL;
+  const UInt32 kBufferSize = (1 << 14);
+  Byte buffer[kBufferSize];
+  for (;;)
+  {
+    UInt32 realProcessedSize;
+    RINOK(inStream->Read(buffer, kBufferSize, &realProcessedSize));
+    if (realProcessedSize == 0)
+    {
+      resultCRC = CRC_GET_DIGEST(crc);
+      return S_OK;
+    }
+    crc = CrcUpdate(crc, buffer, (size_t)realProcessedSize);
+  }
+}
+
+HRESULT CAddCommon::Compress(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    ISequentialInStream *inStream, IOutStream *outStream,
+    ICompressProgressInfo *progress, CCompressingResult &opRes)
+{
+  CSequentialInStreamWithCRC *inSecCrcStreamSpec = 0;
+  CInStreamWithCRC *inCrcStreamSpec = 0;
+  CMyComPtr<ISequentialInStream> inCrcStream;
+  {
+    CMyComPtr<IInStream> inStream2;
+    // we don't support stdin, since stream from stdin can require 64-bit size header
+    RINOK(inStream->QueryInterface(IID_IInStream, (void **)&inStream2));
+    if (inStream2)
+    {
+      inCrcStreamSpec = new CInStreamWithCRC;
+      inCrcStream = inCrcStreamSpec;
+      inCrcStreamSpec->SetStream(inStream2);
+      inCrcStreamSpec->Init();
+    }
+    else
+    {
+      inSecCrcStreamSpec = new CSequentialInStreamWithCRC;
+      inCrcStream = inSecCrcStreamSpec;
+      inSecCrcStreamSpec->SetStream(inStream);
+      inSecCrcStreamSpec->Init();
+    }
+  }
+
+  int numTestMethods = _options.MethodSequence.Size();
+  if (numTestMethods > 1 || _options.PasswordIsDefined)
+  {
+    if (inCrcStreamSpec == 0)
+    {
+      if (_options.PasswordIsDefined)
+        return E_NOTIMPL;
+      numTestMethods = 1;
+    }
+  }
+  Byte method = 0;
+  COutStreamReleaser outStreamReleaser;
+  opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default;
+  for (int i = 0; i < numTestMethods; i++)
+  {
+    opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default;
+    if (inCrcStreamSpec != 0)
+      RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
+    RINOK(outStream->SetSize(0));
+    RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL));
+    if (_options.PasswordIsDefined)
+    {
+      opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_ZipCrypto;
+
+      if (!_cryptoStream)
+      {
+        _cryptoStreamSpec = new CFilterCoder;
+        _cryptoStream = _cryptoStreamSpec;
+      }
+      if (_options.IsAesMode)
+      {
+        opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Aes;
+        if (!_cryptoStreamSpec->Filter)
+        {
+          _cryptoStreamSpec->Filter = _filterAesSpec = new NCrypto::NWzAes::CEncoder;
+          _filterAesSpec->SetKeyMode(_options.AesKeyMode);
+          RINOK(_filterAesSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Length()));
+        }
+        RINOK(_filterAesSpec->WriteHeader(outStream));
+      }
+      else
+      {
+        if (!_cryptoStreamSpec->Filter)
+        {
+          _cryptoStreamSpec->Filter = _filterSpec = new NCrypto::NZip::CEncoder;
+          _filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Length());
+        }
+        UInt32 crc = 0;
+        RINOK(GetStreamCRC(inStream, crc));
+        RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
+        RINOK(_filterSpec->WriteHeader(outStream, crc));
+      }
+      RINOK(_cryptoStreamSpec->SetOutStream(outStream));
+      outStreamReleaser.FilterCoder = _cryptoStreamSpec;
+    }
+
+    method = _options.MethodSequence[i];
+    switch(method)
+    {
+      case NFileHeader::NCompressionMethod::kStored:
+      {
+        if (_copyCoderSpec == NULL)
+        {
+          _copyCoderSpec = new NCompress::CCopyCoder;
+          _copyCoder = _copyCoderSpec;
+        }
+        CMyComPtr<ISequentialOutStream> outStreamNew;
+        if (_options.PasswordIsDefined)
+          outStreamNew = _cryptoStream;
+        else
+          outStreamNew = outStream;
+        RINOK(_copyCoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress));
+        break;
+      }
+      default:
+      {
+        if (!_compressEncoder)
+        {
+          if (method == NFileHeader::NCompressionMethod::kLZMA)
+          {
+            _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_LZMA;
+            CLzmaEncoder *_lzmaEncoder = new CLzmaEncoder();
+            _compressEncoder = _lzmaEncoder;
+            NWindows::NCOM::CPropVariant props[] =
+            {
+              #ifndef _7ZIP_ST
+              _options.NumThreads,
+              #endif
+              _options.Algo,
+              _options.DicSize,
+              _options.NumFastBytes,
+              const_cast<BSTR>((const wchar_t *)_options.MatchFinder),
+              _options.NumMatchFinderCycles
+            };
+            PROPID propIDs[] =
+            {
+              #ifndef _7ZIP_ST
+              NCoderPropID::kNumThreads,
+              #endif
+              NCoderPropID::kAlgorithm,
+              NCoderPropID::kDictionarySize,
+              NCoderPropID::kNumFastBytes,
+              NCoderPropID::kMatchFinder,
+              NCoderPropID::kMatchFinderCycles
+            };
+            int numProps = sizeof(propIDs) / sizeof(propIDs[0]);
+            if (!_options.NumMatchFinderCyclesDefined)
+              numProps--;
+            RINOK(_lzmaEncoder->SetCoderProperties(propIDs, props, numProps));
+          }
+          else if (method == NFileHeader::NCompressionMethod::kPPMd)
+          {
+            _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_PPMd;
+            NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder();
+            _compressEncoder = encoder;
+            NWindows::NCOM::CPropVariant props[] =
+            {
+              _options.Algo,
+              _options.MemSize,
+              _options.Order
+              
+            };
+            PROPID propIDs[] =
+            {
+              NCoderPropID::kAlgorithm,
+              NCoderPropID::kUsedMemorySize,
+              NCoderPropID::kOrder
+            };
+            RINOK(encoder->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0])));
+          }
+          else
+          {
+          CMethodId methodId;
+          switch(method)
+          {
+            case NFileHeader::NCompressionMethod::kBZip2:
+              methodId = kMethodId_BZip2;
+              _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_BZip2;
+              break;
+            default:
+              _compressExtractVersion = ((method == NFileHeader::NCompressionMethod::kDeflated64) ?
+                  NFileHeader::NCompressionMethod::kExtractVersion_Deflate64 :
+                  NFileHeader::NCompressionMethod::kExtractVersion_Deflate);
+              methodId = kMethodId_ZipBase + method;
+              break;
+          }
+          RINOK(CreateCoder(
+              EXTERNAL_CODECS_LOC_VARS
+              methodId, _compressEncoder, true));
+          if (!_compressEncoder)
+            return E_NOTIMPL;
+
+          if (method == NFileHeader::NCompressionMethod::kDeflated ||
+              method == NFileHeader::NCompressionMethod::kDeflated64)
+          {
+            NWindows::NCOM::CPropVariant props[] =
+            {
+              _options.Algo,
+              _options.NumPasses,
+              _options.NumFastBytes,
+              _options.NumMatchFinderCycles
+            };
+            PROPID propIDs[] =
+            {
+              NCoderPropID::kAlgorithm,
+              NCoderPropID::kNumPasses,
+              NCoderPropID::kNumFastBytes,
+              NCoderPropID::kMatchFinderCycles
+            };
+            int numProps = sizeof(propIDs) / sizeof(propIDs[0]);
+            if (!_options.NumMatchFinderCyclesDefined)
+              numProps--;
+            CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
+            _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties);
+            if (setCoderProperties)
+            {
+              RINOK(setCoderProperties->SetCoderProperties(propIDs, props, numProps));
+            }
+          }
+          else if (method == NFileHeader::NCompressionMethod::kBZip2)
+          {
+            NWindows::NCOM::CPropVariant props[] =
+            {
+              _options.DicSize,
+              _options.NumPasses
+              #ifndef _7ZIP_ST
+              , _options.NumThreads
+              #endif
+            };
+            PROPID propIDs[] =
+            {
+              NCoderPropID::kDictionarySize,
+              NCoderPropID::kNumPasses
+              #ifndef _7ZIP_ST
+              , NCoderPropID::kNumThreads
+              #endif
+            };
+            CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
+            _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties);
+            if (setCoderProperties)
+            {
+              RINOK(setCoderProperties->SetCoderProperties(propIDs, props, sizeof(propIDs) / sizeof(propIDs[0])));
+            }
+          }
+          }
+        }
+        CMyComPtr<ISequentialOutStream> outStreamNew;
+        if (_options.PasswordIsDefined)
+          outStreamNew = _cryptoStream;
+        else
+          outStreamNew = outStream;
+        if (_compressExtractVersion > opRes.ExtractVersion)
+          opRes.ExtractVersion = _compressExtractVersion;
+        RINOK(_compressEncoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress));
+        break;
+      }
+    }
+
+    RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize));
+
+    if (inCrcStreamSpec != 0)
+    {
+      opRes.CRC = inCrcStreamSpec->GetCRC();
+      opRes.UnpackSize = inCrcStreamSpec->GetSize();
+    }
+    else
+    {
+      opRes.CRC = inSecCrcStreamSpec->GetCRC();
+      opRes.UnpackSize = inSecCrcStreamSpec->GetSize();
+    }
+
+    if (_options.PasswordIsDefined)
+    {
+      if (opRes.PackSize < opRes.UnpackSize +
+          (_options.IsAesMode ? _filterAesSpec->GetHeaderSize() : NCrypto::NZip::kHeaderSize))
+        break;
+    }
+    else if (opRes.PackSize < opRes.UnpackSize)
+      break;
+  }
+  if (_options.IsAesMode)
+  {
+    RINOK(_filterAesSpec->WriteFooter(outStream));
+    RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize));
+  }
+  opRes.Method = method;
+  return S_OK;
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipAddCommon.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipAddCommon.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipAddCommon.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipAddCommon.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,56 @@
+// ZipAddCommon.h
+
+#ifndef __ZIP_ADD_COMMON_H
+#define __ZIP_ADD_COMMON_H
+
+#include "../../ICoder.h"
+#include "../../IProgress.h"
+
+#include "../../Common/CreateCoder.h"
+#include "../../Common/FilterCoder.h"
+
+#include "../../Compress/CopyCoder.h"
+
+#include "../../Crypto/ZipCrypto.h"
+#include "../../Crypto/WzAes.h"
+
+#include "ZipCompressionMode.h"
+
+namespace NArchive {
+namespace NZip {
+
+struct CCompressingResult
+{
+  UInt64 UnpackSize;
+  UInt64 PackSize;
+  UInt32 CRC;
+  UInt16 Method;
+  Byte ExtractVersion;
+};
+
+class CAddCommon
+{
+  CCompressionMethodMode _options;
+  NCompress::CCopyCoder *_copyCoderSpec;
+  CMyComPtr<ICompressCoder> _copyCoder;
+
+  CMyComPtr<ICompressCoder> _compressEncoder;
+  Byte _compressExtractVersion;
+
+  CFilterCoder *_cryptoStreamSpec;
+  CMyComPtr<ISequentialOutStream> _cryptoStream;
+
+  NCrypto::NZip::CEncoder *_filterSpec;
+  NCrypto::NWzAes::CEncoder *_filterAesSpec;
+
+public:
+  CAddCommon(const CCompressionMethodMode &options);
+  HRESULT Compress(
+      DECL_EXTERNAL_CODECS_LOC_VARS
+      ISequentialInStream *inStream, IOutStream *outStream,
+      ICompressProgressInfo *progress, CCompressingResult &operationResult);
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipCompressionMode.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipCompressionMode.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipCompressionMode.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipCompressionMode.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,42 @@
+// CompressionMode.h
+
+#ifndef __ZIP_COMPRESSION_MODE_H
+#define __ZIP_COMPRESSION_MODE_H
+
+#include "Common/MyString.h"
+
+namespace NArchive {
+namespace NZip {
+
+struct CCompressionMethodMode
+{
+  CRecordVector<Byte> MethodSequence;
+  UString MatchFinder;
+  UInt32 Algo;
+  UInt32 NumPasses;
+  UInt32 NumFastBytes;
+  bool NumMatchFinderCyclesDefined;
+  UInt32 NumMatchFinderCycles;
+  UInt32 DicSize;
+  UInt32 MemSize;
+  UInt32 Order;
+
+  #ifndef _7ZIP_ST
+  UInt32 NumThreads;
+  #endif
+  bool PasswordIsDefined;
+  AString Password;
+  bool IsAesMode;
+  Byte AesKeyMode;
+  
+  CCompressionMethodMode():
+      NumMatchFinderCyclesDefined(false),
+      PasswordIsDefined(false),
+      IsAesMode(false),
+      AesKeyMode(3)
+      {}
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHandler.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHandler.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHandler.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,822 @@
+// ZipHandler.cpp
+
+#include "StdAfx.h"
+
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../../IPassword.h"
+
+#include "../../Common/FilterCoder.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/StreamUtils.h"
+
+#include "../../Compress/CopyCoder.h"
+#include "../../Compress/LzmaDecoder.h"
+#include "../../Compress/ImplodeDecoder.h"
+#include "../../Compress/PpmdZip.h"
+#include "../../Compress/ShrinkDecoder.h"
+
+#include "../../Crypto/WzAes.h"
+#include "../../Crypto/ZipCrypto.h"
+#include "../../Crypto/ZipStrong.h"
+
+#include "../Common/ItemNameUtils.h"
+#include "../Common/OutStreamWithCRC.h"
+
+#include "ZipHandler.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NZip {
+
+static const CMethodId kMethodId_ZipBase = 0x040100;
+static const CMethodId kMethodId_BZip2 = 0x040202;
+
+static const char *kHostOS[] =
+{
+  "FAT",
+  "AMIGA",
+  "VMS",
+  "Unix",
+  "VM/CMS",
+  "Atari",
+  "HPFS",
+  "Macintosh",
+  "Z-System",
+  "CP/M",
+  "TOPS-20",
+  "NTFS",
+  "SMS/QDOS",
+  "Acorn",
+  "VFAT",
+  "MVS",
+  "BeOS",
+  "Tandem",
+  "OS/400",
+  "OS/X"
+};
+
+static const char *kUnknownOS = "Unknown";
+
+static const char *kMethods[] =
+{
+  "Store",
+  "Shrink",
+  "Reduced1",
+  "Reduced2",
+  "Reduced3",
+  "Reduced4",
+  "Implode",
+  "Tokenizing",
+  "Deflate",
+  "Deflate64",
+  "PKImploding"
+};
+
+static const char *kBZip2Method = "BZip2";
+static const char *kLZMAMethod = "LZMA";
+static const char *kJpegMethod = "Jpeg";
+static const char *kWavPackMethod = "WavPack";
+static const char *kPPMdMethod = "PPMd";
+static const char *kAESMethod = "AES";
+static const char *kZipCryptoMethod = "ZipCrypto";
+static const char *kStrongCryptoMethod = "StrongCrypto";
+
+static struct CStrongCryptoPair
+{
+  UInt16 Id;
+  const char *Name;
+} g_StrongCryptoPairs[] =
+{
+  { NStrongCryptoFlags::kDES, "DES" },
+  { NStrongCryptoFlags::kRC2old, "RC2a" },
+  { NStrongCryptoFlags::k3DES168, "3DES-168" },
+  { NStrongCryptoFlags::k3DES112, "3DES-112" },
+  { NStrongCryptoFlags::kAES128, "pkAES-128" },
+  { NStrongCryptoFlags::kAES192, "pkAES-192" },
+  { NStrongCryptoFlags::kAES256, "pkAES-256" },
+  { NStrongCryptoFlags::kRC2, "RC2" },
+  { NStrongCryptoFlags::kBlowfish, "Blowfish" },
+  { NStrongCryptoFlags::kTwofish, "Twofish" },
+  { NStrongCryptoFlags::kRC4, "RC4" }
+};
+
+static STATPROPSTG kProps[] =
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidIsDir, VT_BOOL},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidPackSize, VT_UI8},
+  { NULL, kpidMTime, VT_FILETIME},
+  { NULL, kpidCTime, VT_FILETIME},
+  { NULL, kpidATime, VT_FILETIME},
+  { NULL, kpidAttrib, VT_UI4},
+  { NULL, kpidEncrypted, VT_BOOL},
+  { NULL, kpidComment, VT_BSTR},
+  { NULL, kpidCRC, VT_UI4},
+  { NULL, kpidMethod, VT_BSTR},
+  { NULL, kpidHostOS, VT_BSTR},
+  { NULL, kpidUnpackVer, VT_UI4}
+};
+
+static STATPROPSTG kArcProps[] =
+{
+  { NULL, kpidBit64, VT_BOOL},
+  { NULL, kpidComment, VT_BSTR},
+  { NULL, kpidPhySize, VT_UI8},
+  { NULL, kpidOffset, VT_UI8}
+};
+
+CHandler::CHandler()
+{
+  InitMethodProperties();
+}
+
+static AString BytesToString(const CByteBuffer &data)
+{
+  AString s;
+  int size = (int)data.GetCapacity();
+  if (size > 0)
+  {
+    char *p = s.GetBuffer(size + 1);
+    memcpy(p, (const Byte *)data, size);
+    p[size] = '\0';
+    s.ReleaseBuffer();
+  }
+  return s;
+}
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidBit64:  if (m_Archive.IsZip64) prop = m_Archive.IsZip64; break;
+    case kpidComment:  prop = MultiByteToUnicodeString(BytesToString(m_Archive.ArcInfo.Comment), CP_ACP); break;
+    case kpidPhySize:  prop = m_Archive.ArcInfo.GetPhySize(); break;
+    case kpidOffset:  if (m_Archive.ArcInfo.StartPosition != 0) prop = m_Archive.ArcInfo.StartPosition; break;
+  }
+  prop.Detach(value);
+  COM_TRY_END
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = m_Items.Size();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  const CItemEx &item = m_Items[index];
+  switch(propID)
+  {
+    case kpidPath:  prop = NItemName::GetOSName2(item.GetUnicodeString(item.Name)); break;
+    case kpidIsDir:  prop = item.IsDir(); break;
+    case kpidSize:  prop = item.UnPackSize; break;
+    case kpidPackSize:  prop = item.PackSize; break;
+    case kpidTimeType:
+    {
+      FILETIME ft;
+      UInt32 unixTime;
+      if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft))
+        prop = (UInt32)NFileTimeType::kWindows;
+      else if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime))
+        prop = (UInt32)NFileTimeType::kUnix;
+      else
+        prop = (UInt32)NFileTimeType::kDOS;
+      break;
+    }
+    case kpidCTime:
+    {
+      FILETIME ft;
+      if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kCTime, ft))
+        prop = ft;
+      break;
+    }
+    case kpidATime:
+    {
+      FILETIME ft;
+      if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kATime, ft))
+        prop = ft;
+      break;
+    }
+    case kpidMTime:
+    {
+      FILETIME utc;
+      if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utc))
+      {
+        UInt32 unixTime;
+        if (item.CentralExtra.GetUnixTime(NFileHeader::NUnixTime::kMTime, unixTime))
+          NTime::UnixTimeToFileTime(unixTime, utc);
+        else
+        {
+          FILETIME localFileTime;
+          if (!NTime::DosTimeToFileTime(item.Time, localFileTime) ||
+              !LocalFileTimeToFileTime(&localFileTime, &utc))
+            utc.dwHighDateTime = utc.dwLowDateTime = 0;
+        }
+      }
+      prop = utc;
+      break;
+    }
+    case kpidAttrib:  prop = item.GetWinAttributes(); break;
+    case kpidEncrypted:  prop = item.IsEncrypted(); break;
+    case kpidComment:  prop = item.GetUnicodeString(BytesToString(item.Comment)); break;
+    case kpidCRC:  if (item.IsThereCrc()) prop = item.FileCRC; break;
+    case kpidMethod:
+    {
+      UInt16 methodId = item.CompressionMethod;
+      AString method;
+      if (item.IsEncrypted())
+      {
+        if (methodId == NFileHeader::NCompressionMethod::kWzAES)
+        {
+          method = kAESMethod;
+          CWzAesExtraField aesField;
+          if (item.CentralExtra.GetWzAesField(aesField))
+          {
+            method += '-';
+            char s[32];
+            ConvertUInt64ToString((aesField.Strength + 1) * 64 , s);
+            method += s;
+            method += ' ';
+            methodId = aesField.Method;
+          }
+        }
+        else
+        {
+          if (item.IsStrongEncrypted())
+          {
+            CStrongCryptoField f;
+            bool finded = false;
+            if (item.CentralExtra.GetStrongCryptoField(f))
+            {
+              for (int i = 0; i < sizeof(g_StrongCryptoPairs) / sizeof(g_StrongCryptoPairs[0]); i++)
+              {
+                const CStrongCryptoPair &pair = g_StrongCryptoPairs[i];
+                if (f.AlgId == pair.Id)
+                {
+                  method += pair.Name;
+                  finded = true;
+                  break;
+                }
+              }
+            }
+            if (!finded)
+              method += kStrongCryptoMethod;
+          }
+          else
+            method += kZipCryptoMethod;
+          method += ' ';
+        }
+      }
+      if (methodId < sizeof(kMethods) / sizeof(kMethods[0]))
+        method += kMethods[methodId];
+      else switch (methodId)
+      {
+        case NFileHeader::NCompressionMethod::kLZMA:
+          method += kLZMAMethod;
+          if (item.IsLzmaEOS())
+            method += ":EOS";
+          break;
+        case NFileHeader::NCompressionMethod::kBZip2: method += kBZip2Method; break;
+        case NFileHeader::NCompressionMethod::kJpeg: method += kJpegMethod; break;
+        case NFileHeader::NCompressionMethod::kWavPack: method += kWavPackMethod; break;
+        case NFileHeader::NCompressionMethod::kPPMd: method += kPPMdMethod; break;
+        default:
+        {
+          char s[32];
+          ConvertUInt64ToString(methodId, s);
+          method += s;
+        }
+      }
+      prop = method;
+      break;
+    }
+    case kpidHostOS:
+      prop = (item.MadeByVersion.HostOS < sizeof(kHostOS) / sizeof(kHostOS[0])) ?
+        (kHostOS[item.MadeByVersion.HostOS]) : kUnknownOS;
+      break;
+    case kpidUnpackVer:
+      prop = (UInt32)item.ExtractVersion.Version;
+      break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+class CProgressImp: public CProgressVirt
+{
+  CMyComPtr<IArchiveOpenCallback> _callback;
+public:
+  STDMETHOD(SetTotal)(UInt64 numFiles);
+  STDMETHOD(SetCompleted)(UInt64 numFiles);
+  CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {}
+};
+
+STDMETHODIMP CProgressImp::SetTotal(UInt64 numFiles)
+{
+  if (_callback)
+    return _callback->SetTotal(&numFiles, NULL);
+  return S_OK;
+}
+
+STDMETHODIMP CProgressImp::SetCompleted(UInt64 numFiles)
+{
+  if (_callback)
+    return _callback->SetCompleted(&numFiles, NULL);
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *inStream,
+    const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback)
+{
+  COM_TRY_BEGIN
+  try
+  {
+    Close();
+    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
+    RINOK(m_Archive.Open(inStream, maxCheckStartPosition));
+    CProgressImp progressImp(callback);
+    return m_Archive.ReadHeaders(m_Items, &progressImp);
+  }
+  catch(const CInArchiveException &) { Close(); return S_FALSE; }
+  catch(...) { Close(); throw; }
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  m_Items.Clear();
+  m_Archive.Close();
+  return S_OK;
+}
+
+//////////////////////////////////////
+// CHandler::DecompressItems
+
+class CLzmaDecoder:
+  public ICompressCoder,
+  public CMyUnknownImp
+{
+  NCompress::NLzma::CDecoder *DecoderSpec;
+  CMyComPtr<ICompressCoder> Decoder;
+public:
+  CLzmaDecoder();
+  STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+
+  MY_UNKNOWN_IMP
+};
+
+CLzmaDecoder::CLzmaDecoder()
+{
+  DecoderSpec = new NCompress::NLzma::CDecoder;
+  Decoder = DecoderSpec;
+}
+
+HRESULT CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
+    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
+{
+  Byte buf[9];
+  RINOK(ReadStream_FALSE(inStream, buf, 9));
+  if (buf[2] != 5 || buf[3] != 0)
+    return E_NOTIMPL;
+  RINOK(DecoderSpec->SetDecoderProperties2(buf + 4, 5));
+  return Decoder->Code(inStream, outStream, NULL, outSize, progress);
+}
+
+struct CMethodItem
+{
+  UInt16 ZipMethod;
+  CMyComPtr<ICompressCoder> Coder;
+};
+
+class CZipDecoder
+{
+  NCrypto::NZip::CDecoder *_zipCryptoDecoderSpec;
+  NCrypto::NZipStrong::CDecoder *_pkAesDecoderSpec;
+  NCrypto::NWzAes::CDecoder *_wzAesDecoderSpec;
+
+  CMyComPtr<ICompressFilter> _zipCryptoDecoder;
+  CMyComPtr<ICompressFilter> _pkAesDecoder;
+  CMyComPtr<ICompressFilter> _wzAesDecoder;
+
+  CFilterCoder *filterStreamSpec;
+  CMyComPtr<ISequentialInStream> filterStream;
+  CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+  CObjectVector<CMethodItem> methodItems;
+
+public:
+  CZipDecoder():
+      _zipCryptoDecoderSpec(0),
+      _pkAesDecoderSpec(0),
+      _wzAesDecoderSpec(0),
+      filterStreamSpec(0) {}
+
+  HRESULT Decode(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    CInArchive &archive, const CItemEx &item,
+    ISequentialOutStream *realOutStream,
+    IArchiveExtractCallback *extractCallback,
+    ICompressProgressInfo *compressProgress,
+    UInt32 numThreads, Int32 &res);
+};
+
+HRESULT CZipDecoder::Decode(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    CInArchive &archive, const CItemEx &item,
+    ISequentialOutStream *realOutStream,
+    IArchiveExtractCallback *extractCallback,
+    ICompressProgressInfo *compressProgress,
+    UInt32 numThreads, Int32 &res)
+{
+  res = NExtract::NOperationResult::kDataError;
+  CInStreamReleaser inStreamReleaser;
+
+  bool needCRC = true;
+  bool wzAesMode = false;
+  bool pkAesMode = false;
+  UInt16 methodId = item.CompressionMethod;
+  if (item.IsEncrypted())
+  {
+    if (item.IsStrongEncrypted())
+    {
+      CStrongCryptoField f;
+      if (item.CentralExtra.GetStrongCryptoField(f))
+      {
+        pkAesMode = true;
+      }
+      if (!pkAesMode)
+      {
+        res = NExtract::NOperationResult::kUnSupportedMethod;
+        return S_OK;
+      }
+    }
+    if (methodId == NFileHeader::NCompressionMethod::kWzAES)
+    {
+      CWzAesExtraField aesField;
+      if (item.CentralExtra.GetWzAesField(aesField))
+      {
+        wzAesMode = true;
+        needCRC = aesField.NeedCrc();
+      }
+    }
+  }
+    
+  COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
+  CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
+  outStreamSpec->SetStream(realOutStream);
+  outStreamSpec->Init(needCRC);
+  
+  UInt64 authenticationPos;
+  
+  CMyComPtr<ISequentialInStream> inStream;
+  {
+    UInt64 packSize = item.PackSize;
+    if (wzAesMode)
+    {
+      if (packSize < NCrypto::NWzAes::kMacSize)
+        return S_OK;
+      packSize -= NCrypto::NWzAes::kMacSize;
+    }
+    UInt64 dataPos = item.GetDataPosition();
+    inStream.Attach(archive.CreateLimitedStream(dataPos, packSize));
+    authenticationPos = dataPos + packSize;
+  }
+  
+  CMyComPtr<ICompressFilter> cryptoFilter;
+  if (item.IsEncrypted())
+  {
+    if (wzAesMode)
+    {
+      CWzAesExtraField aesField;
+      if (!item.CentralExtra.GetWzAesField(aesField))
+        return S_OK;
+      methodId = aesField.Method;
+      if (!_wzAesDecoder)
+      {
+        _wzAesDecoderSpec = new NCrypto::NWzAes::CDecoder;
+        _wzAesDecoder = _wzAesDecoderSpec;
+      }
+      cryptoFilter = _wzAesDecoder;
+      Byte properties = aesField.Strength;
+      RINOK(_wzAesDecoderSpec->SetDecoderProperties2(&properties, 1));
+    }
+    else if (pkAesMode)
+    {
+      if (!_pkAesDecoder)
+      {
+        _pkAesDecoderSpec = new NCrypto::NZipStrong::CDecoder;
+        _pkAesDecoder = _pkAesDecoderSpec;
+      }
+      cryptoFilter = _pkAesDecoder;
+    }
+    else
+    {
+      if (!_zipCryptoDecoder)
+      {
+        _zipCryptoDecoderSpec = new NCrypto::NZip::CDecoder;
+        _zipCryptoDecoder = _zipCryptoDecoderSpec;
+      }
+      cryptoFilter = _zipCryptoDecoder;
+    }
+    CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
+    RINOK(cryptoFilter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
+    
+    if (!getTextPassword)
+      extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
+    
+    if (getTextPassword)
+    {
+      CMyComBSTR password;
+      RINOK(getTextPassword->CryptoGetTextPassword(&password));
+      AString charPassword;
+      if (wzAesMode || pkAesMode)
+      {
+        charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_ACP);
+        /*
+        for (int i = 0;; i++)
+        {
+          wchar_t c = password[i];
+          if (c == 0)
+            break;
+          if (c >= 0x80)
+          {
+            res = NExtract::NOperationResult::kDataError;
+            return S_OK;
+          }
+          charPassword += (char)c;
+        }
+        */
+      }
+      else
+      {
+        // we use OEM. WinZip/Windows probably use ANSI for some files
+        charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP);
+      }
+      HRESULT result = cryptoSetPassword->CryptoSetPassword(
+        (const Byte *)(const char *)charPassword, charPassword.Length());
+      if (result != S_OK)
+        return S_OK;
+    }
+    else
+    {
+      RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
+    }
+  }
+  
+  int m;
+  for (m = 0; m < methodItems.Size(); m++)
+    if (methodItems[m].ZipMethod == methodId)
+      break;
+
+  if (m == methodItems.Size())
+  {
+    CMethodItem mi;
+    mi.ZipMethod = methodId;
+    if (methodId == NFileHeader::NCompressionMethod::kStored)
+      mi.Coder = new NCompress::CCopyCoder;
+    else if (methodId == NFileHeader::NCompressionMethod::kShrunk)
+      mi.Coder = new NCompress::NShrink::CDecoder;
+    else if (methodId == NFileHeader::NCompressionMethod::kImploded)
+      mi.Coder = new NCompress::NImplode::NDecoder::CCoder;
+    else if (methodId == NFileHeader::NCompressionMethod::kLZMA)
+      mi.Coder = new CLzmaDecoder;
+    else if (methodId == NFileHeader::NCompressionMethod::kPPMd)
+      mi.Coder = new NCompress::NPpmdZip::CDecoder(true);
+    else
+    {
+      CMethodId szMethodID;
+      if (methodId == NFileHeader::NCompressionMethod::kBZip2)
+        szMethodID = kMethodId_BZip2;
+      else
+      {
+        if (methodId > 0xFF)
+        {
+          res = NExtract::NOperationResult::kUnSupportedMethod;
+          return S_OK;
+        }
+        szMethodID = kMethodId_ZipBase + (Byte)methodId;
+      }
+
+      RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS szMethodID, mi.Coder, false));
+
+      if (mi.Coder == 0)
+      {
+        res = NExtract::NOperationResult::kUnSupportedMethod;
+        return S_OK;
+      }
+    }
+    m = methodItems.Add(mi);
+  }
+  ICompressCoder *coder = methodItems[m].Coder;
+  
+  {
+    CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
+    coder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
+    if (setDecoderProperties)
+    {
+      Byte properties = (Byte)item.Flags;
+      RINOK(setDecoderProperties->SetDecoderProperties2(&properties, 1));
+    }
+  }
+  
+  #ifndef _7ZIP_ST
+  {
+    CMyComPtr<ICompressSetCoderMt> setCoderMt;
+    coder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
+    if (setCoderMt)
+    {
+      RINOK(setCoderMt->SetNumberOfThreads(numThreads));
+    }
+  }
+  #endif
+  
+  {
+    HRESULT result = S_OK;
+    CMyComPtr<ISequentialInStream> inStreamNew;
+    if (item.IsEncrypted())
+    {
+      if (!filterStream)
+      {
+        filterStreamSpec = new CFilterCoder;
+        filterStream = filterStreamSpec;
+      }
+      filterStreamSpec->Filter = cryptoFilter;
+      if (wzAesMode)
+      {
+        result = _wzAesDecoderSpec->ReadHeader(inStream);
+      }
+      else if (pkAesMode)
+      {
+        result =_pkAesDecoderSpec->ReadHeader(inStream, item.FileCRC, item.UnPackSize);
+        if (result == S_OK)
+        {
+          bool passwOK;
+          result = _pkAesDecoderSpec->CheckPassword(passwOK);
+          if (result == S_OK && !passwOK)
+            result = S_FALSE;
+        }
+      }
+      else
+      {
+        result = _zipCryptoDecoderSpec->ReadHeader(inStream);
+      }
+
+      if (result == S_OK)
+      {
+        RINOK(filterStreamSpec->SetInStream(inStream));
+        inStreamReleaser.FilterCoder = filterStreamSpec;
+        inStreamNew = filterStream;
+        if (wzAesMode)
+        {
+          if (!_wzAesDecoderSpec->CheckPasswordVerifyCode())
+            result = S_FALSE;
+        }
+      }
+    }
+    else
+      inStreamNew = inStream;
+    if (result == S_OK)
+      result = coder->Code(inStreamNew, outStream, NULL, &item.UnPackSize, compressProgress);
+    if (result == S_FALSE)
+      return S_OK;
+    if (result == E_NOTIMPL)
+    {
+      res = NExtract::NOperationResult::kUnSupportedMethod;
+      return S_OK;
+    }
+
+    RINOK(result);
+  }
+  bool crcOK = true;
+  bool authOk = true;
+  if (needCRC)
+    crcOK = (outStreamSpec->GetCRC() == item.FileCRC);
+  if (wzAesMode)
+  {
+    inStream.Attach(archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAes::kMacSize));
+    if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK)
+      authOk = false;
+  }
+  
+  res = ((crcOK && authOk) ?
+    NExtract::NOperationResult::kOK :
+    NExtract::NOperationResult::kCRCError);
+  return S_OK;
+}
+
+
+STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+    Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+  COM_TRY_BEGIN
+  CZipDecoder myDecoder;
+  UInt64 totalUnPacked = 0, totalPacked = 0;
+  bool allFilesMode = (numItems == (UInt32)-1);
+  if (allFilesMode)
+    numItems = m_Items.Size();
+  if(numItems == 0)
+    return S_OK;
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+  {
+    const CItemEx &item = m_Items[allFilesMode ? i : indices[i]];
+    totalUnPacked += item.UnPackSize;
+    totalPacked += item.PackSize;
+  }
+  RINOK(extractCallback->SetTotal(totalUnPacked));
+
+  UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0;
+  UInt64 currentItemUnPacked, currentItemPacked;
+  
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  for (i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked,
+      currentTotalPacked += currentItemPacked)
+  {
+    currentItemUnPacked = 0;
+    currentItemPacked = 0;
+
+    lps->InSize = currentTotalPacked;
+    lps->OutSize = currentTotalUnPacked;
+    RINOK(lps->SetCur());
+
+    CMyComPtr<ISequentialOutStream> realOutStream;
+    Int32 askMode = testMode ?
+        NExtract::NAskMode::kTest :
+        NExtract::NAskMode::kExtract;
+    Int32 index = allFilesMode ? i : indices[i];
+
+    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+    CItemEx item = m_Items[index];
+    if (!item.FromLocal)
+    {
+      HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item);
+      if (res == S_FALSE)
+      {
+        if (item.IsDir() || realOutStream || testMode)
+        {
+          RINOK(extractCallback->PrepareOperation(askMode));
+          realOutStream.Release();
+          RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
+        }
+        continue;
+      }
+      RINOK(res);
+    }
+
+    if (item.IsDir() || item.IgnoreItem())
+    {
+      // if (!testMode)
+      {
+        RINOK(extractCallback->PrepareOperation(askMode));
+        realOutStream.Release();
+        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
+      }
+      continue;
+    }
+
+    currentItemUnPacked = item.UnPackSize;
+    currentItemPacked = item.PackSize;
+
+    if (!testMode && !realOutStream)
+      continue;
+
+    RINOK(extractCallback->PrepareOperation(askMode));
+
+    Int32 res;
+    RINOK(myDecoder.Decode(
+        EXTERNAL_CODECS_VARS
+        m_Archive, item, realOutStream, extractCallback,
+        progress, _numThreads, res));
+    realOutStream.Release();
+    
+    RINOK(extractCallback->SetOperationResult(res))
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+IMPL_ISetCompressCodecsInfo
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHandler.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHandler.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHandler.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHandler.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,101 @@
+// Zip/Handler.h
+
+#ifndef __ZIP_HANDLER_H
+#define __ZIP_HANDLER_H
+
+#include "Common/DynamicBuffer.h"
+#include "../../ICoder.h"
+#include "../IArchive.h"
+
+#include "../../Common/CreateCoder.h"
+
+#include "ZipIn.h"
+#include "ZipCompressionMode.h"
+
+#ifndef _7ZIP_ST
+#include "../../../Windows/System.h"
+#endif
+
+namespace NArchive {
+namespace NZip {
+
+class CHandler:
+  public IInArchive,
+  public IOutArchive,
+  public ISetProperties,
+  PUBLIC_ISetCompressCodecsInfo
+  public CMyUnknownImp
+{
+public:
+  MY_QUERYINTERFACE_BEGIN2(IInArchive)
+  MY_QUERYINTERFACE_ENTRY(IOutArchive)
+  MY_QUERYINTERFACE_ENTRY(ISetProperties)
+  QUERY_ENTRY_ISetCompressCodecsInfo
+  MY_QUERYINTERFACE_END
+  MY_ADDREF_RELEASE
+
+  INTERFACE_IInArchive(;)
+  INTERFACE_IOutArchive(;)
+
+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties);
+
+  DECL_ISetCompressCodecsInfo
+
+  CHandler();
+private:
+  CObjectVector<CItemEx> m_Items;
+  CInArchive m_Archive;
+
+  int m_Level;
+  int m_MainMethod;
+  UInt32 m_DicSize;
+  UInt32 m_Algo;
+  UInt32 m_NumPasses;
+  UInt32 m_NumFastBytes;
+  UInt32 m_NumMatchFinderCycles;
+  UInt32 m_MemSize;
+  UInt32 m_Order;
+
+  bool m_NumMatchFinderCyclesDefined;
+
+  bool m_ForceAesMode;
+  bool m_IsAesMode;
+  Byte m_AesKeyMode;
+
+  bool m_WriteNtfsTimeExtra;
+  bool m_ForceLocal;
+  bool m_ForceUtf8;
+
+  #ifndef _7ZIP_ST
+  UInt32 _numThreads;
+  #endif
+
+  DECL_EXTERNAL_CODECS_VARS
+
+  void InitMethodProperties()
+  {
+    m_Level = -1;
+    m_MainMethod = -1;
+    m_Algo =
+    m_DicSize =
+    m_NumPasses =
+    m_NumFastBytes =
+    m_Order =
+    m_MemSize =
+    m_NumMatchFinderCycles = 0xFFFFFFFF;
+    m_NumMatchFinderCyclesDefined = false;
+    m_ForceAesMode = false;
+    m_IsAesMode = false;
+    m_AesKeyMode = 3; // aes-256
+    m_WriteNtfsTimeExtra = false;
+    m_ForceLocal = false;
+    m_ForceUtf8 = false;
+    #ifndef _7ZIP_ST
+    _numThreads = NWindows::NSystem::GetNumberOfProcessors();;
+    #endif
+  }
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,537 @@
+// ZipHandlerOut.cpp
+
+#include "StdAfx.h"
+
+#include "Common/ComTry.h"
+#include "Common/StringConvert.h"
+#include "Common/StringToInt.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../../IPassword.h"
+
+#include "../../Common/OutBuffer.h"
+
+#include "../../Crypto/WzAes.h"
+
+#include "../Common/ItemNameUtils.h"
+#include "../Common/ParseProperties.h"
+
+#include "ZipHandler.h"
+#include "ZipUpdate.h"
+
+using namespace NWindows;
+using namespace NCOM;
+using namespace NTime;
+
+namespace NArchive {
+namespace NZip {
+
+static const UInt32 kLzAlgoX1 = 0;
+static const UInt32 kLzAlgoX5 = 1;
+
+static const UInt32 kDeflateNumPassesX1  = 1;
+static const UInt32 kDeflateNumPassesX7  = 3;
+static const UInt32 kDeflateNumPassesX9  = 10;
+
+static const UInt32 kDeflateNumFastBytesX1 = 32;
+static const UInt32 kDeflateNumFastBytesX7 = 64;
+static const UInt32 kDeflateNumFastBytesX9 = 128;
+
+static const wchar_t *kLzmaMatchFinderX1 = L"HC4";
+static const wchar_t *kLzmaMatchFinderX5 = L"BT4";
+
+static const UInt32 kLzmaNumFastBytesX1 = 32;
+static const UInt32 kLzmaNumFastBytesX7 = 64;
+
+static const UInt32 kLzmaDicSizeX1 = 1 << 16;
+static const UInt32 kLzmaDicSizeX3 = 1 << 20;
+static const UInt32 kLzmaDicSizeX5 = 1 << 24;
+static const UInt32 kLzmaDicSizeX7 = 1 << 25;
+static const UInt32 kLzmaDicSizeX9 = 1 << 26;
+
+static const UInt32 kBZip2NumPassesX1 = 1;
+static const UInt32 kBZip2NumPassesX7 = 2;
+static const UInt32 kBZip2NumPassesX9 = 7;
+
+static const UInt32 kBZip2DicSizeX1 = 100000;
+static const UInt32 kBZip2DicSizeX3 = 500000;
+static const UInt32 kBZip2DicSizeX5 = 900000;
+
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
+{
+  *timeType = NFileTimeType::kDOS;
+  return S_OK;
+}
+
+static bool IsAsciiString(const UString &s)
+{
+  for (int i = 0; i < s.Length(); i++)
+  {
+    wchar_t c = s[i];
+    if (c < 0x20 || c > 0x7F)
+      return false;
+  }
+  return true;
+}
+
+#define COM_TRY_BEGIN2 try {
+#define COM_TRY_END2 } \
+catch(const CSystemException &e) { return e.ErrorCode; } \
+catch(...) { return E_OUTOFMEMORY; }
+
+static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propID, FILETIME &filetime)
+{
+  filetime.dwHighDateTime = filetime.dwLowDateTime = 0;
+  NCOM::CPropVariant prop;
+  RINOK(callback->GetProperty(index, propID, &prop));
+  if (prop.vt == VT_FILETIME)
+    filetime = prop.filetime;
+  else if (prop.vt != VT_EMPTY)
+    return E_INVALIDARG;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+    IArchiveUpdateCallback *callback)
+{
+  COM_TRY_BEGIN2
+  CObjectVector<CUpdateItem> updateItems;
+  bool thereAreAesUpdates = false;
+  for (UInt32 i = 0; i < numItems; i++)
+  {
+    CUpdateItem ui;
+    Int32 newData;
+    Int32 newProperties;
+    UInt32 indexInArchive;
+    if (!callback)
+      return E_FAIL;
+    RINOK(callback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive));
+    ui.NewProperties = IntToBool(newProperties);
+    ui.NewData = IntToBool(newData);
+    ui.IndexInArchive = indexInArchive;
+    ui.IndexInClient = i;
+    bool existInArchive = (indexInArchive != (UInt32)-1);
+    if (existInArchive && newData)
+      if (m_Items[indexInArchive].IsAesEncrypted())
+        thereAreAesUpdates = true;
+
+    if (IntToBool(newProperties))
+    {
+      UString name;
+      {
+        NCOM::CPropVariant prop;
+        RINOK(callback->GetProperty(i, kpidAttrib, &prop));
+        if (prop.vt == VT_EMPTY)
+          ui.Attributes = 0;
+        else if (prop.vt != VT_UI4)
+          return E_INVALIDARG;
+        else
+          ui.Attributes = prop.ulVal;
+      }
+
+      {
+        NCOM::CPropVariant prop;
+        RINOK(callback->GetProperty(i, kpidPath, &prop));
+        if (prop.vt == VT_EMPTY)
+          name.Empty();
+        else if (prop.vt != VT_BSTR)
+          return E_INVALIDARG;
+        else
+          name = prop.bstrVal;
+      }
+      {
+        NCOM::CPropVariant prop;
+        RINOK(callback->GetProperty(i, kpidIsDir, &prop));
+        if (prop.vt == VT_EMPTY)
+          ui.IsDir = false;
+        else if (prop.vt != VT_BOOL)
+          return E_INVALIDARG;
+        else
+          ui.IsDir = (prop.boolVal != VARIANT_FALSE);
+      }
+
+      {
+        CPropVariant prop;
+        RINOK(callback->GetProperty(i, kpidTimeType, &prop));
+        if (prop.vt == VT_UI4)
+          ui.NtfsTimeIsDefined = (prop.ulVal == NFileTimeType::kWindows);
+        else
+          ui.NtfsTimeIsDefined = m_WriteNtfsTimeExtra;
+      }
+      RINOK(GetTime(callback, i, kpidMTime, ui.NtfsMTime));
+      RINOK(GetTime(callback, i, kpidATime, ui.NtfsATime));
+      RINOK(GetTime(callback, i, kpidCTime, ui.NtfsCTime));
+
+      {
+        FILETIME localFileTime = { 0, 0 };
+        if (ui.NtfsMTime.dwHighDateTime != 0 ||
+            ui.NtfsMTime.dwLowDateTime != 0)
+          if (!FileTimeToLocalFileTime(&ui.NtfsMTime, &localFileTime))
+            return E_INVALIDARG;
+        FileTimeToDosTime(localFileTime, ui.Time);
+      }
+
+      name = NItemName::MakeLegalName(name);
+      bool needSlash = ui.IsDir;
+      const wchar_t kSlash = L'/';
+      if (!name.IsEmpty())
+      {
+        if (name[name.Length() - 1] == kSlash)
+        {
+          if (!ui.IsDir)
+            return E_INVALIDARG;
+          needSlash = false;
+        }
+      }
+      if (needSlash)
+        name += kSlash;
+
+      bool tryUtf8 = true;
+      if (m_ForceLocal || !m_ForceUtf8)
+      {
+#ifdef _WIN32
+        bool defaultCharWasUsed;
+        ui.Name = UnicodeStringToMultiByte(name, CP_OEMCP, '_', defaultCharWasUsed);
+        tryUtf8 = (!m_ForceLocal && (defaultCharWasUsed ||
+          MultiByteToUnicodeString(ui.Name, CP_OEMCP) != name));
+#else
+	// FIXME
+        ui.Name = UnicodeStringToMultiByte(name, CP_OEMCP);
+        tryUtf8 = (!m_ForceLocal);
+#endif
+      }
+
+      if (tryUtf8)
+      {
+        int i;
+        for (i = 0; i < name.Length() && (unsigned)name[i] < 0x80; i++);
+        ui.IsUtf8 = (i != name.Length());
+        if (!ConvertUnicodeToUTF8(name, ui.Name))
+          return E_INVALIDARG;
+      }
+
+      if (ui.Name.Length() >= (1 << 16))
+        return E_INVALIDARG;
+
+      ui.IndexInClient = i;
+      /*
+      if (existInArchive)
+      {
+        const CItemEx &itemInfo = m_Items[indexInArchive];
+        // ui.Commented = itemInfo.IsCommented();
+        ui.Commented = false;
+        if (ui.Commented)
+        {
+          ui.CommentRange.Position = itemInfo.GetCommentPosition();
+          ui.CommentRange.Size  = itemInfo.CommentSize;
+        }
+      }
+      else
+        ui.Commented = false;
+      */
+    }
+    if (IntToBool(newData))
+    {
+      UInt64 size;
+      {
+        NCOM::CPropVariant prop;
+        RINOK(callback->GetProperty(i, kpidSize, &prop));
+        if (prop.vt != VT_UI8)
+          return E_INVALIDARG;
+        size = prop.uhVal.QuadPart;
+      }
+      ui.Size = size;
+    }
+    updateItems.Add(ui);
+  }
+
+  CMyComPtr<ICryptoGetTextPassword2> getTextPassword;
+  {
+    CMyComPtr<IArchiveUpdateCallback> udateCallBack2(callback);
+    udateCallBack2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword);
+  }
+  CCompressionMethodMode options;
+
+  if (getTextPassword)
+  {
+    CMyComBSTR password;
+    Int32 passwordIsDefined;
+    RINOK(getTextPassword->CryptoGetTextPassword2(&passwordIsDefined, &password));
+    options.PasswordIsDefined = IntToBool(passwordIsDefined);
+    if (options.PasswordIsDefined)
+    {
+      options.IsAesMode = (m_ForceAesMode ? m_IsAesMode : thereAreAesUpdates);
+      options.AesKeyMode = m_AesKeyMode;
+
+      if (!IsAsciiString((const wchar_t *)password))
+        return E_INVALIDARG;
+      if (options.IsAesMode)
+      {
+        if (options.Password.Length() > NCrypto::NWzAes::kPasswordSizeMax)
+          return E_INVALIDARG;
+      }
+      options.Password = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP);
+    }
+  }
+  else
+    options.PasswordIsDefined = false;
+
+  int level = m_Level;
+  if (level < 0)
+    level = 5;
+  
+  Byte mainMethod;
+  if (m_MainMethod < 0)
+    mainMethod = (Byte)(((level == 0) ?
+        NFileHeader::NCompressionMethod::kStored :
+        NFileHeader::NCompressionMethod::kDeflated));
+  else
+    mainMethod = (Byte)m_MainMethod;
+  options.MethodSequence.Add(mainMethod);
+  if (mainMethod != NFileHeader::NCompressionMethod::kStored)
+    options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStored);
+  bool isDeflate = (mainMethod == NFileHeader::NCompressionMethod::kDeflated) ||
+      (mainMethod == NFileHeader::NCompressionMethod::kDeflated64);
+  bool isLZMA = (mainMethod == NFileHeader::NCompressionMethod::kLZMA);
+  bool isLz = (isLZMA || isDeflate);
+  options.NumPasses = m_NumPasses;
+  options.DicSize = m_DicSize;
+  options.NumFastBytes = m_NumFastBytes;
+  options.NumMatchFinderCycles = m_NumMatchFinderCycles;
+  options.NumMatchFinderCyclesDefined = m_NumMatchFinderCyclesDefined;
+  options.Algo = m_Algo;
+  options.MemSize = m_MemSize;
+  options.Order = m_Order;
+  #ifndef _7ZIP_ST
+  options.NumThreads = _numThreads;
+  #endif
+  if (isLz)
+  {
+    if (isDeflate)
+    {
+      if (options.NumPasses == 0xFFFFFFFF)
+        options.NumPasses = (level >= 9 ? kDeflateNumPassesX9 :
+                            (level >= 7 ? kDeflateNumPassesX7 :
+                                          kDeflateNumPassesX1));
+      if (options.NumFastBytes == 0xFFFFFFFF)
+        options.NumFastBytes = (level >= 9 ? kDeflateNumFastBytesX9 :
+                               (level >= 7 ? kDeflateNumFastBytesX7 :
+                                             kDeflateNumFastBytesX1));
+    }
+    else if (isLZMA)
+    {
+      if (options.DicSize == 0xFFFFFFFF)
+        options.DicSize =
+          (level >= 9 ? kLzmaDicSizeX9 :
+          (level >= 7 ? kLzmaDicSizeX7 :
+          (level >= 5 ? kLzmaDicSizeX5 :
+          (level >= 3 ? kLzmaDicSizeX3 :
+                        kLzmaDicSizeX1))));
+
+      if (options.NumFastBytes == 0xFFFFFFFF)
+        options.NumFastBytes = (level >= 7 ? kLzmaNumFastBytesX7 :
+                                             kLzmaNumFastBytesX1);
+
+      options.MatchFinder =
+        (level >= 5 ? kLzmaMatchFinderX5 :
+                      kLzmaMatchFinderX1);
+    }
+
+    if (options.Algo == 0xFFFFFFFF)
+        options.Algo = (level >= 5 ? kLzAlgoX5 :
+                                     kLzAlgoX1);
+  }
+  if (mainMethod == NFileHeader::NCompressionMethod::kBZip2)
+  {
+    if (options.NumPasses == 0xFFFFFFFF)
+      options.NumPasses = (level >= 9 ? kBZip2NumPassesX9 :
+                          (level >= 7 ? kBZip2NumPassesX7 :
+                                        kBZip2NumPassesX1));
+    if (options.DicSize == 0xFFFFFFFF)
+      options.DicSize = (level >= 5 ? kBZip2DicSizeX5 :
+                        (level >= 3 ? kBZip2DicSizeX3 :
+                                      kBZip2DicSizeX1));
+  }
+  if (mainMethod == NFileHeader::NCompressionMethod::kPPMd)
+  {
+    int level2 = level;
+    if (level2 < 1) level2 = 1;
+    if (level2 > 9) level2 = 9;
+
+    if (options.MemSize == 0xFFFFFFFF)
+      options.MemSize = (1 << (19 + (level2 > 8 ? 8 : level2)));
+
+    if (options.Order == 0xFFFFFFFF)
+      options.Order = 3 + level2;
+
+    if (options.Algo == 0xFFFFFFFF)
+      options.Algo = (level2 >= 7 ? 1 : 0);
+  }
+
+  return Update(
+      EXTERNAL_CODECS_VARS
+      m_Items, updateItems, outStream,
+      m_Archive.IsOpen() ? &m_Archive : NULL, &options, callback);
+  COM_TRY_END2
+}
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
+{
+  #ifndef _7ZIP_ST
+  const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
+  _numThreads = numProcessors;
+  #endif
+  InitMethodProperties();
+  for (int i = 0; i < numProperties; i++)
+  {
+    UString name = UString(names[i]);
+    name.MakeUpper();
+    if (name.IsEmpty())
+      return E_INVALIDARG;
+
+    const PROPVARIANT &prop = values[i];
+
+    if (name[0] == L'X')
+    {
+      UInt32 level = 9;
+      RINOK(ParsePropValue(name.Mid(1), prop, level));
+      m_Level = level;
+      continue;
+    }
+    else if (name == L"M")
+    {
+      if (prop.vt == VT_BSTR)
+      {
+        UString m = prop.bstrVal;
+        m.MakeUpper();
+        if (m == L"COPY") m_MainMethod = NFileHeader::NCompressionMethod::kStored;
+        else if (m == L"DEFLATE") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated;
+        else if (m == L"DEFLATE64") m_MainMethod = NFileHeader::NCompressionMethod::kDeflated64;
+        else if (m == L"BZIP2") m_MainMethod = NFileHeader::NCompressionMethod::kBZip2;
+        else if (m == L"LZMA") m_MainMethod = NFileHeader::NCompressionMethod::kLZMA;
+        else if (m == L"PPMD") m_MainMethod = NFileHeader::NCompressionMethod::kPPMd;
+        else return E_INVALIDARG;
+      }
+      else if (prop.vt == VT_UI4)
+      {
+        switch(prop.ulVal)
+        {
+          case NFileHeader::NCompressionMethod::kStored:
+          case NFileHeader::NCompressionMethod::kDeflated:
+          case NFileHeader::NCompressionMethod::kDeflated64:
+          case NFileHeader::NCompressionMethod::kBZip2:
+          case NFileHeader::NCompressionMethod::kLZMA:
+            m_MainMethod = (Byte)prop.ulVal;
+            break;
+          default:
+            return E_INVALIDARG;
+        }
+      }
+      else
+        return E_INVALIDARG;
+    }
+    else if (name.Left(2) == L"EM")
+    {
+      if (prop.vt == VT_BSTR)
+      {
+        UString valueString = prop.bstrVal;
+        valueString.MakeUpper();
+        if (valueString.Left(3) == L"AES")
+        {
+          valueString = valueString.Mid(3);
+          if (valueString == L"128")
+            m_AesKeyMode = 1;
+          else if (valueString == L"192")
+            m_AesKeyMode = 2;
+          else if (valueString == L"256" || valueString.IsEmpty())
+            m_AesKeyMode = 3;
+          else
+            return E_INVALIDARG;
+          m_IsAesMode = true;
+          m_ForceAesMode = true;
+        }
+        else if (valueString == L"ZIPCRYPTO")
+        {
+          m_IsAesMode = false;
+          m_ForceAesMode = true;
+        }
+        else
+          return E_INVALIDARG;
+      }
+      else
+        return E_INVALIDARG;
+    }
+    else if (name[0] == L'D')
+    {
+      UInt32 dicSize = kBZip2DicSizeX5;
+      RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize));
+      m_DicSize = dicSize;
+    }
+    else if (name.Left(3) == L"MEM")
+    {
+      UInt32 memSize = 1 << 24;
+      RINOK(ParsePropDictionaryValue(name.Mid(3), prop, memSize));
+      m_MemSize = memSize;
+    }
+    else if (name[0] == L'O')
+    {
+      UInt32 order = 8;
+      RINOK(ParsePropValue(name.Mid(1), prop, order));
+      m_Order = order;
+    }
+    else if (name.Left(4) == L"PASS")
+    {
+      UInt32 num = kDeflateNumPassesX9;
+      RINOK(ParsePropValue(name.Mid(4), prop, num));
+      m_NumPasses = num;
+    }
+    else if (name.Left(2) == L"FB")
+    {
+      UInt32 num = kDeflateNumFastBytesX9;
+      RINOK(ParsePropValue(name.Mid(2), prop, num));
+      m_NumFastBytes = num;
+    }
+    else if (name.Left(2) == L"MC")
+    {
+      UInt32 num = 0xFFFFFFFF;
+      RINOK(ParsePropValue(name.Mid(2), prop, num));
+      m_NumMatchFinderCycles = num;
+      m_NumMatchFinderCyclesDefined = true;
+    }
+    else if (name.Left(2) == L"MT")
+    {
+      #ifndef _7ZIP_ST
+      RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads));
+      #endif
+    }
+    else if (name.Left(1) == L"A")
+    {
+      UInt32 num = kLzAlgoX5;
+      RINOK(ParsePropValue(name.Mid(1), prop, num));
+      m_Algo = num;
+    }
+    else if (name.CompareNoCase(L"TC") == 0)
+    {
+      RINOK(SetBoolProperty(m_WriteNtfsTimeExtra, prop));
+    }
+    else if (name.CompareNoCase(L"CL") == 0)
+    {
+      RINOK(SetBoolProperty(m_ForceLocal, prop));
+      if (m_ForceLocal)
+        m_ForceUtf8 = false;
+    }
+    else if (name.CompareNoCase(L"CU") == 0)
+    {
+      RINOK(SetBoolProperty(m_ForceUtf8, prop));
+      if (m_ForceUtf8)
+        m_ForceLocal = false;
+    }
+    else
+      return E_INVALIDARG;
+  }
+  return S_OK;
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHeader.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHeader.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHeader.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHeader.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,36 @@
+// Archive/Zip/Header.h
+
+#include "StdAfx.h"
+
+#include "ZipHeader.h"
+
+namespace NArchive {
+namespace NZip {
+
+namespace NSignature
+{
+  UInt32 kLocalFileHeader   = 0x04034B50 + 1;
+  UInt32 kDataDescriptor    = 0x08074B50 + 1;
+  UInt32 kCentralFileHeader = 0x02014B50 + 1;
+  UInt32 kEndOfCentralDir   = 0x06054B50 + 1;
+  UInt32 kZip64EndOfCentralDir   = 0x06064B50 + 1;
+  UInt32 kZip64EndOfCentralDirLocator   = 0x07064B50 + 1;
+  
+  class CMarkersInitializer
+  {
+  public:
+    CMarkersInitializer()
+    {
+      kLocalFileHeader--;
+      kDataDescriptor--;
+      kCentralFileHeader--;
+      kEndOfCentralDir--;
+      kZip64EndOfCentralDir--;
+      kZip64EndOfCentralDirLocator--;
+    }
+  };
+  static CMarkersInitializer g_MarkerInitializer;
+}
+
+}}
+

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHeader.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHeader.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHeader.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipHeader.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,284 @@
+// Archive/Zip/Header.h
+
+#ifndef __ARCHIVE_ZIP_HEADER_H
+#define __ARCHIVE_ZIP_HEADER_H
+
+#include "Common/Types.h"
+
+namespace NArchive {
+namespace NZip {
+
+namespace NSignature
+{
+  extern UInt32 kLocalFileHeader;
+  extern UInt32 kDataDescriptor;
+  extern UInt32 kCentralFileHeader;
+  extern UInt32 kEndOfCentralDir;
+  extern UInt32 kZip64EndOfCentralDir;
+  extern UInt32 kZip64EndOfCentralDirLocator;
+  
+  static const UInt32 kMarkerSize = 4;
+}
+
+const UInt32 kEcdSize = 22;
+const UInt32 kZip64EcdSize = 44;
+const UInt32 kZip64EcdLocatorSize = 20;
+/*
+struct CEndOfCentralDirectoryRecord
+{
+  UInt16 ThisDiskNumber;
+  UInt16 StartCentralDirectoryDiskNumber;
+  UInt16 NumEntriesInCentaralDirectoryOnThisDisk;
+  UInt16 NumEntriesInCentaralDirectory;
+  UInt32 CentralDirectorySize;
+  UInt32 CentralDirectoryStartOffset;
+  UInt16 CommentSize;
+};
+
+struct CEndOfCentralDirectoryRecordFull
+{
+  UInt32 Signature;
+  CEndOfCentralDirectoryRecord Header;
+};
+*/
+
+namespace NFileHeader
+{
+  /*
+  struct CVersion
+  {
+    Byte Version;
+    Byte HostOS;
+  };
+  */
+  
+  namespace NCompressionMethod
+  {
+    enum EType
+    {
+      kStored = 0,
+      kShrunk = 1,
+      kReduced1 = 2,
+      kReduced2 = 3,
+      kReduced3 = 4,
+      kReduced4 = 5,
+      kImploded = 6,
+      kReservedTokenizing = 7, // reserved for tokenizing
+      kDeflated = 8,
+      kDeflated64 = 9,
+      kPKImploding = 10,
+      
+      kBZip2 = 12,
+      kLZMA = 14,
+      kTerse = 18,
+      kLz77 = 19,
+      kJpeg = 0x60,
+      kWavPack = 0x61,
+      kPPMd = 0x62,
+      kWzAES = 0x63
+    };
+    const int kNumCompressionMethods = 11;
+    const Byte kMadeByProgramVersion = 63;
+    
+    const Byte kExtractVersion_Default = 10;
+    const Byte kExtractVersion_Dir = 20;
+    const Byte kExtractVersion_ZipCrypto = 20;
+    const Byte kExtractVersion_Deflate = 20;
+    const Byte kExtractVersion_Deflate64 = 21;
+    const Byte kExtractVersion_Zip64 = 45;
+    const Byte kExtractVersion_BZip2 = 46;
+    const Byte kExtractVersion_Aes = 51;
+    const Byte kExtractVersion_LZMA = 63;
+    const Byte kExtractVersion_PPMd = 63;
+    
+    // const Byte kSupportedVersion   = 20;
+  }
+
+  namespace NExtraID
+  {
+    enum
+    {
+      kZip64 = 0x01,
+      kNTFS = 0x0A,
+      kStrongEncrypt = 0x17,
+      kUnixTime = 0x5455,
+      kWzAES = 0x9901
+    };
+  }
+
+  namespace NNtfsExtra
+  {
+    const UInt16 kTagTime = 1;
+    enum
+    {
+      kMTime = 0,
+      kATime,
+      kCTime
+    };
+  }
+
+  namespace NUnixTime
+  {
+    enum
+    {
+      kMTime = 0,
+      kATime,
+      kCTime
+    };
+  }
+
+  const UInt32 kLocalBlockSize = 26;
+  /*
+  struct CLocalBlock
+  {
+    CVersion ExtractVersion;
+    
+    UInt16 Flags;
+    UInt16 CompressionMethod;
+    UInt32 Time;
+    UInt32 FileCRC;
+    UInt32 PackSize;
+    UInt32 UnPackSize;
+    UInt16 NameSize;
+    UInt16 ExtraSize;
+  };
+  */
+
+  const UInt32 kDataDescriptorSize = 16;
+  // const UInt32 kDataDescriptor64Size = 16 + 8;
+  /*
+  struct CDataDescriptor
+  {
+    UInt32 Signature;
+    UInt32 FileCRC;
+    UInt32 PackSize;
+    UInt32 UnPackSize;
+  };
+
+  struct CLocalBlockFull
+  {
+    UInt32 Signature;
+    CLocalBlock Header;
+  };
+  */
+  
+  const UInt32 kCentralBlockSize = 42;
+  /*
+  struct CBlock
+  {
+    CVersion MadeByVersion;
+    CVersion ExtractVersion;
+    UInt16 Flags;
+    UInt16 CompressionMethod;
+    UInt32 Time;
+    UInt32 FileCRC;
+    UInt32 PackSize;
+    UInt32 UnPackSize;
+    UInt16 NameSize;
+    UInt16 ExtraSize;
+    UInt16 CommentSize;
+    UInt16 DiskNumberStart;
+    UInt16 InternalAttributes;
+    UInt32 ExternalAttributes;
+    UInt32 LocalHeaderOffset;
+  };
+  
+  struct CBlockFull
+  {
+    UInt32 Signature;
+    CBlock Header;
+  };
+  */
+
+  namespace NFlags
+  {
+    const int kEncrypted = 1 << 0;
+    const int kLzmaEOS = 1 << 1;
+    const int kDescriptorUsedMask = 1 << 3;
+    const int kStrongEncrypted = 1 << 6;
+    const int kUtf8 = 1 << 11;
+
+    const int kImplodeDictionarySizeMask = 1 << 1;
+    const int kImplodeLiteralsOnMask     = 1 << 2;
+    
+    const int kDeflateTypeBitStart = 1;
+    const int kNumDeflateTypeBits = 2;
+    const int kNumDeflateTypes = (1 << kNumDeflateTypeBits);
+    const int kDeflateTypeMask = (1 << kNumDeflateTypeBits) - 1;
+  }
+  
+  namespace NHostOS
+  {
+    enum EEnum
+    {
+        kFAT      = 0,
+        kAMIGA    = 1,
+        kVMS      = 2,  // VAX/VMS
+        kUnix     = 3,
+        kVM_CMS   = 4,
+        kAtari    = 5,  // what if it's a minix filesystem? [cjh]
+        kHPFS     = 6,  // filesystem used by OS/2 (and NT 3.x)
+        kMac      = 7,
+        kZ_System = 8,
+        kCPM      = 9,
+        kTOPS20   = 10, // pkzip 2.50 NTFS
+        kNTFS     = 11, // filesystem used by Windows NT
+        kQDOS     = 12, // SMS/QDOS
+        kAcorn    = 13, // Archimedes Acorn RISC OS
+        kVFAT     = 14, // filesystem used by Windows 95, NT
+        kMVS      = 15,
+        kBeOS     = 16, // hybrid POSIX/database filesystem
+        kTandem   = 17,
+        kOS400    = 18,
+        kOSX      = 19
+    };
+  }
+  namespace NUnixAttribute
+  {
+    const UInt32 kIFMT   =   0170000;     /* Unix file type mask */
+    
+    const UInt32 kIFDIR  =   0040000;     /* Unix directory */
+    const UInt32 kIFREG  =   0100000;     /* Unix regular file */
+    const UInt32 kIFSOCK =   0140000;     /* Unix socket (BSD, not SysV or Amiga) */
+    const UInt32 kIFLNK  =   0120000;     /* Unix symbolic link (not SysV, Amiga) */
+    const UInt32 kIFBLK  =   0060000;     /* Unix block special       (not Amiga) */
+    const UInt32 kIFCHR  =   0020000;     /* Unix character special   (not Amiga) */
+    const UInt32 kIFIFO  =   0010000;     /* Unix fifo    (BCC, not MSC or Amiga) */
+    
+    const UInt32 kISUID  =   04000;       /* Unix set user id on execution */
+    const UInt32 kISGID  =   02000;       /* Unix set group id on execution */
+    const UInt32 kISVTX  =   01000;       /* Unix directory permissions control */
+    const UInt32 kENFMT  =   kISGID;   /* Unix record locking enforcement flag */
+    const UInt32 kIRWXU  =   00700;       /* Unix read, write, execute: owner */
+    const UInt32 kIRUSR  =   00400;       /* Unix read permission: owner */
+    const UInt32 kIWUSR  =   00200;       /* Unix write permission: owner */
+    const UInt32 kIXUSR  =   00100;       /* Unix execute permission: owner */
+    const UInt32 kIRWXG  =   00070;       /* Unix read, write, execute: group */
+    const UInt32 kIRGRP  =   00040;       /* Unix read permission: group */
+    const UInt32 kIWGRP  =   00020;       /* Unix write permission: group */
+    const UInt32 kIXGRP  =   00010;       /* Unix execute permission: group */
+    const UInt32 kIRWXO  =   00007;       /* Unix read, write, execute: other */
+    const UInt32 kIROTH  =   00004;       /* Unix read permission: other */
+    const UInt32 kIWOTH  =   00002;       /* Unix write permission: other */
+    const UInt32 kIXOTH  =   00001;       /* Unix execute permission: other */
+  }
+  
+  namespace NAmigaAttribute
+  {
+    const UInt32 kIFMT     = 06000;       /* Amiga file type mask */
+    const UInt32 kIFDIR    = 04000;       /* Amiga directory */
+    const UInt32 kIFREG    = 02000;       /* Amiga regular file */
+    const UInt32 kIHIDDEN  = 00200;       /* to be supported in AmigaDOS 3.x */
+    const UInt32 kISCRIPT  = 00100;       /* executable script (text command file) */
+    const UInt32 kIPURE    = 00040;       /* allow loading into resident memory */
+    const UInt32 kIARCHIVE = 00020;       /* not modified since bit was last set */
+    const UInt32 kIREAD    = 00010;       /* can be opened for reading */
+    const UInt32 kIWRITE   = 00004;       /* can be opened for writing */
+    const UInt32 kIEXECUTE = 00002;       /* executable image, a loadable runfile */
+    const UInt32 kIDELETE  = 00001;      /* can be deleted */
+  }
+}
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipIn.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipIn.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipIn.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipIn.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,893 @@
+// Archive/ZipIn.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/CpuArch.h"
+
+#include "Common/DynamicBuffer.h"
+
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/StreamUtils.h"
+
+#include "ZipIn.h"
+
+#define Get16(p) GetUi16(p)
+#define Get32(p) GetUi32(p)
+#define Get64(p) GetUi64(p)
+
+namespace NArchive {
+namespace NZip {
+ 
+HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
+{
+  _inBufMode = false;
+  Close();
+  RINOK(stream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition));
+  m_Position = m_StreamStartPosition;
+  RINOK(FindAndReadMarker(stream, searchHeaderSizeLimit));
+  RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL));
+  m_Stream = stream;
+  return S_OK;
+}
+
+void CInArchive::Close()
+{
+  _inBuffer.ReleaseStream();
+  m_Stream.Release();
+}
+
+HRESULT CInArchive::Seek(UInt64 offset)
+{
+  return m_Stream->Seek(offset, STREAM_SEEK_SET, NULL);
+}
+
+//////////////////////////////////////
+// Markers
+
+static inline bool TestMarkerCandidate(const Byte *p, UInt32 &value)
+{
+  value = Get32(p);
+  return
+    (value == NSignature::kLocalFileHeader) ||
+    (value == NSignature::kEndOfCentralDir);
+}
+
+static const UInt32 kNumMarkerAddtionalBytes = 2;
+static inline bool TestMarkerCandidate2(const Byte *p, UInt32 &value)
+{
+  value = Get32(p);
+  if (value == NSignature::kEndOfCentralDir)
+    return (Get16(p + 4) == 0);
+  return (value == NSignature::kLocalFileHeader && p[4] < 128);
+}
+
+HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
+{
+  ArcInfo.Clear();
+  m_Position = m_StreamStartPosition;
+
+  Byte marker[NSignature::kMarkerSize];
+  RINOK(ReadStream_FALSE(stream, marker, NSignature::kMarkerSize));
+  m_Position += NSignature::kMarkerSize;
+  if (TestMarkerCandidate(marker, m_Signature))
+    return S_OK;
+
+  CByteDynamicBuffer dynamicBuffer;
+  const UInt32 kSearchMarkerBufferSize = 0x10000;
+  dynamicBuffer.EnsureCapacity(kSearchMarkerBufferSize);
+  Byte *buffer = dynamicBuffer;
+  UInt32 numBytesPrev = NSignature::kMarkerSize - 1;
+  memcpy(buffer, marker + 1, numBytesPrev);
+  UInt64 curTestPos = m_StreamStartPosition + 1;
+  for (;;)
+  {
+    if (searchHeaderSizeLimit != NULL)
+      if (curTestPos - m_StreamStartPosition > *searchHeaderSizeLimit)
+        break;
+    size_t numReadBytes = kSearchMarkerBufferSize - numBytesPrev;
+    RINOK(ReadStream(stream, buffer + numBytesPrev, &numReadBytes));
+    m_Position += numReadBytes;
+    UInt32 numBytesInBuffer = numBytesPrev + (UInt32)numReadBytes;
+    const UInt32 kMarker2Size = NSignature::kMarkerSize + kNumMarkerAddtionalBytes;
+    if (numBytesInBuffer < kMarker2Size)
+      break;
+    UInt32 numTests = numBytesInBuffer - kMarker2Size + 1;
+    for (UInt32 pos = 0; pos < numTests; pos++)
+    {
+      if (buffer[pos] != 0x50)
+        continue;
+      if (TestMarkerCandidate2(buffer + pos, m_Signature))
+      {
+        curTestPos += pos;
+        ArcInfo.StartPosition = curTestPos;
+        m_Position = curTestPos + NSignature::kMarkerSize;
+        return S_OK;
+      }
+    }
+    curTestPos += numTests;
+    numBytesPrev = numBytesInBuffer - numTests;
+    memmove(buffer, buffer + numTests, numBytesPrev);
+  }
+  return S_FALSE;
+}
+
+HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)
+{
+  size_t realProcessedSize = size;
+  HRESULT result = S_OK;
+  if (_inBufMode)
+  {
+    try { realProcessedSize = _inBuffer.ReadBytes((Byte *)data, size); }
+    catch (const CInBufferException &e) { return e.ErrorCode; }
+  }
+  else
+    result = ReadStream(m_Stream, data, &realProcessedSize);
+  if (processedSize != NULL)
+    *processedSize = (UInt32)realProcessedSize;
+  m_Position += realProcessedSize;
+  return result;
+}
+
+void CInArchive::Skip(UInt64 num)
+{
+  for (UInt64 i = 0; i < num; i++)
+    ReadByte();
+}
+
+void CInArchive::IncreaseRealPosition(UInt64 addValue)
+{
+  if (m_Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position) != S_OK)
+    throw CInArchiveException(CInArchiveException::kSeekStreamError);
+}
+
+bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size)
+{
+  UInt32 realProcessedSize;
+  if (ReadBytes(data, size, &realProcessedSize) != S_OK)
+    throw CInArchiveException(CInArchiveException::kReadStreamError);
+  return (realProcessedSize == size);
+}
+
+void CInArchive::SafeReadBytes(void *data, UInt32 size)
+{
+  if (!ReadBytesAndTestSize(data, size))
+    throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
+}
+
+void CInArchive::ReadBuffer(CByteBuffer &buffer, UInt32 size)
+{
+  buffer.SetCapacity(size);
+  if (size > 0)
+    SafeReadBytes(buffer, size);
+}
+
+Byte CInArchive::ReadByte()
+{
+  Byte b;
+  SafeReadBytes(&b, 1);
+  return b;
+}
+
+UInt16 CInArchive::ReadUInt16()
+{
+  Byte buf[2];
+  SafeReadBytes(buf, 2);
+  return Get16(buf);
+}
+
+UInt32 CInArchive::ReadUInt32()
+{
+  Byte buf[4];
+  SafeReadBytes(buf, 4);
+  return Get32(buf);
+}
+
+UInt64 CInArchive::ReadUInt64()
+{
+  Byte buf[8];
+  SafeReadBytes(buf, 8);
+  return Get64(buf);
+}
+
+bool CInArchive::ReadUInt32(UInt32 &value)
+{
+  Byte buf[4];
+  if (!ReadBytesAndTestSize(buf, 4))
+    return false;
+  value = Get32(buf);
+  return true;
+}
+
+void CInArchive::ReadFileName(UInt32 nameSize, AString &dest)
+{
+  if (nameSize == 0)
+    dest.Empty();
+  char *p = dest.GetBuffer((int)nameSize);
+  SafeReadBytes(p, nameSize);
+  p[nameSize] = 0;
+  dest.ReleaseBuffer();
+}
+
+void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock,
+    UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber)
+{
+  extraBlock.Clear();
+  UInt32 remain = extraSize;
+  while(remain >= 4)
+  {
+    CExtraSubBlock subBlock;
+    subBlock.ID = ReadUInt16();
+    UInt32 dataSize = ReadUInt16();
+    remain -= 4;
+    if (dataSize > remain) // it's bug
+      dataSize = remain;
+    if (subBlock.ID == NFileHeader::NExtraID::kZip64)
+    {
+      if (unpackSize == 0xFFFFFFFF)
+      {
+        if (dataSize < 8)
+          break;
+        unpackSize = ReadUInt64();
+        remain -= 8;
+        dataSize -= 8;
+      }
+      if (packSize == 0xFFFFFFFF)
+      {
+        if (dataSize < 8)
+          break;
+        packSize = ReadUInt64();
+        remain -= 8;
+        dataSize -= 8;
+      }
+      if (localHeaderOffset == 0xFFFFFFFF)
+      {
+        if (dataSize < 8)
+          break;
+        localHeaderOffset = ReadUInt64();
+        remain -= 8;
+        dataSize -= 8;
+      }
+      if (diskStartNumber == 0xFFFF)
+      {
+        if (dataSize < 4)
+          break;
+        diskStartNumber = ReadUInt32();
+        remain -= 4;
+        dataSize -= 4;
+      }
+      for (UInt32 i = 0; i < dataSize; i++)
+        ReadByte();
+    }
+    else
+    {
+      ReadBuffer(subBlock.Data, dataSize);
+      extraBlock.SubBlocks.Add(subBlock);
+    }
+    remain -= dataSize;
+  }
+  Skip(remain);
+}
+
+HRESULT CInArchive::ReadLocalItem(CItemEx &item)
+{
+  const int kBufSize = 26;
+  Byte p[kBufSize];
+  SafeReadBytes(p, kBufSize);
+
+  item.ExtractVersion.Version = p[0];
+  item.ExtractVersion.HostOS = p[1];
+  item.Flags = Get16(p + 2);
+  item.CompressionMethod = Get16(p + 4);
+  item.Time = Get32(p + 6);
+  item.FileCRC = Get32(p + 10);
+  item.PackSize = Get32(p + 14);
+  item.UnPackSize = Get32(p + 18);
+  UInt32 fileNameSize = Get16(p + 22);
+  item.LocalExtraSize = Get16(p + 24);
+  ReadFileName(fileNameSize, item.Name);
+  item.FileHeaderWithNameSize = 4 + NFileHeader::kLocalBlockSize + fileNameSize;
+  if (item.LocalExtraSize > 0)
+  {
+    UInt64 localHeaderOffset = 0;
+    UInt32 diskStartNumber = 0;
+    ReadExtra(item.LocalExtraSize, item.LocalExtra, item.UnPackSize, item.PackSize,
+      localHeaderOffset, diskStartNumber);
+  }
+  /*
+  if (item.IsDir())
+    item.UnPackSize = 0;       // check It
+  */
+  return S_OK;
+}
+
+static bool FlagsAreSame(CItem &i1, CItem &i2)
+{
+  if (i1.CompressionMethod != i2.CompressionMethod)
+    return false;
+  // i1.Time
+
+  if (i1.Flags == i2.Flags)
+    return true;
+  UInt32 mask = 0xFFFF;
+  switch(i1.CompressionMethod)
+  {
+    case NFileHeader::NCompressionMethod::kDeflated:
+      mask = 0x7FF9;
+      break;
+    default:
+      if (i1.CompressionMethod <= NFileHeader::NCompressionMethod::kImploded)
+        mask = 0x7FFF;
+  }
+  return ((i1.Flags & mask) == (i2.Flags & mask));
+}
+
+HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item)
+{
+  if (item.FromLocal)
+    return S_OK;
+  try
+  {
+    RINOK(Seek(ArcInfo.Base + item.LocalHeaderPosition));
+    CItemEx localItem;
+    if (ReadUInt32() != NSignature::kLocalFileHeader)
+      return S_FALSE;
+    RINOK(ReadLocalItem(localItem));
+    if (!FlagsAreSame(item, localItem))
+      return S_FALSE;
+
+    if ((!localItem.HasDescriptor() &&
+          (
+            item.FileCRC != localItem.FileCRC ||
+            item.PackSize != localItem.PackSize ||
+            item.UnPackSize != localItem.UnPackSize
+          )
+        ) ||
+        item.Name.Length() != localItem.Name.Length()
+        )
+      return S_FALSE;
+    item.FileHeaderWithNameSize = localItem.FileHeaderWithNameSize;
+    item.LocalExtraSize = localItem.LocalExtraSize;
+    item.LocalExtra = localItem.LocalExtra;
+    item.FromLocal = true;
+  }
+  catch(...) { return S_FALSE; }
+  return S_OK;
+}
+
+HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item)
+{
+  if (item.HasDescriptor())
+  {
+    const int kBufferSize = (1 << 12);
+    Byte buffer[kBufferSize];
+    
+    UInt32 numBytesInBuffer = 0;
+    UInt32 packedSize = 0;
+    
+    bool descriptorWasFound = false;
+    for (;;)
+    {
+      UInt32 processedSize;
+      RINOK(ReadBytes(buffer + numBytesInBuffer, kBufferSize - numBytesInBuffer, &processedSize));
+      numBytesInBuffer += processedSize;
+      if (numBytesInBuffer < NFileHeader::kDataDescriptorSize)
+        return S_FALSE;
+      UInt32 i;
+      for (i = 0; i <= numBytesInBuffer - NFileHeader::kDataDescriptorSize; i++)
+      {
+        // descriptorSignature field is Info-ZIP's extension
+        // to Zip specification.
+        UInt32 descriptorSignature = Get32(buffer + i);
+        
+        // !!!! It must be fixed for Zip64 archives
+        UInt32 descriptorPackSize = Get32(buffer + i + 8);
+        if (descriptorSignature== NSignature::kDataDescriptor && descriptorPackSize == packedSize + i)
+        {
+          descriptorWasFound = true;
+          item.FileCRC = Get32(buffer + i + 4);
+          item.PackSize = descriptorPackSize;
+          item.UnPackSize = Get32(buffer + i + 12);
+          IncreaseRealPosition(Int64(Int32(0 - (numBytesInBuffer - i - NFileHeader::kDataDescriptorSize))));
+          break;
+        }
+      }
+      if (descriptorWasFound)
+        break;
+      packedSize += i;
+      int j;
+      for (j = 0; i < numBytesInBuffer; i++, j++)
+        buffer[j] = buffer[i];
+      numBytesInBuffer = j;
+    }
+  }
+  else
+    IncreaseRealPosition(item.PackSize);
+  return S_OK;
+}
+
+HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item)
+{
+  if (item.FromLocal)
+    return S_OK;
+  try
+  {
+    RINOK(ReadLocalItemAfterCdItem(item));
+    if (item.HasDescriptor())
+    {
+      RINOK(Seek(ArcInfo.Base + item.GetDataPosition() + item.PackSize));
+      if (ReadUInt32() != NSignature::kDataDescriptor)
+        return S_FALSE;
+      UInt32 crc = ReadUInt32();
+      UInt64 packSize, unpackSize;
+
+      /*
+      if (IsZip64)
+      {
+        packSize = ReadUInt64();
+        unpackSize = ReadUInt64();
+      }
+      else
+      */
+      {
+        packSize = ReadUInt32();
+        unpackSize = ReadUInt32();
+      }
+
+      if (crc != item.FileCRC || item.PackSize != packSize || item.UnPackSize != unpackSize)
+        return S_FALSE;
+    }
+  }
+  catch(...) { return S_FALSE; }
+  return S_OK;
+}
+  
+HRESULT CInArchive::ReadCdItem(CItemEx &item)
+{
+  item.FromCentral = true;
+  const int kBufSize = 42;
+  Byte p[kBufSize];
+  SafeReadBytes(p, kBufSize);
+  item.MadeByVersion.Version = p[0];
+  item.MadeByVersion.HostOS = p[1];
+  item.ExtractVersion.Version = p[2];
+  item.ExtractVersion.HostOS = p[3];
+  item.Flags = Get16(p + 4);
+  item.CompressionMethod = Get16(p + 6);
+  item.Time = Get32(p + 8);
+  item.FileCRC = Get32(p + 12);
+  item.PackSize = Get32(p + 16);
+  item.UnPackSize = Get32(p + 20);
+  UInt16 headerNameSize = Get16(p + 24);
+  UInt16 headerExtraSize = Get16(p + 26);
+  UInt16 headerCommentSize = Get16(p + 28);
+  UInt32 headerDiskNumberStart = Get16(p + 30);
+  item.InternalAttributes = Get16(p + 32);
+  item.ExternalAttributes = Get32(p + 34);
+  item.LocalHeaderPosition = Get32(p + 38);
+  ReadFileName(headerNameSize, item.Name);
+  
+  if (headerExtraSize > 0)
+  {
+    ReadExtra(headerExtraSize, item.CentralExtra, item.UnPackSize, item.PackSize,
+        item.LocalHeaderPosition, headerDiskNumberStart);
+  }
+
+  if (headerDiskNumberStart != 0)
+    throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
+  
+  // May be these strings must be deleted
+  /*
+  if (item.IsDir())
+    item.UnPackSize = 0;
+  */
+  
+  ReadBuffer(item.Comment, headerCommentSize);
+  return S_OK;
+}
+
+HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo)
+{
+  RINOK(Seek(offset));
+  const UInt32 kEcd64Size = 56;
+  Byte buf[kEcd64Size];
+  if (!ReadBytesAndTestSize(buf, kEcd64Size))
+    return S_FALSE;
+  if (Get32(buf) != NSignature::kZip64EndOfCentralDir)
+    return S_FALSE;
+  // cdInfo.NumEntries = Get64(buf + 24);
+  cdInfo.Size = Get64(buf + 40);
+  cdInfo.Offset = Get64(buf + 48);
+  return S_OK;
+}
+
+HRESULT CInArchive::FindCd(CCdInfo &cdInfo)
+{
+  UInt64 endPosition;
+  RINOK(m_Stream->Seek(0, STREAM_SEEK_END, &endPosition));
+  const UInt32 kBufSizeMax = (1 << 16) + kEcdSize + kZip64EcdLocatorSize;
+  CByteBuffer byteBuffer;
+  byteBuffer.SetCapacity(kBufSizeMax);
+  Byte *buf = byteBuffer;
+  UInt32 bufSize = (endPosition < kBufSizeMax) ? (UInt32)endPosition : kBufSizeMax;
+  if (bufSize < kEcdSize)
+    return S_FALSE;
+  UInt64 startPosition = endPosition - bufSize;
+  RINOK(m_Stream->Seek(startPosition, STREAM_SEEK_SET, &m_Position));
+  if (m_Position != startPosition)
+    return S_FALSE;
+  if (!ReadBytesAndTestSize(buf, bufSize))
+    return S_FALSE;
+  for (int i = (int)(bufSize - kEcdSize); i >= 0; i--)
+  {
+    if (Get32(buf + i) == NSignature::kEndOfCentralDir)
+    {
+      if (i >= kZip64EcdLocatorSize)
+      {
+        const Byte *locator = buf + i - kZip64EcdLocatorSize;
+        if (Get32(locator) == NSignature::kZip64EndOfCentralDirLocator)
+        {
+          UInt64 ecd64Offset = Get64(locator + 8);
+          if (TryEcd64(ecd64Offset, cdInfo) == S_OK)
+            return S_OK;
+          if (TryEcd64(ArcInfo.StartPosition + ecd64Offset, cdInfo) == S_OK)
+          {
+            ArcInfo.Base = ArcInfo.StartPosition;
+            return S_OK;
+          }
+        }
+      }
+      if (Get32(buf + i + 4) == 0)
+      {
+        // cdInfo.NumEntries = GetUInt16(buf + i + 10);
+        cdInfo.Size = Get32(buf + i + 12);
+        cdInfo.Offset = Get32(buf + i + 16);
+        UInt64 curPos = endPosition - bufSize + i;
+        UInt64 cdEnd = cdInfo.Size + cdInfo.Offset;
+        if (curPos != cdEnd)
+        {
+          /*
+          if (cdInfo.Offset <= 16 && cdInfo.Size != 0)
+          {
+            // here we support some rare ZIP files with Central directory at the start
+            ArcInfo.Base = 0;
+          }
+          else
+          */
+            ArcInfo.Base = curPos - cdEnd;
+        }
+        return S_OK;
+      }
+    }
+  }
+  return S_FALSE;
+}
+
+HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UInt64 cdSize, CProgressVirt *progress)
+{
+  items.Clear();
+  RINOK(m_Stream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position));
+  if (m_Position != cdOffset)
+    return S_FALSE;
+
+  if (!_inBuffer.Create(1 << 15))
+    return E_OUTOFMEMORY;
+  _inBuffer.SetStream(m_Stream);
+  _inBuffer.Init();
+  _inBufMode = true;
+
+  while(m_Position - cdOffset < cdSize)
+  {
+    if (ReadUInt32() != NSignature::kCentralFileHeader)
+      return S_FALSE;
+    CItemEx cdItem;
+    RINOK(ReadCdItem(cdItem));
+    items.Add(cdItem);
+    if (progress && items.Size() % 1000 == 0)
+      RINOK(progress->SetCompleted(items.Size()));
+  }
+  return (m_Position - cdOffset == cdSize) ? S_OK : S_FALSE;
+}
+
+HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt64 &cdSize, CProgressVirt *progress)
+{
+  ArcInfo.Base = 0;
+  CCdInfo cdInfo;
+  RINOK(FindCd(cdInfo));
+  HRESULT res = S_FALSE;
+  cdSize = cdInfo.Size;
+  cdOffset = cdInfo.Offset;
+  res = TryReadCd(items, ArcInfo.Base + cdOffset, cdSize, progress);
+  if (res == S_FALSE && ArcInfo.Base == 0)
+  {
+    res = TryReadCd(items, cdInfo.Offset + ArcInfo.StartPosition, cdSize, progress);
+    if (res == S_OK)
+      ArcInfo.Base = ArcInfo.StartPosition;
+  }
+  if (!ReadUInt32(m_Signature))
+    return S_FALSE;
+  return res;
+}
+
+HRESULT CInArchive::ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset, int &numCdItems)
+{
+  items.Clear();
+  numCdItems = 0;
+  while (m_Signature == NSignature::kLocalFileHeader)
+  {
+    // FSeek points to next byte after signature
+    // NFileHeader::CLocalBlock localHeader;
+    CItemEx item;
+    item.LocalHeaderPosition = m_Position - m_StreamStartPosition - 4; // points to signature;
+    RINOK(ReadLocalItem(item));
+    item.FromLocal = true;
+    ReadLocalItemDescriptor(item);
+    items.Add(item);
+    if (progress && items.Size() % 100 == 0)
+      RINOK(progress->SetCompleted(items.Size()));
+    if (!ReadUInt32(m_Signature))
+      break;
+  }
+  cdOffset = m_Position - 4;
+  int i;
+  for (i = 0; i < items.Size(); i++, numCdItems++)
+  {
+    if (progress && i % 1000 == 0)
+      RINOK(progress->SetCompleted(items.Size()));
+    if (m_Signature == NSignature::kEndOfCentralDir)
+      break;
+
+    if (m_Signature != NSignature::kCentralFileHeader)
+      return S_FALSE;
+
+    CItemEx cdItem;
+    RINOK(ReadCdItem(cdItem));
+
+    if (i == 0)
+    {
+      int j;
+      for (j = 0; j < items.Size(); j++)
+      {
+        CItemEx &item = items[j];
+        if (item.Name == cdItem.Name)
+        {
+          ArcInfo.Base = item.LocalHeaderPosition - cdItem.LocalHeaderPosition;
+          break;
+        }
+      }
+      if (j == items.Size())
+        return S_FALSE;
+    }
+
+    int index;
+    int left = 0, right = items.Size();
+    for (;;)
+    {
+      if (left >= right)
+        return S_FALSE;
+      index = (left + right) / 2;
+      UInt64 position = items[index].LocalHeaderPosition - ArcInfo.Base;
+      if (cdItem.LocalHeaderPosition == position)
+        break;
+      if (cdItem.LocalHeaderPosition < position)
+        right = index;
+      else
+        left = index + 1;
+    }
+    CItemEx &item = items[index];
+    // item.LocalHeaderPosition = cdItem.LocalHeaderPosition;
+    item.MadeByVersion = cdItem.MadeByVersion;
+    item.CentralExtra = cdItem.CentralExtra;
+
+    if (
+        // item.ExtractVersion != cdItem.ExtractVersion ||
+        !FlagsAreSame(item, cdItem) ||
+        item.FileCRC != cdItem.FileCRC)
+      return S_FALSE;
+
+    if (item.Name.Length() != cdItem.Name.Length() ||
+        item.PackSize != cdItem.PackSize ||
+        item.UnPackSize != cdItem.UnPackSize
+      )
+      return S_FALSE;
+    item.Name = cdItem.Name;
+    item.InternalAttributes = cdItem.InternalAttributes;
+    item.ExternalAttributes = cdItem.ExternalAttributes;
+    item.Comment = cdItem.Comment;
+    item.FromCentral = cdItem.FromCentral;
+    if (!ReadUInt32(m_Signature))
+      return S_FALSE;
+  }
+  for (i = 0; i < items.Size(); i++)
+    items[i].LocalHeaderPosition -= ArcInfo.Base;
+  return S_OK;
+}
+
+struct CEcd
+{
+  UInt16 thisDiskNumber;
+  UInt16 startCDDiskNumber;
+  UInt16 numEntriesInCDOnThisDisk;
+  UInt16 numEntriesInCD;
+  UInt32 cdSize;
+  UInt32 cdStartOffset;
+  UInt16 commentSize;
+  void Parse(const Byte *p);
+};
+
+void CEcd::Parse(const Byte *p)
+{
+  thisDiskNumber = Get16(p);
+  startCDDiskNumber = Get16(p + 2);
+  numEntriesInCDOnThisDisk = Get16(p + 4);
+  numEntriesInCD = Get16(p + 6);
+  cdSize = Get32(p + 8);
+  cdStartOffset = Get32(p + 12);
+  commentSize = Get16(p + 16);
+}
+
+struct CEcd64
+{
+  UInt16 versionMade;
+  UInt16 versionNeedExtract;
+  UInt32 thisDiskNumber;
+  UInt32 startCDDiskNumber;
+  UInt64 numEntriesInCDOnThisDisk;
+  UInt64 numEntriesInCD;
+  UInt64 cdSize;
+  UInt64 cdStartOffset;
+  void Parse(const Byte *p);
+  CEcd64() { memset(this, 0, sizeof(*this)); }
+};
+
+void CEcd64::Parse(const Byte *p)
+{
+  versionMade = Get16(p);
+  versionNeedExtract = Get16(p + 2);
+  thisDiskNumber = Get32(p + 4);
+  startCDDiskNumber = Get32(p + 8);
+  numEntriesInCDOnThisDisk = Get64(p + 12);
+  numEntriesInCD = Get64(p + 20);
+  cdSize = Get64(p + 28);
+  cdStartOffset = Get64(p + 36);
+}
+
+#define COPY_ECD_ITEM_16(n) if (!isZip64 || ecd. n != 0xFFFF)     ecd64. n = ecd. n;
+#define COPY_ECD_ITEM_32(n) if (!isZip64 || ecd. n != 0xFFFFFFFF) ecd64. n = ecd. n;
+
+HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress)
+{
+  // m_Signature must be kLocalFileHeaderSignature or
+  // kEndOfCentralDirSignature
+  // m_Position points to next byte after signature
+
+  IsZip64 = false;
+  items.Clear();
+
+  UInt64 cdSize, cdStartOffset;
+  HRESULT res;
+  try
+  {
+    res = ReadCd(items, cdStartOffset, cdSize, progress);
+  }
+  catch(CInArchiveException &)
+  {
+    res = S_FALSE;
+  }
+  if (res != S_FALSE && res != S_OK)
+    return res;
+
+  /*
+  if (res != S_OK)
+    return res;
+  res = S_FALSE;
+  */
+
+  int numCdItems = items.Size();
+  if (res == S_FALSE)
+  {
+    _inBufMode = false;
+    ArcInfo.Base = 0;
+    RINOK(m_Stream->Seek(ArcInfo.StartPosition, STREAM_SEEK_SET, &m_Position));
+    if (m_Position != ArcInfo.StartPosition)
+      return S_FALSE;
+    if (!ReadUInt32(m_Signature))
+      return S_FALSE;
+    RINOK(ReadLocalsAndCd(items, progress, cdStartOffset, numCdItems));
+    cdSize = (m_Position - 4) - cdStartOffset;
+    cdStartOffset -= ArcInfo.Base;
+  }
+
+  CEcd64 ecd64;
+  bool isZip64 = false;
+  UInt64 zip64EcdStartOffset = m_Position - 4 - ArcInfo.Base;
+  if (m_Signature == NSignature::kZip64EndOfCentralDir)
+  {
+    IsZip64 = isZip64 = true;
+    UInt64 recordSize = ReadUInt64();
+
+    const int kBufSize = kZip64EcdSize;
+    Byte buf[kBufSize];
+    SafeReadBytes(buf, kBufSize);
+    ecd64.Parse(buf);
+
+    Skip(recordSize - kZip64EcdSize);
+    if (!ReadUInt32(m_Signature))
+      return S_FALSE;
+    if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0)
+      throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
+    if (ecd64.numEntriesInCDOnThisDisk != numCdItems ||
+        ecd64.numEntriesInCD != numCdItems ||
+        ecd64.cdSize != cdSize ||
+        (ecd64.cdStartOffset != cdStartOffset &&
+        (!items.IsEmpty())))
+      return S_FALSE;
+  }
+  if (m_Signature == NSignature::kZip64EndOfCentralDirLocator)
+  {
+    /* UInt32 startEndCDDiskNumber = */ ReadUInt32();
+    UInt64 endCDStartOffset = ReadUInt64();
+    /* UInt32 numberOfDisks = */ ReadUInt32();
+    if (zip64EcdStartOffset != endCDStartOffset)
+      return S_FALSE;
+    if (!ReadUInt32(m_Signature))
+      return S_FALSE;
+  }
+  if (m_Signature != NSignature::kEndOfCentralDir)
+    return S_FALSE;
+
+  const int kBufSize = kEcdSize - 4;
+  Byte buf[kBufSize];
+  SafeReadBytes(buf, kBufSize);
+  CEcd ecd;
+  ecd.Parse(buf);
+
+  COPY_ECD_ITEM_16(thisDiskNumber);
+  COPY_ECD_ITEM_16(startCDDiskNumber);
+  COPY_ECD_ITEM_16(numEntriesInCDOnThisDisk);
+  COPY_ECD_ITEM_16(numEntriesInCD);
+  COPY_ECD_ITEM_32(cdSize);
+  COPY_ECD_ITEM_32(cdStartOffset);
+
+  ReadBuffer(ArcInfo.Comment, ecd.commentSize);
+
+  if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0)
+    throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
+  if ((UInt16)ecd64.numEntriesInCDOnThisDisk != ((UInt16)numCdItems) ||
+      (UInt16)ecd64.numEntriesInCD != ((UInt16)numCdItems) ||
+      (UInt32)ecd64.cdSize != (UInt32)cdSize ||
+      ((UInt32)(ecd64.cdStartOffset) != (UInt32)cdStartOffset &&
+        (!items.IsEmpty())))
+    return S_FALSE;
+  
+  _inBufMode = false;
+  _inBuffer.Free();
+  IsOkHeaders = (numCdItems == items.Size());
+  ArcInfo.FinishPosition = m_Position;
+  return S_OK;
+}
+
+ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size)
+{
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<ISequentialInStream> stream(streamSpec);
+  SeekInArchive(ArcInfo.Base + position);
+  streamSpec->SetStream(m_Stream);
+  streamSpec->Init(size);
+  return stream.Detach();
+}
+
+IInStream* CInArchive::CreateStream()
+{
+  CMyComPtr<IInStream> stream = m_Stream;
+  return stream.Detach();
+}
+
+bool CInArchive::SeekInArchive(UInt64 position)
+{
+  UInt64 newPosition;
+  if (m_Stream->Seek(position, STREAM_SEEK_SET, &newPosition) != S_OK)
+    return false;
+  return (newPosition == position);
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipIn.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipIn.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipIn.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipIn.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,125 @@
+// Archive/ZipIn.h
+
+#ifndef __ZIP_IN_H
+#define __ZIP_IN_H
+
+#include "Common/MyCom.h"
+
+#include "../../IStream.h"
+
+#include "../../Common/InBuffer.h"
+
+#include "ZipHeader.h"
+#include "ZipItemEx.h"
+
+namespace NArchive {
+namespace NZip {
+  
+class CInArchiveException
+{
+public:
+  enum ECauseType
+  {
+    kUnexpectedEndOfArchive = 0,
+    kArchiceHeaderCRCError,
+    kFileHeaderCRCError,
+    kIncorrectArchive,
+    kDataDescroptorsAreNotSupported,
+    kMultiVolumeArchiveAreNotSupported,
+    kReadStreamError,
+    kSeekStreamError
+  }
+  Cause;
+  CInArchiveException(ECauseType cause): Cause(cause) {}
+};
+
+class CInArchiveInfo
+{
+public:
+  UInt64 Base;
+  UInt64 StartPosition;
+  UInt64 FinishPosition;
+  CByteBuffer Comment;
+
+  CInArchiveInfo(): Base(0), StartPosition(0) {}
+  UInt64 GetPhySize() const { return FinishPosition - StartPosition; }
+  void Clear()
+  {
+    Base = 0;
+    StartPosition = 0;
+    Comment.SetCapacity(0);
+  }
+};
+
+class CProgressVirt
+{
+public:
+  STDMETHOD(SetTotal)(UInt64 numFiles) PURE;
+  STDMETHOD(SetCompleted)(UInt64 numFiles) PURE;
+};
+
+struct CCdInfo
+{
+  // UInt64 NumEntries;
+  UInt64 Size;
+  UInt64 Offset;
+};
+
+class CInArchive
+{
+  CMyComPtr<IInStream> m_Stream;
+  UInt32 m_Signature;
+  UInt64 m_StreamStartPosition;
+  UInt64 m_Position;
+ 
+  bool _inBufMode;
+  CInBuffer _inBuffer;
+  
+  HRESULT Seek(UInt64 offset);
+
+  HRESULT FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
+  void ReadFileName(UInt32 nameSize, AString &dest);
+  
+  HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize);
+  bool ReadBytesAndTestSize(void *data, UInt32 size);
+  void SafeReadBytes(void *data, UInt32 size);
+  void ReadBuffer(CByteBuffer &buffer, UInt32 size);
+  Byte ReadByte();
+  UInt16 ReadUInt16();
+  UInt32 ReadUInt32();
+  UInt64 ReadUInt64();
+  bool ReadUInt32(UInt32 &signature);
+  
+  void Skip(UInt64 num);
+  void IncreaseRealPosition(UInt64 addValue);
+ 
+  void ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock,
+      UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber);
+  HRESULT ReadLocalItem(CItemEx &item);
+  HRESULT ReadLocalItemDescriptor(CItemEx &item);
+  HRESULT ReadCdItem(CItemEx &item);
+  HRESULT TryEcd64(UInt64 offset, CCdInfo &cdInfo);
+  HRESULT FindCd(CCdInfo &cdInfo);
+  HRESULT TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UInt64 cdSize, CProgressVirt *progress);
+  HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt64 &cdSize, CProgressVirt *progress);
+  HRESULT ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset, int &numCdItems);
+public:
+  CInArchiveInfo ArcInfo;
+  bool IsZip64;
+  bool IsOkHeaders;
+
+  HRESULT ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress);
+  HRESULT ReadLocalItemAfterCdItem(CItemEx &item);
+  HRESULT ReadLocalItemAfterCdItemFull(CItemEx &item);
+  HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
+  void Close();
+  bool SeekInArchive(UInt64 position);
+  ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size);
+  IInStream* CreateStream();
+
+  bool IsOpen() const { return m_Stream != NULL; }
+};
+  
+}}
+  
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipItem.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipItem.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipItem.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipItem.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,181 @@
+// Archive/ZipItem.cpp
+
+#include "StdAfx.h"
+
+#include "ZipHeader.h"
+#include "ZipItem.h"
+#include "../Common/ItemNameUtils.h"
+#include "../../../../C/CpuArch.h"
+
+namespace NArchive {
+namespace NZip {
+
+bool operator==(const CVersion &v1, const CVersion &v2)
+{
+  return (v1.Version == v2.Version) && (v1.HostOS == v2.HostOS);
+}
+
+bool operator!=(const CVersion &v1, const CVersion &v2)
+{
+  return !(v1 == v2);
+}
+
+bool CExtraSubBlock::ExtractNtfsTime(int index, FILETIME &ft) const
+{
+  ft.dwHighDateTime = ft.dwLowDateTime = 0;
+  UInt32 size = (UInt32)Data.GetCapacity();
+  if (ID != NFileHeader::NExtraID::kNTFS || size < 32)
+    return false;
+  const Byte *p = (const Byte *)Data;
+  p += 4; // for reserved
+  size -= 4;
+  while (size > 4)
+  {
+    UInt16 tag = GetUi16(p);
+    UInt32 attrSize = GetUi16(p + 2);
+    p += 4;
+    size -= 4;
+    if (attrSize > size)
+      attrSize = size;
+    
+    if (tag == NFileHeader::NNtfsExtra::kTagTime && attrSize >= 24)
+    {
+      p += 8 * index;
+      ft.dwLowDateTime = GetUi32(p);
+      ft.dwHighDateTime = GetUi32(p + 4);
+      return true;
+    }
+    p += attrSize;
+    size -= attrSize;
+  }
+  return false;
+}
+
+bool CExtraSubBlock::ExtractUnixTime(int index, UInt32 &res) const
+{
+  res = 0;
+  UInt32 size = (UInt32)Data.GetCapacity();
+  if (ID != NFileHeader::NExtraID::kUnixTime || size < 5)
+    return false;
+  const Byte *p = (const Byte *)Data;
+  Byte flags = *p++;
+  size--;
+  for (int i = 0; i < 3; i++)
+    if ((flags & (1 << i)) != 0)
+    {
+      if (size < 4)
+        return false;
+      if (index == i)
+      {
+        res = GetUi32(p);
+        return true;
+      }
+      p += 4;
+      size -= 4;
+    }
+  return false;
+}
+
+bool CLocalItem::IsDir() const
+{
+  return NItemName::HasTailSlash(Name, GetCodePage());
+}
+
+bool CItem::IsDir() const
+{
+  if (NItemName::HasTailSlash(Name, GetCodePage()))
+    return true;
+  if (!FromCentral)
+    return false;
+  WORD highAttributes = WORD((ExternalAttributes >> 16 ) & 0xFFFF);
+  switch(MadeByVersion.HostOS)
+  {
+    case NFileHeader::NHostOS::kAMIGA:
+      switch (highAttributes & NFileHeader::NAmigaAttribute::kIFMT)
+      {
+        case NFileHeader::NAmigaAttribute::kIFDIR: return true;
+        case NFileHeader::NAmigaAttribute::kIFREG: return false;
+        default: return false; // change it throw kUnknownAttributes;
+      }
+    case NFileHeader::NHostOS::kFAT:
+    case NFileHeader::NHostOS::kNTFS:
+    case NFileHeader::NHostOS::kHPFS:
+    case NFileHeader::NHostOS::kVFAT:
+      return ((ExternalAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
+    case NFileHeader::NHostOS::kAtari:
+    case NFileHeader::NHostOS::kMac:
+    case NFileHeader::NHostOS::kVMS:
+    case NFileHeader::NHostOS::kVM_CMS:
+    case NFileHeader::NHostOS::kAcorn:
+    case NFileHeader::NHostOS::kMVS:
+      return false; // change it throw kUnknownAttributes;
+    default:
+      /*
+      switch (highAttributes & NFileHeader::NUnixAttribute::kIFMT)
+      {
+        case NFileHeader::NUnixAttribute::kIFDIR:
+          return true;
+        default:
+          return false;
+      }
+      */
+      return false;
+  }
+}
+
+#ifndef FILE_ATTRIBUTE_UNIX_EXTENSION
+UInt32 CLocalItem::GetWinAttributes() const
+{
+  DWORD winAttributes = 0;
+  if (IsDir())
+    winAttributes |= FILE_ATTRIBUTE_DIRECTORY;
+  return winAttributes;
+}
+#endif
+
+UInt32 CItem::GetWinAttributes() const
+{
+  DWORD winAttributes = 0;
+  switch(MadeByVersion.HostOS)
+  {
+    case NFileHeader::NHostOS::kFAT:
+    case NFileHeader::NHostOS::kNTFS:
+      if (FromCentral)
+        winAttributes = ExternalAttributes;
+      break;
+#ifdef FILE_ATTRIBUTE_UNIX_EXTENSION
+    case NFileHeader::NHostOS::kUnix:
+        winAttributes = (ExternalAttributes & 0xFFFF0000) | FILE_ATTRIBUTE_UNIX_EXTENSION; 
+        if (winAttributes & (NFileHeader::NUnixAttribute::kIFDIR << 16))
+		winAttributes |= FILE_ATTRIBUTE_DIRECTORY;
+        return winAttributes;
+#endif
+    default:
+      winAttributes = 0; // must be converted from unix value;
+  }
+  if (IsDir())       // test it;
+    winAttributes |= FILE_ATTRIBUTE_DIRECTORY;
+  return winAttributes;
+}
+
+void CLocalItem::SetFlagBits(int startBitNumber, int numBits, int value)
+{
+  UInt16 mask = (UInt16)(((1 << numBits) - 1) << startBitNumber);
+  Flags &= ~mask;
+  Flags |= value << startBitNumber;
+}
+
+void CLocalItem::SetBitMask(int bitMask, bool enable)
+{
+  if(enable)
+    Flags |= bitMask;
+  else
+    Flags &= ~bitMask;
+}
+
+void CLocalItem::SetEncrypted(bool encrypted)
+  { SetBitMask(NFileHeader::NFlags::kEncrypted, encrypted); }
+void CLocalItem::SetUtf8(bool isUtf8)
+  { SetBitMask(NFileHeader::NFlags::kUtf8, isUtf8); }
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipItem.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipItem.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipItem.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipItem.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,281 @@
+// Archive/ZipItem.h
+
+#ifndef __ARCHIVE_ZIP_ITEM_H
+#define __ARCHIVE_ZIP_ITEM_H
+
+#include "Common/Types.h"
+#include "Common/MyString.h"
+#include "Common/Buffer.h"
+#include "Common/UTFConvert.h"
+#include "Common/StringConvert.h"
+
+#include "ZipHeader.h"
+
+namespace NArchive {
+namespace NZip {
+
+struct CVersion
+{
+  Byte Version;
+  Byte HostOS;
+};
+
+bool operator==(const CVersion &v1, const CVersion &v2);
+bool operator!=(const CVersion &v1, const CVersion &v2);
+
+struct CExtraSubBlock
+{
+  UInt16 ID;
+  CByteBuffer Data;
+  bool ExtractNtfsTime(int index, FILETIME &ft) const;
+  bool ExtractUnixTime(int index, UInt32 &res) const;
+};
+
+struct CWzAesExtraField
+{
+  UInt16 VendorVersion; // 0x0001 - AE-1, 0x0002 - AE-2,
+  // UInt16 VendorId; // "AE"
+  Byte Strength; // 1 - 128-bit , 2 - 192-bit , 3 - 256-bit
+  UInt16 Method;
+
+  CWzAesExtraField(): VendorVersion(2), Strength(3), Method(0) {}
+
+  bool NeedCrc() const { return (VendorVersion == 1); }
+
+  bool ParseFromSubBlock(const CExtraSubBlock &sb)
+  {
+    if (sb.ID != NFileHeader::NExtraID::kWzAES)
+      return false;
+    if (sb.Data.GetCapacity() < 7)
+      return false;
+    const Byte *p = (const Byte *)sb.Data;
+    VendorVersion = (((UInt16)p[1]) << 8) | p[0];
+    if (p[2] != 'A' || p[3] != 'E')
+      return false;
+    Strength = p[4];
+    Method = (((UInt16)p[6]) << 16) | p[5];
+    return true;
+  }
+  void SetSubBlock(CExtraSubBlock &sb) const
+  {
+    sb.Data.SetCapacity(7);
+    sb.ID = NFileHeader::NExtraID::kWzAES;
+    Byte *p = (Byte *)sb.Data;
+    p[0] = (Byte)VendorVersion;
+    p[1] = (Byte)(VendorVersion >> 8);
+    p[2] = 'A';
+    p[3] = 'E';
+    p[4] = Strength;
+    p[5] = (Byte)Method;
+    p[6] = (Byte)(Method >> 8);
+  }
+};
+
+namespace NStrongCryptoFlags
+{
+  const UInt16 kDES = 0x6601;
+  const UInt16 kRC2old = 0x6602;
+  const UInt16 k3DES168 = 0x6603;
+  const UInt16 k3DES112 = 0x6609;
+  const UInt16 kAES128 = 0x660E;
+  const UInt16 kAES192 = 0x660F;
+  const UInt16 kAES256 = 0x6610;
+  const UInt16 kRC2 = 0x6702;
+  const UInt16 kBlowfish = 0x6720;
+  const UInt16 kTwofish = 0x6721;
+  const UInt16 kRC4 = 0x6801;
+}
+
+struct CStrongCryptoField
+{
+  UInt16 Format;
+  UInt16 AlgId;
+  UInt16 BitLen;
+  UInt16 Flags;
+
+  bool ParseFromSubBlock(const CExtraSubBlock &sb)
+  {
+    if (sb.ID != NFileHeader::NExtraID::kStrongEncrypt)
+      return false;
+    const Byte *p = (const Byte *)sb.Data;
+    if (sb.Data.GetCapacity() < 8)
+      return false;
+    Format = (((UInt16)p[1]) << 8) | p[0];
+    AlgId  = (((UInt16)p[3]) << 8) | p[2];
+    BitLen = (((UInt16)p[5]) << 8) | p[4];
+    Flags  = (((UInt16)p[7]) << 8) | p[6];
+    return (Format == 2);
+  }
+};
+
+struct CExtraBlock
+{
+  CObjectVector<CExtraSubBlock> SubBlocks;
+  void Clear() { SubBlocks.Clear(); }
+  size_t GetSize() const
+  {
+    size_t res = 0;
+    for (int i = 0; i < SubBlocks.Size(); i++)
+      res += SubBlocks[i].Data.GetCapacity() + 2 + 2;
+    return res;
+  }
+  bool GetWzAesField(CWzAesExtraField &aesField) const
+  {
+    for (int i = 0; i < SubBlocks.Size(); i++)
+      if (aesField.ParseFromSubBlock(SubBlocks[i]))
+        return true;
+    return false;
+  }
+
+  bool GetStrongCryptoField(CStrongCryptoField &f) const
+  {
+    for (int i = 0; i < SubBlocks.Size(); i++)
+      if (f.ParseFromSubBlock(SubBlocks[i]))
+        return true;
+    return false;
+  }
+
+  bool HasWzAesField() const
+  {
+    CWzAesExtraField aesField;
+    return GetWzAesField(aesField);
+  }
+
+  bool GetNtfsTime(int index, FILETIME &ft) const
+  {
+    for (int i = 0; i < SubBlocks.Size(); i++)
+    {
+      const CExtraSubBlock &sb = SubBlocks[i];
+      if (sb.ID == NFileHeader::NExtraID::kNTFS)
+        return sb.ExtractNtfsTime(index, ft);
+    }
+    return false;
+  }
+
+  bool GetUnixTime(int index, UInt32 &res) const
+  {
+    for (int i = 0; i < SubBlocks.Size(); i++)
+    {
+      const CExtraSubBlock &sb = SubBlocks[i];
+      if (sb.ID == NFileHeader::NExtraID::kUnixTime)
+        return sb.ExtractUnixTime(index, res);
+    }
+    return false;
+  }
+
+  /*
+  bool HasStrongCryptoField() const
+  {
+    CStrongCryptoField f;
+    return GetStrongCryptoField(f);
+  }
+  */
+
+  void RemoveUnknownSubBlocks()
+  {
+    for (int i = SubBlocks.Size() - 1; i >= 0; i--)
+      if (SubBlocks[i].ID != NFileHeader::NExtraID::kWzAES)
+        SubBlocks.Delete(i);
+  }
+};
+
+
+class CLocalItem
+{
+public:
+  CVersion ExtractVersion;
+  UInt16 Flags;
+  UInt16 CompressionMethod;
+  UInt32 Time;
+  UInt32 FileCRC;
+  UInt64 PackSize;
+  UInt64 UnPackSize;
+  
+  AString Name;
+
+  CExtraBlock LocalExtra;
+
+  bool IsUtf8() const { return (Flags & NFileHeader::NFlags::kUtf8) != 0; }
+  
+  bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kEncrypted) != 0; }
+  bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; };
+  bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || CompressionMethod == NFileHeader::NCompressionMethod::kWzAES); };
+  
+  bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; }
+  
+  bool IsDir() const;
+  bool IgnoreItem() const { return false; }
+  UInt32 GetWinAttributes() const;
+  
+  bool HasDescriptor() const  { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }
+
+  UString GetUnicodeString(const AString &s) const
+  {
+    UString res;
+    if (IsUtf8())
+      if (!ConvertUTF8ToUnicode(s, res))
+        res.Empty();
+    if (res.IsEmpty())
+      res = MultiByteToUnicodeString(s, GetCodePage());
+    return res;
+  }
+  
+private:
+  void SetFlagBits(int startBitNumber, int numBits, int value);
+  void SetBitMask(int bitMask, bool enable);
+public:
+  void ClearFlags() { Flags = 0; }
+  void SetEncrypted(bool encrypted);
+  void SetUtf8(bool isUtf8);
+
+  WORD GetCodePage() const { return  CP_OEMCP; }
+};
+
+class CItem: public CLocalItem
+{
+public:
+  CVersion MadeByVersion;
+  UInt16 InternalAttributes;
+  UInt32 ExternalAttributes;
+  
+  UInt64 LocalHeaderPosition;
+  
+  FILETIME NtfsMTime;
+  FILETIME NtfsATime;
+  FILETIME NtfsCTime;
+
+  CExtraBlock CentralExtra;
+  CByteBuffer Comment;
+
+  bool FromLocal;
+  bool FromCentral;
+  bool NtfsTimeIsDefined;
+  
+  bool IsDir() const;
+  UInt32 GetWinAttributes() const;
+
+  bool IsThereCrc() const
+  {
+    if (CompressionMethod == NFileHeader::NCompressionMethod::kWzAES)
+    {
+      CWzAesExtraField aesField;
+      if (CentralExtra.GetWzAesField(aesField))
+        return aesField.NeedCrc();
+    }
+    return (FileCRC != 0 || !IsDir());
+  }
+  
+  WORD GetCodePage() const
+  {
+    return (WORD)((MadeByVersion.HostOS == NFileHeader::NHostOS::kFAT
+        || MadeByVersion.HostOS == NFileHeader::NHostOS::kNTFS
+        ) ? CP_OEMCP : CP_ACP);
+  }
+  CItem() : FromLocal(false), FromCentral(false), NtfsTimeIsDefined(false) {}
+};
+
+}}
+
+#endif
+
+

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipItemEx.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipItemEx.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipItemEx.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipItemEx.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,34 @@
+// Archive/ZipItemEx.h
+
+#ifndef __ARCHIVE_ZIP_ITEMEX_H
+#define __ARCHIVE_ZIP_ITEMEX_H
+
+#include "ZipHeader.h"
+#include "ZipItem.h"
+
+namespace NArchive {
+namespace NZip {
+  
+class CItemEx: public CItem
+{
+public:
+  UInt32 FileHeaderWithNameSize;
+  UInt16 LocalExtraSize;
+  
+  UInt64 GetLocalFullSize() const
+    { return FileHeaderWithNameSize + LocalExtraSize + PackSize +
+      (HasDescriptor() ? NFileHeader::kDataDescriptorSize : 0); };
+  /*
+  UInt64 GetLocalFullSize(bool isZip64) const
+    { return FileHeaderWithNameSize + LocalExtraSize + PackSize +
+    (HasDescriptor() ? (isZip64 ? NFileHeader::kDataDescriptor64Size : NFileHeader::kDataDescriptorSize) : 0); };
+  */
+  UInt64 GetLocalExtraPosition() const
+    { return LocalHeaderPosition + FileHeaderWithNameSize; };
+  UInt64 GetDataPosition() const
+    { return GetLocalExtraPosition() + LocalExtraSize; };
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipOut.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipOut.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipOut.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipOut.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,289 @@
+// ZipOut.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/OffsetStream.h"
+
+#include "ZipOut.h"
+
+namespace NArchive {
+namespace NZip {
+
+void COutArchive::Create(IOutStream *outStream)
+{
+  if (!m_OutBuffer.Create(1 << 16))
+    throw CSystemException(E_OUTOFMEMORY);
+  m_Stream = outStream;
+  m_OutBuffer.SetStream(outStream);
+  m_OutBuffer.Init();
+  m_BasePosition = 0;
+}
+
+void COutArchive::MoveBasePosition(UInt64 distanceToMove)
+{
+  m_BasePosition += distanceToMove; // test overflow
+}
+
+void COutArchive::PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64, bool aesEncryption)
+{
+  m_IsZip64 = isZip64;
+  m_ExtraSize = isZip64 ? (4 + 8 + 8) : 0;
+  if (aesEncryption)
+    m_ExtraSize += 4 + 7;
+  m_LocalFileHeaderSize = 4 + NFileHeader::kLocalBlockSize + fileNameLength + m_ExtraSize;
+}
+
+void COutArchive::PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize, bool aesEncryption)
+{
+  // We test it to 0xF8000000 to support case when compressed size
+  // can be larger than uncompressed size.
+  PrepareWriteCompressedDataZip64(fileNameLength, unPackSize >= 0xF8000000, aesEncryption);
+}
+
+void COutArchive::PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize, bool aesEncryption)
+{
+  bool isUnPack64 = unPackSize >= 0xFFFFFFFF;
+  bool isPack64 = packSize >= 0xFFFFFFFF;
+  bool isZip64 = isPack64 || isUnPack64;
+  PrepareWriteCompressedDataZip64(fileNameLength, isZip64, aesEncryption);
+}
+
+void COutArchive::WriteBytes(const void *buffer, UInt32 size)
+{
+  m_OutBuffer.WriteBytes(buffer, size);
+  m_BasePosition += size;
+}
+
+void COutArchive::WriteByte(Byte b)
+{
+  WriteBytes(&b, 1);
+}
+
+void COutArchive::WriteUInt16(UInt16 value)
+{
+  for (int i = 0; i < 2; i++)
+  {
+    WriteByte((Byte)value);
+    value >>= 8;
+  }
+}
+
+void COutArchive::WriteUInt32(UInt32 value)
+{
+  for (int i = 0; i < 4; i++)
+  {
+    WriteByte((Byte)value);
+    value >>= 8;
+  }
+}
+
+void COutArchive::WriteUInt64(UInt64 value)
+{
+  for (int i = 0; i < 8; i++)
+  {
+    WriteByte((Byte)value);
+    value >>= 8;
+  }
+}
+
+void COutArchive::WriteExtra(const CExtraBlock &extra)
+{
+  if (extra.SubBlocks.Size() != 0)
+  {
+    for (int i = 0; i < extra.SubBlocks.Size(); i++)
+    {
+      const CExtraSubBlock &subBlock = extra.SubBlocks[i];
+      WriteUInt16(subBlock.ID);
+      WriteUInt16((UInt16)subBlock.Data.GetCapacity());
+      WriteBytes(subBlock.Data, (UInt32)subBlock.Data.GetCapacity());
+    }
+  }
+}
+
+void COutArchive::SeekTo(UInt64 offset)
+{
+  HRESULT res = m_Stream->Seek(offset, STREAM_SEEK_SET, NULL);
+  if (res != S_OK)
+    throw CSystemException(res);
+}
+
+void COutArchive::WriteLocalHeader(const CLocalItem &item)
+{
+  SeekTo(m_BasePosition);
+  
+  bool isZip64 = m_IsZip64 || item.PackSize >= 0xFFFFFFFF || item.UnPackSize >= 0xFFFFFFFF;
+  
+  WriteUInt32(NSignature::kLocalFileHeader);
+  {
+    Byte ver = item.ExtractVersion.Version;
+    if (isZip64 && ver < NFileHeader::NCompressionMethod::kExtractVersion_Zip64)
+      ver = NFileHeader::NCompressionMethod::kExtractVersion_Zip64;
+    WriteByte(ver);
+  }
+  WriteByte(item.ExtractVersion.HostOS);
+  WriteUInt16(item.Flags);
+  WriteUInt16(item.CompressionMethod);
+  WriteUInt32(item.Time);
+  WriteUInt32(item.FileCRC);
+  WriteUInt32(isZip64 ? 0xFFFFFFFF: (UInt32)item.PackSize);
+  WriteUInt32(isZip64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize);
+  WriteUInt16((UInt16)item.Name.Length());
+  {
+    UInt16 localExtraSize = (UInt16)((isZip64 ? (4 + 16): 0) + item.LocalExtra.GetSize());
+    if (localExtraSize > m_ExtraSize)
+      throw CSystemException(E_FAIL);
+  }
+  WriteUInt16((UInt16)m_ExtraSize); // test it;
+  WriteBytes((const char *)item.Name, item.Name.Length());
+
+  UInt32 extraPos = 0;
+  if (isZip64)
+  {
+    extraPos += 4 + 16;
+    WriteUInt16(NFileHeader::NExtraID::kZip64);
+    WriteUInt16(16);
+    WriteUInt64(item.UnPackSize);
+    WriteUInt64(item.PackSize);
+  }
+
+  WriteExtra(item.LocalExtra);
+  extraPos += (UInt32)item.LocalExtra.GetSize();
+  for (; extraPos < m_ExtraSize; extraPos++)
+    WriteByte(0);
+
+  m_OutBuffer.FlushWithCheck();
+  MoveBasePosition(item.PackSize);
+  SeekTo(m_BasePosition);
+}
+
+void COutArchive::WriteCentralHeader(const CItem &item)
+{
+  bool isUnPack64 = item.UnPackSize >= 0xFFFFFFFF;
+  bool isPack64 = item.PackSize >= 0xFFFFFFFF;
+  bool isPosition64 = item.LocalHeaderPosition >= 0xFFFFFFFF;
+  bool isZip64  = isPack64 || isUnPack64 || isPosition64;
+  
+  WriteUInt32(NSignature::kCentralFileHeader);
+  WriteByte(item.MadeByVersion.Version);
+  WriteByte(item.MadeByVersion.HostOS);
+  {
+    Byte ver = item.ExtractVersion.Version;
+    if (isZip64 && ver < NFileHeader::NCompressionMethod::kExtractVersion_Zip64)
+      ver = NFileHeader::NCompressionMethod::kExtractVersion_Zip64;
+    WriteByte(ver);
+  }
+  WriteByte(item.ExtractVersion.HostOS);
+  WriteUInt16(item.Flags);
+  WriteUInt16(item.CompressionMethod);
+  WriteUInt32(item.Time);
+  WriteUInt32(item.FileCRC);
+  WriteUInt32(isPack64 ? 0xFFFFFFFF: (UInt32)item.PackSize);
+  WriteUInt32(isUnPack64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize);
+  WriteUInt16((UInt16)item.Name.Length());
+  UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) +  (isPack64 ? 8: 0) + (isPosition64 ? 8: 0));
+  const UInt16 kNtfsExtraSize = 4 + 2 + 2 + (3 * 8);
+  UInt16 centralExtraSize = (UInt16)(isZip64 ? (4 + zip64ExtraSize) : 0) + (item.NtfsTimeIsDefined ? (4 + kNtfsExtraSize) : 0);
+  centralExtraSize = (UInt16)(centralExtraSize + item.CentralExtra.GetSize());
+  WriteUInt16(centralExtraSize); // test it;
+  WriteUInt16((UInt16)item.Comment.GetCapacity());
+  WriteUInt16(0); // DiskNumberStart;
+  WriteUInt16(item.InternalAttributes);
+  WriteUInt32(item.ExternalAttributes);
+  WriteUInt32(isPosition64 ? 0xFFFFFFFF: (UInt32)item.LocalHeaderPosition);
+  WriteBytes((const char *)item.Name, item.Name.Length());
+  if (isZip64)
+  {
+    WriteUInt16(NFileHeader::NExtraID::kZip64);
+    WriteUInt16(zip64ExtraSize);
+    if(isUnPack64)
+      WriteUInt64(item.UnPackSize);
+    if(isPack64)
+      WriteUInt64(item.PackSize);
+    if(isPosition64)
+      WriteUInt64(item.LocalHeaderPosition);
+  }
+  if (item.NtfsTimeIsDefined)
+  {
+    WriteUInt16(NFileHeader::NExtraID::kNTFS);
+    WriteUInt16(kNtfsExtraSize);
+    WriteUInt32(0); // reserved
+    WriteUInt16(NFileHeader::NNtfsExtra::kTagTime);
+    WriteUInt16(8 * 3);
+    WriteUInt32(item.NtfsMTime.dwLowDateTime);
+    WriteUInt32(item.NtfsMTime.dwHighDateTime);
+    WriteUInt32(item.NtfsATime.dwLowDateTime);
+    WriteUInt32(item.NtfsATime.dwHighDateTime);
+    WriteUInt32(item.NtfsCTime.dwLowDateTime);
+    WriteUInt32(item.NtfsCTime.dwHighDateTime);
+  }
+  WriteExtra(item.CentralExtra);
+  if (item.Comment.GetCapacity() > 0)
+    WriteBytes(item.Comment, (UInt32)item.Comment.GetCapacity());
+}
+
+void COutArchive::WriteCentralDir(const CObjectVector<CItem> &items, const CByteBuffer *comment)
+{
+  SeekTo(m_BasePosition);
+  
+  UInt64 cdOffset = GetCurrentPosition();
+  for(int i = 0; i < items.Size(); i++)
+    WriteCentralHeader(items[i]);
+  UInt64 cd64EndOffset = GetCurrentPosition();
+  UInt64 cdSize = cd64EndOffset - cdOffset;
+  bool cdOffset64 = cdOffset >= 0xFFFFFFFF;
+  bool cdSize64 = cdSize >= 0xFFFFFFFF;
+  bool items64 = items.Size() >= 0xFFFF;
+  bool isZip64 = (cdOffset64 || cdSize64 || items64);
+
+  if (isZip64)
+  {
+    WriteUInt32(NSignature::kZip64EndOfCentralDir);
+    WriteUInt64(kZip64EcdSize); // ThisDiskNumber = 0;
+    WriteUInt16(45); // version
+    WriteUInt16(45); // version
+    WriteUInt32(0); // ThisDiskNumber = 0;
+    WriteUInt32(0); // StartCentralDirectoryDiskNumber;;
+    WriteUInt64((UInt64)items.Size());
+    WriteUInt64((UInt64)items.Size());
+    WriteUInt64((UInt64)cdSize);
+    WriteUInt64((UInt64)cdOffset);
+
+    WriteUInt32(NSignature::kZip64EndOfCentralDirLocator);
+    WriteUInt32(0); // number of the disk with the start of the zip64 end of central directory
+    WriteUInt64(cd64EndOffset);
+    WriteUInt32(1); // total number of disks
+  }
+  WriteUInt32(NSignature::kEndOfCentralDir);
+  WriteUInt16(0); // ThisDiskNumber = 0;
+  WriteUInt16(0); // StartCentralDirectoryDiskNumber;
+  WriteUInt16((UInt16)(items64 ? 0xFFFF: items.Size()));
+  WriteUInt16((UInt16)(items64 ? 0xFFFF: items.Size()));
+  WriteUInt32(cdSize64 ? 0xFFFFFFFF: (UInt32)cdSize);
+  WriteUInt32(cdOffset64 ? 0xFFFFFFFF: (UInt32)cdOffset);
+  UInt32 commentSize = (UInt32)(comment ? comment->GetCapacity() : 0);
+  WriteUInt16((UInt16)commentSize);
+  if (commentSize > 0)
+    WriteBytes((const Byte *)*comment, commentSize);
+  m_OutBuffer.FlushWithCheck();
+}
+
+void COutArchive::CreateStreamForCompressing(IOutStream **outStream)
+{
+  COffsetOutStream *streamSpec = new COffsetOutStream;
+  CMyComPtr<IOutStream> tempStream(streamSpec);
+  streamSpec->Init(m_Stream, m_BasePosition + m_LocalFileHeaderSize);
+  *outStream = tempStream.Detach();
+}
+
+void COutArchive::SeekToPackedDataPosition()
+{
+  SeekTo(m_BasePosition + m_LocalFileHeaderSize);
+}
+
+void COutArchive::CreateStreamForCopying(ISequentialOutStream **outStream)
+{
+  CMyComPtr<ISequentialOutStream> tempStream(m_Stream);
+  *outStream = tempStream.Detach();
+}
+
+}}

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipOut.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipOut.h?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipOut.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipOut.h Sun Dec 16 23:23:25 2012
@@ -0,0 +1,56 @@
+// ZipOut.h
+
+#ifndef __ZIP_OUT_H
+#define __ZIP_OUT_H
+
+#include "Common/MyCom.h"
+
+#include "../../IStream.h"
+#include "../../Common/OutBuffer.h"
+
+#include "ZipItem.h"
+
+namespace NArchive {
+namespace NZip {
+
+// can throw CSystemException and COutBufferException
+  
+class COutArchive
+{
+  CMyComPtr<IOutStream> m_Stream;
+  COutBuffer m_OutBuffer;
+
+  UInt64 m_BasePosition;
+  UInt32 m_LocalFileHeaderSize;
+  UInt32 m_ExtraSize;
+  bool m_IsZip64;
+
+  void WriteBytes(const void *buffer, UInt32 size);
+  void WriteByte(Byte b);
+  void WriteUInt16(UInt16 value);
+  void WriteUInt32(UInt32 value);
+  void WriteUInt64(UInt64 value);
+
+  void WriteExtraHeader(const CItem &item);
+  void WriteCentralHeader(const CItem &item);
+  void WriteExtra(const CExtraBlock &extra);
+  void SeekTo(UInt64 offset);
+public:
+  void Create(IOutStream *outStream);
+  void MoveBasePosition(UInt64 distanceToMove);
+  UInt64 GetCurrentPosition() const { return m_BasePosition; };
+  void PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64, bool aesEncryption);
+  void PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize, bool aesEncryption);
+  void PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize, bool aesEncryption);
+  void WriteLocalHeader(const CLocalItem &item);
+
+  void WriteCentralDir(const CObjectVector<CItem> &items, const CByteBuffer *comment);
+
+  void CreateStreamForCompressing(IOutStream **outStream);
+  void CreateStreamForCopying(ISequentialOutStream **outStream);
+  void SeekToPackedDataPosition();
+};
+
+}}
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipRegister.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipRegister.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipRegister.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipRegister.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,18 @@
+// ZipRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterArc.h"
+
+#include "ZipHandler.h"
+static IInArchive *CreateArc() { return new NArchive::NZip::CHandler; }
+#ifndef EXTRACT_ONLY
+static IOutArchive *CreateArcOut() { return new NArchive::NZip::CHandler; }
+#else
+#define CreateArcOut 0
+#endif
+
+static CArcInfo g_ArcInfo =
+  { L"zip", L"zip jar xpi odt ods docx xlsx", 0, 1, { 0x50, 0x4B, 0x03, 0x04 }, 4, false, CreateArc, CreateArcOut };
+
+REGISTER_ARC(Zip)

Added: test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipUpdate.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipUpdate.cpp?rev=170306&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipUpdate.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/7zip/CPP/7zip/Archive/Zip/ZipUpdate.cpp Sun Dec 16 23:23:25 2012
@@ -0,0 +1,1076 @@
+// ZipUpdate.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/Alloc.h"
+
+#include "Common/AutoPtr.h"
+#include "Common/Defs.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/Defs.h"
+#include "Windows/Thread.h"
+
+#include "../../Common/CreateCoder.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/OutMemStream.h"
+#include "../../Common/ProgressUtils.h"
+#ifndef _7ZIP_ST
+#include "../../Common/ProgressMt.h"
+#endif
+#include "../../Common/StreamUtils.h"
+
+#include "../../Compress/CopyCoder.h"
+
+#include "ZipAddCommon.h"
+#include "ZipOut.h"
+#include "ZipUpdate.h"
+
+using namespace NWindows;
+using namespace NSynchronization;
+
+namespace NArchive {
+namespace NZip {
+
+static const Byte kHostOS =
+  #ifdef _WIN32
+  NFileHeader::NHostOS::kFAT;
+  #else
+  NFileHeader::NHostOS::kUnix;
+  #endif
+
+static const Byte kMadeByHostOS = kHostOS;
+static const Byte kExtractHostOS = kHostOS;
+
+static const Byte kMethodForDirectory = NFileHeader::NCompressionMethod::kStored;
+
+static HRESULT CopyBlockToArchive(ISequentialInStream *inStream,
+    COutArchive &outArchive, ICompressProgressInfo *progress)
+{
+  CMyComPtr<ISequentialOutStream> outStream;
+  outArchive.CreateStreamForCopying(&outStream);
+  return NCompress::CopyStream(inStream, outStream, progress);
+}
+
+static HRESULT WriteRange(IInStream *inStream, COutArchive &outArchive,
+    const CUpdateRange &range, ICompressProgressInfo *progress)
+{
+  UInt64 position;
+  RINOK(inStream->Seek(range.Position, STREAM_SEEK_SET, &position));
+
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);
+  streamSpec->SetStream(inStream);
+  streamSpec->Init(range.Size);
+
+  RINOK(CopyBlockToArchive(inStreamLimited, outArchive, progress));
+  return progress->SetRatioInfo(&range.Size, &range.Size);
+}
+
+static void SetFileHeader(
+    COutArchive &archive,
+    const CCompressionMethodMode &options,
+    const CUpdateItem &ui,
+    CItem &item)
+{
+  item.UnPackSize = ui.Size;
+  bool isDir;
+
+  item.ClearFlags();
+
+  if (ui.NewProperties)
+  {
+    isDir = ui.IsDir;
+    item.Name = ui.Name;
+    item.SetUtf8(ui.IsUtf8);
+    item.ExternalAttributes = ui.Attributes;
+    item.Time = ui.Time;
+    item.NtfsMTime = ui.NtfsMTime;
+    item.NtfsATime = ui.NtfsATime;
+    item.NtfsCTime = ui.NtfsCTime;
+    item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined;
+  }
+  else
+    isDir = item.IsDir();
+
+  item.LocalHeaderPosition = archive.GetCurrentPosition();
+  item.MadeByVersion.HostOS = kMadeByHostOS;
+  item.MadeByVersion.Version = NFileHeader::NCompressionMethod::kMadeByProgramVersion;
+  
+  item.ExtractVersion.HostOS = kExtractHostOS;
+
+  item.InternalAttributes = 0; // test it
+  item.SetEncrypted(!isDir && options.PasswordIsDefined);
+  if (isDir)
+  {
+    item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir;
+    item.CompressionMethod = kMethodForDirectory;
+    item.PackSize = 0;
+    item.FileCRC = 0; // test it
+  }
+}
+
+static void SetItemInfoFromCompressingResult(const CCompressingResult &compressingResult,
+    bool isAesMode, Byte aesKeyMode, CItem &item)
+{
+  item.ExtractVersion.Version = compressingResult.ExtractVersion;
+  item.CompressionMethod = compressingResult.Method;
+  item.FileCRC = compressingResult.CRC;
+  item.UnPackSize = compressingResult.UnpackSize;
+  item.PackSize = compressingResult.PackSize;
+
+  item.LocalExtra.Clear();
+  item.CentralExtra.Clear();
+
+  if (isAesMode)
+  {
+    CWzAesExtraField wzAesField;
+    wzAesField.Strength = aesKeyMode;
+    wzAesField.Method = compressingResult.Method;
+    item.CompressionMethod = NFileHeader::NCompressionMethod::kWzAES;
+    item.FileCRC = 0;
+    CExtraSubBlock sb;
+    wzAesField.SetSubBlock(sb);
+    item.LocalExtra.SubBlocks.Add(sb);
+    item.CentralExtra.SubBlocks.Add(sb);
+  }
+}
+
+#ifndef _7ZIP_ST
+
+static THREAD_FUNC_DECL CoderThread(void *threadCoderInfo);
+
+struct CThreadInfo
+{
+  #ifdef EXTERNAL_CODECS
+  CMyComPtr<ICompressCodecsInfo> _codecsInfo;
+  const CObjectVector<CCodecInfoEx> *_externalCodecs;
+  #endif
+
+  NWindows::CThread Thread;
+  NWindows::NSynchronization::CAutoResetEvent CompressEvent;
+  NWindows::NSynchronization::CAutoResetEventWFMO CompressionCompletedEvent;
+  bool ExitThread;
+
+  CMtCompressProgress *ProgressSpec;
+  CMyComPtr<ICompressProgressInfo> Progress;
+
+  COutMemStream *OutStreamSpec;
+  CMyComPtr<IOutStream> OutStream;
+  CMyComPtr<ISequentialInStream> InStream;
+
+  CAddCommon Coder;
+  HRESULT Result;
+  CCompressingResult CompressingResult;
+
+  bool IsFree;
+  UInt32 UpdateIndex;
+
+  CThreadInfo(const CCompressionMethodMode &options):
+      ExitThread(false),
+      ProgressSpec(0),
+      OutStreamSpec(0),
+      Coder(options)
+  {}
+  
+  HRESULT CreateEvents(CSynchro *sync)
+  {
+    RINOK(CompressEvent.CreateIfNotCreated());
+    return CompressionCompletedEvent.CreateIfNotCreated(sync);
+  }
+  HRes CreateThread() { return Thread.Create(CoderThread, this); }
+
+  void WaitAndCode();
+  void StopWaitClose()
+  {
+    ExitThread = true;
+    if (OutStreamSpec != 0)
+      OutStreamSpec->StopWriting(E_ABORT);
+    if (CompressEvent.IsCreated())
+      CompressEvent.Set();
+    Thread.Wait();
+    Thread.Close();
+  }
+
+};
+
+void CThreadInfo::WaitAndCode()
+{
+  for (;;)
+  {
+    CompressEvent.Lock();
+    if (ExitThread)
+      return;
+    Result = Coder.Compress(
+        #ifdef EXTERNAL_CODECS
+        _codecsInfo, _externalCodecs,
+        #endif
+        InStream, OutStream, Progress, CompressingResult);
+    if (Result == S_OK && Progress)
+      Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize);
+    CompressionCompletedEvent.Set();
+  }
+}
+
+static THREAD_FUNC_DECL CoderThread(void *threadCoderInfo)
+{
+  ((CThreadInfo *)threadCoderInfo)->WaitAndCode();
+  return 0;
+}
+
+class CThreads
+{
+public:
+  CObjectVector<CThreadInfo> Threads;
+  ~CThreads()
+  {
+    for (int i = 0; i < Threads.Size(); i++)
+      Threads[i].StopWaitClose();
+  }
+};
+
+struct CMemBlocks2: public CMemLockBlocks
+{
+  CCompressingResult CompressingResult;
+  bool Defined;
+  bool Skip;
+  CMemBlocks2(): Defined(false), Skip(false) {}
+};
+
+class CMemRefs
+{
+public:
+  CMemBlockManagerMt *Manager;
+  CObjectVector<CMemBlocks2> Refs;
+  CMemRefs(CMemBlockManagerMt *manager): Manager(manager) {} ;
+  ~CMemRefs()
+  {
+    for (int i = 0; i < Refs.Size(); i++)
+      Refs[i].FreeOpt(Manager);
+  }
+};
+
+class CMtProgressMixer2:
+  public ICompressProgressInfo,
+  public CMyUnknownImp
+{
+  UInt64 ProgressOffset;
+  UInt64 InSizes[2];
+  UInt64 OutSizes[2];
+  CMyComPtr<IProgress> Progress;
+  CMyComPtr<ICompressProgressInfo> RatioProgress;
+  bool _inSizeIsMain;
+public:
+  NWindows::NSynchronization::CCriticalSection CriticalSection;
+  MY_UNKNOWN_IMP
+  void Create(IProgress *progress, bool inSizeIsMain);
+  void SetProgressOffset(UInt64 progressOffset);
+  HRESULT SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize);
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+void CMtProgressMixer2::Create(IProgress *progress, bool inSizeIsMain)
+{
+  Progress = progress;
+  Progress.QueryInterface(IID_ICompressProgressInfo, &RatioProgress);
+  _inSizeIsMain = inSizeIsMain;
+  ProgressOffset = InSizes[0] = InSizes[1] = OutSizes[0] = OutSizes[1] = 0;
+}
+
+void CMtProgressMixer2::SetProgressOffset(UInt64 progressOffset)
+{
+  CriticalSection.Enter();
+  InSizes[1] = OutSizes[1] = 0;
+  ProgressOffset = progressOffset;
+  CriticalSection.Leave();
+}
+
+HRESULT CMtProgressMixer2::SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize)
+{
+  NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
+  if (index == 0 && RatioProgress)
+  {
+    RINOK(RatioProgress->SetRatioInfo(inSize, outSize));
+  }
+  if (inSize != 0)
+    InSizes[index] = *inSize;
+  if (outSize != 0)
+    OutSizes[index] = *outSize;
+  UInt64 v = ProgressOffset + (_inSizeIsMain  ?
+      (InSizes[0] + InSizes[1]) :
+      (OutSizes[0] + OutSizes[1]));
+  return Progress->SetCompleted(&v);
+}
+
+STDMETHODIMP CMtProgressMixer2::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
+{
+  return SetRatioInfo(0, inSize, outSize);
+}
+
+class CMtProgressMixer:
+  public ICompressProgressInfo,
+  public CMyUnknownImp
+{
+public:
+  CMtProgressMixer2 *Mixer2;
+  CMyComPtr<ICompressProgressInfo> RatioProgress;
+  void Create(IProgress *progress, bool inSizeIsMain);
+  MY_UNKNOWN_IMP
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+void CMtProgressMixer::Create(IProgress *progress, bool inSizeIsMain)
+{
+  Mixer2 = new CMtProgressMixer2;
+  RatioProgress = Mixer2;
+  Mixer2->Create(progress, inSizeIsMain);
+}
+
+STDMETHODIMP CMtProgressMixer::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
+{
+  return Mixer2->SetRatioInfo(1, inSize, outSize);
+}
+
+
+#endif
+
+
+static HRESULT UpdateItemOldData(COutArchive &archive,
+    IInStream *inStream,
+    const CUpdateItem &ui, CItemEx &item,
+    /* bool izZip64, */
+    ICompressProgressInfo *progress,
+    UInt64 &complexity)
+{
+  if (ui.NewProperties)
+  {
+    if (item.HasDescriptor())
+      return E_NOTIMPL;
+    
+    // use old name size.
+    // CUpdateRange range(item.GetLocalExtraPosition(), item.LocalExtraSize + item.PackSize);
+    CUpdateRange range(item.GetDataPosition(), item.PackSize);
+    
+    // item.ExternalAttributes = ui.Attributes;
+    // Test it
+    item.Name = ui.Name;
+    item.SetUtf8(ui.IsUtf8);
+    item.Time = ui.Time;
+    item.NtfsMTime = ui.NtfsMTime;
+    item.NtfsATime = ui.NtfsATime;
+    item.NtfsCTime = ui.NtfsCTime;
+    item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined;
+
+    item.CentralExtra.RemoveUnknownSubBlocks();
+    item.LocalExtra.RemoveUnknownSubBlocks();
+    
+    archive.PrepareWriteCompressedData2((UInt16)item.Name.Length(), item.UnPackSize, item.PackSize, item.LocalExtra.HasWzAesField());
+    item.LocalHeaderPosition = archive.GetCurrentPosition();
+    archive.SeekToPackedDataPosition();
+    RINOK(WriteRange(inStream, archive, range, progress));
+    complexity += range.Size;
+    archive.WriteLocalHeader(item);
+  }
+  else
+  {
+    CUpdateRange range(item.LocalHeaderPosition, item.GetLocalFullSize());
+    
+    // set new header position
+    item.LocalHeaderPosition = archive.GetCurrentPosition();
+    
+    RINOK(WriteRange(inStream, archive, range, progress));
+    complexity += range.Size;
+    archive.MoveBasePosition(range.Size);
+  }
+  return S_OK;
+}
+
+static void WriteDirHeader(COutArchive &archive, const CCompressionMethodMode *options,
+    const CUpdateItem &ui, CItemEx &item)
+{
+  SetFileHeader(archive, *options, ui, item);
+  archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsAesMode);
+  archive.WriteLocalHeader(item);
+}
+
+static HRESULT Update2St(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    COutArchive &archive,
+    CInArchive *inArchive,
+    IInStream *inStream,
+    const CObjectVector<CItemEx> &inputItems,
+    const CObjectVector<CUpdateItem> &updateItems,
+    const CCompressionMethodMode *options,
+    const CByteBuffer *comment,
+    IArchiveUpdateCallback *updateCallback)
+{
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(updateCallback, true);
+
+  CAddCommon compressor(*options);
+  
+  CObjectVector<CItem> items;
+  UInt64 unpackSizeTotal = 0, packSizeTotal = 0;
+
+  for (int itemIndex = 0; itemIndex < updateItems.Size(); itemIndex++)
+  {
+    lps->InSize = unpackSizeTotal;
+    lps->OutSize = packSizeTotal;
+    RINOK(lps->SetCur());
+    const CUpdateItem &ui = updateItems[itemIndex];
+    CItemEx item;
+    if (!ui.NewProperties || !ui.NewData)
+    {
+      item = inputItems[ui.IndexInArchive];
+      if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK)
+        return E_NOTIMPL;
+    }
+
+    if (ui.NewData)
+    {
+      bool isDir = ((ui.NewProperties) ? ui.IsDir : item.IsDir());
+      if (isDir)
+      {
+        WriteDirHeader(archive, options, ui, item);
+      }
+      else
+      {
+        CMyComPtr<ISequentialInStream> fileInStream;
+        HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);
+        if (res == S_FALSE)
+        {
+          lps->ProgressOffset += ui.Size;
+          RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+          continue;
+        }
+        RINOK(res);
+
+        // file Size can be 64-bit !!!
+        SetFileHeader(archive, *options, ui, item);
+        archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsAesMode);
+        CCompressingResult compressingResult;
+        CMyComPtr<IOutStream> outStream;
+        archive.CreateStreamForCompressing(&outStream);
+        RINOK(compressor.Compress(
+            EXTERNAL_CODECS_LOC_VARS
+            fileInStream, outStream, progress, compressingResult));
+        SetItemInfoFromCompressingResult(compressingResult, options->IsAesMode, options->AesKeyMode, item);
+        archive.WriteLocalHeader(item);
+        RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+        unpackSizeTotal += item.UnPackSize;
+        packSizeTotal += item.PackSize;
+      }
+    }
+    else
+    {
+      UInt64 complexity = 0;
+      lps->SendRatio = false;
+      RINOK(UpdateItemOldData(archive, inStream, ui, item, progress, complexity));
+      lps->SendRatio = true;
+      lps->ProgressOffset += complexity;
+    }
+    items.Add(item);
+    lps->ProgressOffset += NFileHeader::kLocalBlockSize;
+  }
+  archive.WriteCentralDir(items, comment);
+  return S_OK;
+}
+
+static HRESULT Update2(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    COutArchive &archive,
+    CInArchive *inArchive,
+    IInStream *inStream,
+    const CObjectVector<CItemEx> &inputItems,
+    const CObjectVector<CUpdateItem> &updateItems,
+    const CCompressionMethodMode *options,
+    const CByteBuffer *comment,
+    IArchiveUpdateCallback *updateCallback)
+{
+  UInt64 complexity = 0;
+  UInt64 numFilesToCompress = 0;
+  UInt64 numBytesToCompress = 0;
+ 
+  int i;
+  for(i = 0; i < updateItems.Size(); i++)
+  {
+    const CUpdateItem &ui = updateItems[i];
+    if (ui.NewData)
+    {
+      complexity += ui.Size;
+      numBytesToCompress += ui.Size;
+      numFilesToCompress++;
+      /*
+      if (ui.Commented)
+        complexity += ui.CommentRange.Size;
+      */
+    }
+    else
+    {
+      CItemEx inputItem = inputItems[ui.IndexInArchive];
+      if (inArchive->ReadLocalItemAfterCdItemFull(inputItem) != S_OK)
+        return E_NOTIMPL;
+      complexity += inputItem.GetLocalFullSize();
+      // complexity += inputItem.GetCentralExtraPlusCommentSize();
+    }
+    complexity += NFileHeader::kLocalBlockSize;
+    complexity += NFileHeader::kCentralBlockSize;
+  }
+
+  if (comment)
+    complexity += comment->GetCapacity();
+  complexity++; // end of central
+  updateCallback->SetTotal(complexity);
+
+  CAddCommon compressor(*options);
+  
+  complexity = 0;
+  
+  #ifndef _7ZIP_ST
+
+  const size_t kNumMaxThreads = (1 << 10);
+  UInt32 numThreads = options->NumThreads;
+  if (numThreads > kNumMaxThreads)
+    numThreads = kNumMaxThreads;
+  
+  const size_t kMemPerThread = (1 << 25);
+  const size_t kBlockSize = 1 << 16;
+
+  CCompressionMethodMode options2;
+  if (options != 0)
+    options2 = *options;
+
+  bool mtMode = ((options != 0) && (numThreads > 1));
+
+  if (numFilesToCompress <= 1)
+    mtMode = false;
+
+  if (mtMode)
+  {
+    Byte method = options->MethodSequence.Front();
+    if (method == NFileHeader::NCompressionMethod::kStored && !options->PasswordIsDefined)
+      mtMode = false;
+    if (method == NFileHeader::NCompressionMethod::kBZip2)
+    {
+      UInt64 averageSize = numBytesToCompress / numFilesToCompress;
+      UInt32 blockSize = options->DicSize;
+      if (blockSize == 0)
+        blockSize = 1;
+      UInt64 averageNumberOfBlocks = averageSize / blockSize;
+      UInt32 numBZip2Threads = 32;
+      if (averageNumberOfBlocks < numBZip2Threads)
+        numBZip2Threads = (UInt32)averageNumberOfBlocks;
+      if (numBZip2Threads < 1)
+        numBZip2Threads = 1;
+      numThreads = numThreads / numBZip2Threads;
+      options2.NumThreads = numBZip2Threads;
+      if (numThreads <= 1)
+        mtMode = false;
+    }
+    if (method == NFileHeader::NCompressionMethod::kLZMA)
+    {
+      UInt32 numLZMAThreads = (options->Algo > 0 ? 2 : 1);
+      numThreads /= numLZMAThreads;
+      options2.NumThreads = numLZMAThreads;
+      if (numThreads <= 1)
+        mtMode = false;
+    }
+  }
+
+  if (!mtMode)
+  #endif
+    return Update2St(
+        EXTERNAL_CODECS_LOC_VARS
+        archive, inArchive,inStream,
+        inputItems, updateItems, options, comment, updateCallback);
+
+
+  #ifndef _7ZIP_ST
+
+  // Warning : before memManager, threads and compressingCompletedEvents
+  // in order to have a "good" order for the destructor
+  NWindows::NSynchronization::CSynchro synchroForCompressingCompletedEvents;
+  synchroForCompressingCompletedEvents.Create();
+  NWindows::NSynchronization::CSynchro synchroForOutStreamSpec;
+  synchroForOutStreamSpec.Create();
+  
+
+  CObjectVector<CItem> items;
+
+  CMtProgressMixer *mtProgressMixerSpec = new CMtProgressMixer;
+  CMyComPtr<ICompressProgressInfo> progress = mtProgressMixerSpec;
+  mtProgressMixerSpec->Create(updateCallback, true);
+
+  CMtCompressProgressMixer mtCompressProgressMixer;
+  mtCompressProgressMixer.Init(numThreads, mtProgressMixerSpec->RatioProgress);
+
+  CMemBlockManagerMt memManager(kBlockSize);
+  CMemRefs refs(&memManager);
+
+  CThreads threads;
+  CRecordVector<HANDLE> compressingCompletedEvents;
+  CRecordVector<int> threadIndices;  // list threads in order of updateItems
+
+  {
+    RINOK(memManager.AllocateSpaceAlways(&synchroForOutStreamSpec,(size_t)numThreads * (kMemPerThread / kBlockSize)));
+    for(i = 0; i < updateItems.Size(); i++)
+      refs.Refs.Add(CMemBlocks2());
+
+    UInt32 i;
+    for (i = 0; i < numThreads; i++)
+      threads.Threads.Add(CThreadInfo(options2));
+
+    for (i = 0; i < numThreads; i++)
+    {
+      CThreadInfo &threadInfo = threads.Threads[i];
+      #ifdef EXTERNAL_CODECS
+      threadInfo._codecsInfo = codecsInfo;
+      threadInfo._externalCodecs = externalCodecs;
+      #endif
+      RINOK(threadInfo.CreateEvents(&synchroForCompressingCompletedEvents));
+      threadInfo.OutStreamSpec = new COutMemStream(&memManager);
+      RINOK(threadInfo.OutStreamSpec->CreateEvents(&synchroForOutStreamSpec));
+      threadInfo.OutStream = threadInfo.OutStreamSpec;
+      threadInfo.IsFree = true;
+      threadInfo.ProgressSpec = new CMtCompressProgress();
+      threadInfo.Progress = threadInfo.ProgressSpec;
+      threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, (int)i);
+      RINOK(threadInfo.CreateThread());
+    }
+  }
+  int mtItemIndex = 0;
+
+  int itemIndex = 0;
+  int lastRealStreamItemIndex = -1;
+
+  while (itemIndex < updateItems.Size())
+  {
+    if ((UInt32)threadIndices.Size() < numThreads && mtItemIndex < updateItems.Size())
+    {
+      const CUpdateItem &ui = updateItems[mtItemIndex++];
+      if (!ui.NewData)
+        continue;
+      CItemEx item;
+      if (ui.NewProperties)
+      {
+        if (ui.IsDir)
+          continue;
+      }
+      else
+      {
+        item = inputItems[ui.IndexInArchive];
+        if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK)
+          return E_NOTIMPL;
+        if (item.IsDir())
+          continue;
+      }
+      CMyComPtr<ISequentialInStream> fileInStream;
+      {
+        NWindows::NSynchronization::CCriticalSectionLock lock(mtProgressMixerSpec->Mixer2->CriticalSection);
+        HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);
+        if (res == S_FALSE)
+        {
+          complexity += ui.Size;
+          complexity += NFileHeader::kLocalBlockSize;
+          mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);
+          RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+          refs.Refs[mtItemIndex - 1].Skip = true;
+          continue;
+        }
+        RINOK(res);
+        RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+      }
+
+      for (UInt32 i = 0; i < numThreads; i++)
+      {
+        CThreadInfo &threadInfo = threads.Threads[i];
+        if (threadInfo.IsFree)
+        {
+          threadInfo.IsFree = false;
+          threadInfo.InStream = fileInStream;
+
+          // !!!!! we must release ref before sending event
+          // BUG was here in v4.43 and v4.44. It could change ref counter in two threads in same time
+          fileInStream.Release();
+
+          threadInfo.OutStreamSpec->Init();
+          threadInfo.ProgressSpec->Reinit();
+          threadInfo.CompressEvent.Set();
+          threadInfo.UpdateIndex = mtItemIndex - 1;
+
+          compressingCompletedEvents.Add(threadInfo.CompressionCompletedEvent);
+          threadIndices.Add(i);
+          break;
+        }
+      }
+      continue;
+    }
+    
+    if (refs.Refs[itemIndex].Skip)
+    {
+      itemIndex++;
+      continue;
+    }
+
+    const CUpdateItem &ui = updateItems[itemIndex];
+
+    CItemEx item;
+    if (!ui.NewProperties || !ui.NewData)
+    {
+      item = inputItems[ui.IndexInArchive];
+      if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK)
+        return E_NOTIMPL;
+    }
+
+    if (ui.NewData)
+    {
+      bool isDir = ((ui.NewProperties) ? ui.IsDir : item.IsDir());
+      if (isDir)
+      {
+        WriteDirHeader(archive, options, ui, item);
+      }
+      else
+      {
+        if (lastRealStreamItemIndex < itemIndex)
+        {
+          lastRealStreamItemIndex = itemIndex;
+          SetFileHeader(archive, *options, ui, item);
+          // file Size can be 64-bit !!!
+          archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), ui.Size, options->IsAesMode);
+        }
+
+        CMemBlocks2 &memRef = refs.Refs[itemIndex];
+        if (memRef.Defined)
+        {
+          CMyComPtr<IOutStream> outStream;
+          archive.CreateStreamForCompressing(&outStream);
+          memRef.WriteToStream(memManager.GetBlockSize(), outStream);
+          SetItemInfoFromCompressingResult(memRef.CompressingResult,
+              options->IsAesMode, options->AesKeyMode, item);
+          SetFileHeader(archive, *options, ui, item);
+          archive.WriteLocalHeader(item);
+          // RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+          memRef.FreeOpt(&memManager);
+        }
+        else
+        {
+          {
+            CThreadInfo &thread = threads.Threads[threadIndices.Front()];
+            if (!thread.OutStreamSpec->WasUnlockEventSent())
+            {
+              CMyComPtr<IOutStream> outStream;
+              archive.CreateStreamForCompressing(&outStream);
+              thread.OutStreamSpec->SetOutStream(outStream);
+              thread.OutStreamSpec->SetRealStreamMode();
+            }
+          }
+
+          DWORD result = ::WaitForMultipleObjects(compressingCompletedEvents.Size(),
+              &compressingCompletedEvents.Front(), FALSE, INFINITE);
+          int t = (int)(result - WAIT_OBJECT_0);
+          CThreadInfo &threadInfo = threads.Threads[threadIndices[t]];
+          threadInfo.InStream.Release();
+          threadInfo.IsFree = true;
+          RINOK(threadInfo.Result);
+          threadIndices.Delete(t);
+          compressingCompletedEvents.Delete(t);
+          if (t == 0)
+          {
+            RINOK(threadInfo.OutStreamSpec->WriteToRealStream());
+            threadInfo.OutStreamSpec->ReleaseOutStream();
+            SetItemInfoFromCompressingResult(threadInfo.CompressingResult,
+                options->IsAesMode, options->AesKeyMode, item);
+            SetFileHeader(archive, *options, ui, item);
+            archive.WriteLocalHeader(item);
+          }
+          else
+          {
+            CMemBlocks2 &memRef = refs.Refs[threadInfo.UpdateIndex];
+            threadInfo.OutStreamSpec->DetachData(memRef);
+            memRef.CompressingResult = threadInfo.CompressingResult;
+            memRef.Defined = true;
+            continue;
+          }
+        }
+      }
+    }
+    else
+    {
+      RINOK(UpdateItemOldData(archive, inStream, ui, item, progress, complexity));
+    }
+    items.Add(item);
+    complexity += NFileHeader::kLocalBlockSize;
+    mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);
+    itemIndex++;
+  }
+  archive.WriteCentralDir(items, comment);
+  return S_OK;
+  #endif
+}
+
+static const size_t kCacheBlockSize = (1 << 20);
+static const size_t kCacheSize = (kCacheBlockSize << 2);
+static const size_t kCacheMask = (kCacheSize - 1);
+
+class CCacheOutStream:
+  public IOutStream,
+  public CMyUnknownImp
+{
+  CMyComPtr<IOutStream> _stream;
+  Byte *_cache;
+  UInt64 _virtPos;
+  UInt64 _virtSize;
+  UInt64 _phyPos;
+  UInt64 _phySize; // <= _virtSize
+  UInt64 _cachedPos; // (_cachedPos + _cachedSize) <= _virtSize
+  size_t _cachedSize;
+
+  HRESULT MyWrite(size_t size);
+  HRESULT MyWriteBlock()
+  {
+    return MyWrite(kCacheBlockSize - ((size_t)_cachedPos & (kCacheBlockSize - 1)));
+  }
+  HRESULT FlushCache();
+public:
+  CCacheOutStream(): _cache(0) {}
+  ~CCacheOutStream();
+  bool Allocate();
+  HRESULT Init(IOutStream *stream);
+  
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+  STDMETHOD(SetSize)(UInt64 newSize);
+};
+
+bool CCacheOutStream::Allocate()
+{
+  if (!_cache)
+    _cache = (Byte *)::MidAlloc(kCacheSize);
+  return (_cache != NULL);
+}
+
+HRESULT CCacheOutStream::Init(IOutStream *stream)
+{
+  _virtPos = _phyPos = 0;
+  _stream = stream;
+  RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &_virtPos));
+  RINOK(_stream->Seek(0, STREAM_SEEK_END, &_virtSize));
+  RINOK(_stream->Seek(_virtPos, STREAM_SEEK_SET, &_virtPos));
+  _phyPos = _virtPos;
+  _phySize = _virtSize;
+  _cachedPos = 0;
+  _cachedSize = 0;
+  return S_OK;
+}
+
+HRESULT CCacheOutStream::MyWrite(size_t size)
+{
+  while (size != 0 && _cachedSize != 0)
+  {
+    if (_phyPos != _cachedPos)
+    {
+      RINOK(_stream->Seek(_cachedPos, STREAM_SEEK_SET, &_phyPos));
+    }
+    size_t pos = (size_t)_cachedPos & kCacheMask;
+    size_t curSize = MyMin(kCacheSize - pos, _cachedSize);
+    curSize = MyMin(curSize, size);
+    RINOK(WriteStream(_stream, _cache + pos, curSize));
+    _phyPos += curSize;
+    if (_phySize < _phyPos)
+      _phySize = _phyPos;
+    _cachedPos += curSize;
+    _cachedSize -= curSize;
+    size -= curSize;
+  }
+  return S_OK;
+}
+
+HRESULT CCacheOutStream::FlushCache()
+{
+  return MyWrite(_cachedSize);
+}
+
+CCacheOutStream::~CCacheOutStream()
+{
+  FlushCache();
+  if (_virtSize != _phySize)
+    _stream->SetSize(_virtSize);
+  if (_virtPos != _phyPos)
+    _stream->Seek(_virtPos, STREAM_SEEK_SET, NULL);
+  ::MidFree(_cache);
+}
+
+STDMETHODIMP CCacheOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  if (processedSize)
+    *processedSize = 0;
+  if (size == 0)
+    return S_OK;
+
+  UInt64 zerosStart = _virtPos;
+  if (_cachedSize != 0)
+  {
+    if (_virtPos < _cachedPos)
+    {
+      RINOK(FlushCache());
+    }
+    else
+    {
+      UInt64 cachedEnd = _cachedPos + _cachedSize;
+      if (cachedEnd < _virtPos)
+      {
+        if (cachedEnd < _phySize)
+        {
+          RINOK(FlushCache());
+        }
+        else
+          zerosStart = cachedEnd;
+      }
+    }
+  }
+
+  if (_cachedSize == 0 && _phySize < _virtPos)
+    _cachedPos = zerosStart = _phySize;
+
+  if (zerosStart != _virtPos)
+  {
+    // write zeros to [cachedEnd ... _virtPos)
+    
+    for (;;)
+    {
+      UInt64 cachedEnd = _cachedPos + _cachedSize;
+      size_t endPos = (size_t)cachedEnd & kCacheMask;
+      size_t curSize = kCacheSize - endPos;
+      if (curSize > _virtPos - cachedEnd)
+        curSize = (size_t)(_virtPos - cachedEnd);
+      if (curSize == 0)
+        break;
+      while (curSize > (kCacheSize - _cachedSize))
+      {
+        RINOK(MyWriteBlock());
+      }
+      memset(_cache + endPos, 0, curSize);
+      _cachedSize += curSize;
+    }
+  }
+
+  if (_cachedSize == 0)
+    _cachedPos = _virtPos;
+
+  size_t pos = (size_t)_virtPos & kCacheMask;
+  size = (UInt32)MyMin((size_t)size, kCacheSize - pos);
+  UInt64 cachedEnd = _cachedPos + _cachedSize;
+  if (_virtPos != cachedEnd) // _virtPos < cachedEnd
+    size = (UInt32)MyMin((size_t)size, (size_t)(cachedEnd - _virtPos));
+  else
+  {
+    // _virtPos == cachedEnd
+    if (_cachedSize == kCacheSize)
+    {
+      RINOK(MyWriteBlock());
+    }
+    size_t startPos = (size_t)_cachedPos & kCacheMask;
+    if (startPos > pos)
+      size = (UInt32)MyMin((size_t)size, (size_t)(startPos - pos));
+    _cachedSize += size;
+  }
+  memcpy(_cache + pos, data, size);
+  if (processedSize)
+    *processedSize = size;
+  _virtPos += size;
+  if (_virtSize < _virtPos)
+    _virtSize = _virtPos;
+  return S_OK;
+}
+
+STDMETHODIMP CCacheOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+  switch(seekOrigin)
+  {
+    case STREAM_SEEK_SET: _virtPos = offset; break;
+    case STREAM_SEEK_CUR: _virtPos += offset; break;
+    case STREAM_SEEK_END: _virtPos = _virtSize + offset; break;
+    default: return STG_E_INVALIDFUNCTION;
+  }
+  if (newPosition)
+    *newPosition = _virtPos;
+  return S_OK;
+}
+
+STDMETHODIMP CCacheOutStream::SetSize(UInt64 newSize)
+{
+  _virtSize = newSize;
+  if (newSize < _phySize)
+  {
+    RINOK(_stream->SetSize(newSize));
+    _phySize = newSize;
+  }
+  if (newSize <= _cachedPos)
+  {
+    _cachedSize = 0;
+    _cachedPos = newSize;
+  }
+  if (newSize < _cachedPos + _cachedSize)
+    _cachedSize = (size_t)(newSize - _cachedPos);
+  return S_OK;
+}
+
+
+HRESULT Update(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    const CObjectVector<CItemEx> &inputItems,
+    const CObjectVector<CUpdateItem> &updateItems,
+    ISequentialOutStream *seqOutStream,
+    CInArchive *inArchive,
+    CCompressionMethodMode *compressionMethodMode,
+    IArchiveUpdateCallback *updateCallback)
+{
+  CMyComPtr<IOutStream> outStream;
+  {
+    CMyComPtr<IOutStream> outStreamReal;
+    seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStreamReal);
+    if (!outStreamReal)
+      return E_NOTIMPL;
+    CCacheOutStream *cacheStream = new CCacheOutStream();
+    outStream = cacheStream;
+    if (!cacheStream->Allocate())
+      return E_OUTOFMEMORY;
+    RINOK(cacheStream->Init(outStreamReal));
+  }
+
+  if (inArchive)
+  {
+    if (inArchive->ArcInfo.Base != 0 ||
+        inArchive->ArcInfo.StartPosition != 0 ||
+        !inArchive->IsOkHeaders)
+      return E_NOTIMPL;
+  }
+  
+  COutArchive outArchive;
+  outArchive.Create(outStream);
+  /*
+  if (inArchive && inArchive->ArcInfo.StartPosition > 0)
+  {
+    CMyComPtr<ISequentialInStream> inStream;
+    inStream.Attach(inArchive->CreateLimitedStream(0, inArchive->ArcInfo.StartPosition));
+    RINOK(CopyBlockToArchive(inStream, outArchive, NULL));
+    outArchive.MoveBasePosition(inArchive->ArcInfo.StartPosition);
+  }
+  */
+  CMyComPtr<IInStream> inStream;
+  if (inArchive)
+    inStream.Attach(inArchive->CreateStream());
+
+  return Update2(
+      EXTERNAL_CODECS_LOC_VARS
+      outArchive, inArchive, inStream,
+      inputItems, updateItems,
+      compressionMethodMode,
+      inArchive ? &inArchive->ArcInfo.Comment : NULL,
+      updateCallback);
+}
+
+}}





More information about the llvm-commits mailing list