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