annotate src/win32/7zip/7z/CPP/7zip/Archive/Lzh/LzhIn.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
rev   line source
rlm@1 1 // Archive/LzhIn.cpp
rlm@1 2
rlm@1 3 #include "StdAfx.h"
rlm@1 4
rlm@1 5 #include "Common/StringConvert.h"
rlm@1 6 #include "Common/Buffer.h"
rlm@1 7
rlm@1 8 #include "../../Common/StreamUtils.h"
rlm@1 9
rlm@1 10 #include "LzhIn.h"
rlm@1 11
rlm@1 12 namespace NArchive {
rlm@1 13 namespace NLzh {
rlm@1 14
rlm@1 15 HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
rlm@1 16 {
rlm@1 17 size_t realProcessedSize = size;
rlm@1 18 RINOK(ReadStream(m_Stream, data, &realProcessedSize));
rlm@1 19 processedSize = (UInt32)realProcessedSize;
rlm@1 20 m_Position += processedSize;
rlm@1 21 return S_OK;
rlm@1 22 }
rlm@1 23
rlm@1 24 HRESULT CInArchive::CheckReadBytes(void *data, UInt32 size)
rlm@1 25 {
rlm@1 26 UInt32 processedSize;
rlm@1 27 RINOK(ReadBytes(data, size, processedSize));
rlm@1 28 return (processedSize == size) ? S_OK: S_FALSE;
rlm@1 29 }
rlm@1 30
rlm@1 31 HRESULT CInArchive::Open(IInStream *inStream)
rlm@1 32 {
rlm@1 33 RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));
rlm@1 34 m_Stream = inStream;
rlm@1 35 return S_OK;
rlm@1 36 }
rlm@1 37
rlm@1 38 static const Byte *ReadUInt32(const Byte *p, UInt32 &v)
rlm@1 39 {
rlm@1 40 v = 0;
rlm@1 41 for (int i = 0; i < 4; i++)
rlm@1 42 v |= ((UInt32)(*p++) << (i * 8));
rlm@1 43 return p;
rlm@1 44 }
rlm@1 45
rlm@1 46 static const Byte *ReadUInt16(const Byte *p, UInt16 &v)
rlm@1 47 {
rlm@1 48 v = 0;
rlm@1 49 for (int i = 0; i < 2; i++)
rlm@1 50 v |= ((UInt16)(*p++) << (i * 8));
rlm@1 51 return p;
rlm@1 52 }
rlm@1 53
rlm@1 54 static const Byte *ReadString(const Byte *p, size_t size, AString &s)
rlm@1 55 {
rlm@1 56 s.Empty();
rlm@1 57 for (size_t i = 0; i < size; i++)
rlm@1 58 {
rlm@1 59 char c = p[i];
rlm@1 60 if (c == 0)
rlm@1 61 break;
rlm@1 62 s += c;
rlm@1 63 }
rlm@1 64 return p + size;
rlm@1 65 }
rlm@1 66
rlm@1 67 static Byte CalcSum(const Byte *data, size_t size)
rlm@1 68 {
rlm@1 69 Byte sum = 0;
rlm@1 70 for (size_t i = 0; i < size; i++)
rlm@1 71 sum = (Byte)(sum + data[i]);
rlm@1 72 return sum;
rlm@1 73 }
rlm@1 74
rlm@1 75 HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
rlm@1 76 {
rlm@1 77 filled = false;
rlm@1 78
rlm@1 79 UInt32 processedSize;
rlm@1 80 Byte startHeader[2];
rlm@1 81 RINOK(ReadBytes(startHeader, 2, processedSize))
rlm@1 82 if (processedSize == 0)
rlm@1 83 return S_OK;
rlm@1 84 if (processedSize == 1)
rlm@1 85 return (startHeader[0] == 0) ? S_OK: S_FALSE;
rlm@1 86 if (startHeader[0] == 0 && startHeader[1] == 0)
rlm@1 87 return S_OK;
rlm@1 88
rlm@1 89 Byte header[256];
rlm@1 90 const UInt32 kBasicPartSize = 22;
rlm@1 91 RINOK(ReadBytes(header, kBasicPartSize, processedSize));
rlm@1 92 if (processedSize != kBasicPartSize)
rlm@1 93 return (startHeader[0] == 0) ? S_OK: S_FALSE;
rlm@1 94
rlm@1 95 const Byte *p = header;
rlm@1 96 memmove(item.Method, p, kMethodIdSize);
rlm@1 97 if (!item.IsValidMethod())
rlm@1 98 return S_OK;
rlm@1 99 p += kMethodIdSize;
rlm@1 100 p = ReadUInt32(p, item.PackSize);
rlm@1 101 p = ReadUInt32(p, item.Size);
rlm@1 102 p = ReadUInt32(p, item.ModifiedTime);
rlm@1 103 item.Attributes = *p++;
rlm@1 104 item.Level = *p++;
rlm@1 105 if (item.Level > 2)
rlm@1 106 return S_FALSE;
rlm@1 107 UInt32 headerSize;
rlm@1 108 if (item.Level < 2)
rlm@1 109 {
rlm@1 110 headerSize = startHeader[0];
rlm@1 111 if (headerSize < kBasicPartSize)
rlm@1 112 return S_FALSE;
rlm@1 113 UInt32 remain = headerSize - kBasicPartSize;
rlm@1 114 RINOK(CheckReadBytes(header + kBasicPartSize, remain));
rlm@1 115 if (startHeader[1] != CalcSum(header, headerSize))
rlm@1 116 return S_FALSE;
rlm@1 117 size_t nameLength = *p++;
rlm@1 118 if ((p - header) + nameLength + 2 > headerSize)
rlm@1 119 return S_FALSE;
rlm@1 120 p = ReadString(p, nameLength, item.Name);
rlm@1 121 }
rlm@1 122 else
rlm@1 123 headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8);
rlm@1 124 p = ReadUInt16(p, item.CRC);
rlm@1 125 if (item.Level != 0)
rlm@1 126 {
rlm@1 127 if (item.Level == 2)
rlm@1 128 {
rlm@1 129 RINOK(CheckReadBytes(header + kBasicPartSize, 2));
rlm@1 130 }
rlm@1 131 if ((size_t)(p - header) + 3 > headerSize)
rlm@1 132 return S_FALSE;
rlm@1 133 item.OsId = *p++;
rlm@1 134 UInt16 nextSize;
rlm@1 135 p = ReadUInt16(p, nextSize);
rlm@1 136 while (nextSize != 0)
rlm@1 137 {
rlm@1 138 if (nextSize < 3)
rlm@1 139 return S_FALSE;
rlm@1 140 if (item.Level == 1)
rlm@1 141 {
rlm@1 142 if (item.PackSize < nextSize)
rlm@1 143 return S_FALSE;
rlm@1 144 item.PackSize -= nextSize;
rlm@1 145 }
rlm@1 146 CExtension ext;
rlm@1 147 RINOK(CheckReadBytes(&ext.Type, 1))
rlm@1 148 nextSize -= 3;
rlm@1 149 ext.Data.SetCapacity(nextSize);
rlm@1 150 RINOK(CheckReadBytes((Byte *)ext.Data, nextSize))
rlm@1 151 item.Extensions.Add(ext);
rlm@1 152 Byte hdr2[2];
rlm@1 153 RINOK(CheckReadBytes(hdr2, 2));
rlm@1 154 ReadUInt16(hdr2, nextSize);
rlm@1 155 }
rlm@1 156 }
rlm@1 157 item.DataPosition = m_Position;
rlm@1 158 filled = true;
rlm@1 159 return S_OK;
rlm@1 160 }
rlm@1 161
rlm@1 162 HRESULT CInArchive::Skeep(UInt64 numBytes)
rlm@1 163 {
rlm@1 164 UInt64 newPostion;
rlm@1 165 RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion));
rlm@1 166 m_Position += numBytes;
rlm@1 167 if (m_Position != newPostion)
rlm@1 168 return E_FAIL;
rlm@1 169 return S_OK;
rlm@1 170 }
rlm@1 171
rlm@1 172 }}