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