Mercurial > vba-linux
comparison 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 |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // Archive/LzhIn.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 #include "Common/StringConvert.h" | |
6 #include "Common/Buffer.h" | |
7 | |
8 #include "../../Common/StreamUtils.h" | |
9 | |
10 #include "LzhIn.h" | |
11 | |
12 namespace NArchive { | |
13 namespace NLzh { | |
14 | |
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 } | |
23 | |
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 } | |
30 | |
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 } | |
37 | |
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 } | |
45 | |
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 } | |
53 | |
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 } | |
66 | |
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 } | |
74 | |
75 HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) | |
76 { | |
77 filled = false; | |
78 | |
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; | |
88 | |
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; | |
94 | |
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 } | |
161 | |
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 } | |
171 | |
172 }} |