1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
// IStream.h
#ifndef ZIP7_INC_ISTREAM_H
#define ZIP7_INC_ISTREAM_H
#include "../Common/MyTypes.h"
#include "../Common/MyWindows.h"
#include "IDecl.h"
Z7_PURE_INTERFACES_BEGIN
#define Z7_IFACE_CONSTR_STREAM_SUB(i, base, n) \
Z7_DECL_IFACE_7ZIP_SUB(i, base, 3, n) \
{ Z7_IFACE_COM7_PURE(i) };
#define Z7_IFACE_CONSTR_STREAM(i, n) \
Z7_IFACE_CONSTR_STREAM_SUB(i, IUnknown, n)
/*
ISequentialInStream::Read()
The requirement for caller: (processedSize != NULL).
The callee can allow (processedSize == NULL) for compatibility reasons.
if (size == 0), this function returns S_OK and (*processedSize) is set to 0.
if (size != 0)
{
Partial read is allowed: (*processedSize <= avail_size && *processedSize <= size),
where (avail_size) is the size of remaining bytes in stream.
If (avail_size != 0), this function must read at least 1 byte: (*processedSize > 0).
You must call Read() in loop, if you need to read exact amount of data.
}
If seek pointer before Read() call was changed to position past the end of stream:
if (seek_pointer >= stream_size), this function returns S_OK and (*processedSize) is set to 0.
ERROR CASES:
If the function returns error code, then (*processedSize) is size of
data written to (data) buffer (it can be data before error or data with errors).
The recommended way for callee to work with reading errors:
1) write part of data before error to (data) buffer and return S_OK.
2) return error code for further calls of Read().
*/
#define Z7_IFACEM_ISequentialInStream(x) \
x(Read(void *data, UInt32 size, UInt32 *processedSize))
Z7_IFACE_CONSTR_STREAM(ISequentialInStream, 0x01)
/*
ISequentialOutStream::Write()
The requirement for caller: (processedSize != NULL).
The callee can allow (processedSize == NULL) for compatibility reasons.
if (size != 0)
{
Partial write is allowed: (*processedSize <= size),
but this function must write at least 1 byte: (*processedSize > 0).
You must call Write() in loop, if you need to write exact amount of data.
}
ERROR CASES:
If the function returns error code, then (*processedSize) is size of
data written from (data) buffer.
*/
#define Z7_IFACEM_ISequentialOutStream(x) \
x(Write(const void *data, UInt32 size, UInt32 *processedSize))
Z7_IFACE_CONSTR_STREAM(ISequentialOutStream, 0x02)
#ifdef _WIN32
#ifdef __HRESULT_FROM_WIN32
#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK)
#else
#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK)
#endif
#else
#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK MY_E_ERROR_NEGATIVE_SEEK
#endif
/*
IInStream::Seek() / IOutStream::Seek()
If you seek to position before the beginning of the stream,
Seek() function returns error code:
Recommended error code is __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK).
or STG_E_INVALIDFUNCTION
It is allowed to seek past the end of the stream.
if Seek() returns error, then the value of *newPosition is undefined.
*/
#define Z7_IFACEM_IInStream(x) \
x(Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
Z7_IFACE_CONSTR_STREAM_SUB(IInStream, ISequentialInStream, 0x03)
#define Z7_IFACEM_IOutStream(x) \
x(Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) \
x(SetSize(UInt64 newSize))
Z7_IFACE_CONSTR_STREAM_SUB(IOutStream, ISequentialOutStream, 0x04)
#define Z7_IFACEM_IStreamGetSize(x) \
x(GetSize(UInt64 *size))
Z7_IFACE_CONSTR_STREAM(IStreamGetSize, 0x06)
#define Z7_IFACEM_IOutStreamFinish(x) \
x(OutStreamFinish())
Z7_IFACE_CONSTR_STREAM(IOutStreamFinish, 0x07)
#define Z7_IFACEM_IStreamGetProps(x) \
x(GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib))
Z7_IFACE_CONSTR_STREAM(IStreamGetProps, 0x08)
struct CStreamFileProps
{
UInt64 Size;
UInt64 VolID;
UInt64 FileID_Low;
UInt64 FileID_High;
UInt32 NumLinks;
UInt32 Attrib;
FILETIME CTime;
FILETIME ATime;
FILETIME MTime;
};
#define Z7_IFACEM_IStreamGetProps2(x) \
x(GetProps2(CStreamFileProps *props))
Z7_IFACE_CONSTR_STREAM(IStreamGetProps2, 0x09)
#define Z7_IFACEM_IStreamGetProp(x) \
x(GetProperty(PROPID propID, PROPVARIANT *value)) \
x(ReloadProps())
Z7_IFACE_CONSTR_STREAM(IStreamGetProp, 0x0a)
/*
IStreamSetRestriction::SetRestriction(UInt64 begin, UInt64 end)
It sets region of data in output stream that is restricted.
For restricted region it's expected (or allowed)
to change data with different calls of Write()/SetSize().
Another regions of output stream will be supposed as non-restricted:
- The callee usually doesn't flush the data in restricted region.
- The callee usually can flush data from non-restricted region.
inputs:
(begin > end) is not allowed, and returns E_FAIL;
if (begin == end)
{
it means that there is no region restriction for flushing.
The callee is allowed to flush already written data and
is allowed to flush all data in future calls of
ISequentialOutStream::Write(), but before next call of SetRestriction().
The pair of values (begin == 0 && end == 0) is recommended to
remove all restrictions.
}
if (begin < end)
{
it means that callee must NOT to flush any data in region [begin, end).
The caller is allowed to Seek() to that region and rewrite the
data in that restriction region.
if (end == (UInt64(Int64)-1)
{
there is no upper bound for restricted region.
So non-restricted region will be [0, begin) in that case
}
Note: it's not expected that some already written region was marked as
non-restricted by old call SetRestriction() and later the part of
that region was marked as restricted with new call SetRestriction().
For example, for different calls with non-empty restricted regions:
(begin_new >= begin_old) is expected :
{
SetRestriction(begin_old, ...)
...
SetRestriction(begin_new, ...)
}
}
returns:
- if (begin > end) it return ERROR code (E_FAIL)
- S_OK : if no errors.
- Also the call of SetRestriction() can initiate the flushing of already written data.
So it can return the result of that flushing.
Note: IOutStream::SetSize() also can change the data.
So it's not expected the call
IOutStream::SetSize() to unrestricted already written region.
*/
#define Z7_IFACEM_IStreamSetRestriction(x) \
x(SetRestriction(UInt64 begin, UInt64 end)) \
Z7_IFACE_CONSTR_STREAM(IStreamSetRestriction, 0x10)
Z7_PURE_INTERFACES_END
#endif
|