1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef nsStreamUtils_h__ 8 #define nsStreamUtils_h__ 9 10 #include "nsCOMPtr.h" 11 #include "nsStringFwd.h" 12 #include "nsIInputStream.h" 13 #include "nsTArray.h" 14 #include "nsIRunnable.h" 15 16 class nsIAsyncInputStream; 17 class nsIOutputStream; 18 class nsIInputStreamCallback; 19 class nsIOutputStreamCallback; 20 class nsIEventTarget; 21 22 /** 23 * A "one-shot" proxy of the OnInputStreamReady callback. The resulting 24 * proxy object's OnInputStreamReady function may only be called once! The 25 * proxy object ensures that the real notify object will be free'd on the 26 * thread corresponding to the given event target regardless of what thread 27 * the proxy object is destroyed on. 28 * 29 * This function is designed to be used to implement AsyncWait when the 30 * aTarget parameter is non-null. 31 * 32 * The optional aPriority parameter allows the input stream runnable events 33 * to be dispatched with a different priority than normal. 34 */ 35 extern already_AddRefed<nsIInputStreamCallback> NS_NewInputStreamReadyEvent( 36 const char* aName, nsIInputStreamCallback* aNotify, nsIEventTarget* aTarget, 37 uint32_t aPriority = nsIRunnablePriority::PRIORITY_NORMAL); 38 39 /** 40 * A "one-shot" proxy of the OnOutputStreamReady callback. The resulting 41 * proxy object's OnOutputStreamReady function may only be called once! The 42 * proxy object ensures that the real notify object will be free'd on the 43 * thread corresponding to the given event target regardless of what thread 44 * the proxy object is destroyed on. 45 * 46 * This function is designed to be used to implement AsyncWait when the 47 * aTarget parameter is non-null. 48 */ 49 extern already_AddRefed<nsIOutputStreamCallback> NS_NewOutputStreamReadyEvent( 50 nsIOutputStreamCallback* aNotify, nsIEventTarget* aTarget); 51 52 /* ------------------------------------------------------------------------- */ 53 54 enum nsAsyncCopyMode { 55 NS_ASYNCCOPY_VIA_READSEGMENTS, 56 NS_ASYNCCOPY_VIA_WRITESEGMENTS 57 }; 58 59 /** 60 * This function is called when a new chunk of data has been copied. The 61 * reported count is the size of the current chunk. 62 */ 63 typedef void (*nsAsyncCopyProgressFun)(void* closure, uint32_t count); 64 65 /** 66 * This function is called when the async copy process completes. The reported 67 * status is NS_OK on success and some error code on failure. 68 */ 69 typedef void (*nsAsyncCopyCallbackFun)(void* closure, nsresult status); 70 71 /** 72 * This function asynchronously copies data from the source to the sink. All 73 * data transfer occurs on the thread corresponding to the given event target. 74 * A null event target is not permitted. 75 * 76 * The copier handles blocking or non-blocking streams transparently. If a 77 * stream operation returns NS_BASE_STREAM_WOULD_BLOCK, then the stream will 78 * be QI'd to nsIAsync{In,Out}putStream and its AsyncWait method will be used 79 * to determine when to resume copying. 80 * 81 * Source and sink are closed by default when copying finishes or when error 82 * occurs. Caller can prevent closing source or sink by setting aCloseSource 83 * or aCloseSink to false. 84 * 85 * Caller can obtain aCopierCtx to be able to cancel copying. 86 */ 87 extern nsresult NS_AsyncCopy( 88 nsIInputStream* aSource, nsIOutputStream* aSink, nsIEventTarget* aTarget, 89 nsAsyncCopyMode aMode = NS_ASYNCCOPY_VIA_READSEGMENTS, 90 uint32_t aChunkSize = 4096, nsAsyncCopyCallbackFun aCallbackFun = nullptr, 91 void* aCallbackClosure = nullptr, bool aCloseSource = true, 92 bool aCloseSink = true, nsISupports** aCopierCtx = nullptr, 93 nsAsyncCopyProgressFun aProgressCallbackFun = nullptr); 94 95 /** 96 * This function cancels copying started by function NS_AsyncCopy. 97 * 98 * @param aCopierCtx 99 * Copier context returned by NS_AsyncCopy. 100 * @param aReason 101 * A failure code indicating why the operation is being canceled. 102 * It is an error to pass a success code. 103 */ 104 extern nsresult NS_CancelAsyncCopy(nsISupports* aCopierCtx, nsresult aReason); 105 106 /** 107 * This function copies all of the available data from the stream (up to at 108 * most aMaxCount bytes) into the given buffer. The buffer is truncated at 109 * the start of the function. 110 * 111 * If an error occurs while reading from the stream or while attempting to 112 * resize the buffer, then the corresponding error code is returned from this 113 * function, and any data that has already been read will be returned in the 114 * output buffer. This allows one to use this function with a non-blocking 115 * input stream that may return NS_BASE_STREAM_WOULD_BLOCK if it only has 116 * partial data available. 117 * 118 * @param aSource 119 * The input stream to read. 120 * @param aMaxCount 121 * The maximum number of bytes to consume from the stream. Pass the 122 * value UINT32_MAX to consume the entire stream. The number of 123 * bytes actually read is given by the length of aBuffer upon return. 124 * @param aBuffer 125 * The string object that will contain the stream data upon return. 126 * Note: The data copied to the string may contain null bytes and may 127 * contain non-ASCII values. 128 */ 129 extern nsresult NS_ConsumeStream(nsIInputStream* aSource, uint32_t aMaxCount, 130 nsACString& aBuffer); 131 132 /** 133 * Just like the above, but consumes into an nsTArray<uint8_t>. 134 */ 135 extern nsresult NS_ConsumeStream(nsIInputStream* aSource, uint32_t aMaxCount, 136 nsTArray<uint8_t>& aBuffer); 137 138 /** 139 * This function tests whether or not the input stream is buffered. A buffered 140 * input stream is one that implements readSegments. The test for this is to 141 * 1/ check whether the input stream implements nsIBufferedInputStream; 142 * 2/ if not, call readSegments, without actually consuming any data from the 143 * stream, to verify that it functions. 144 * 145 * NOTE: If the stream is non-blocking and has no data available yet, then this 146 * test will fail. In that case, we return false even though the test is not 147 * really conclusive. 148 * 149 * PERFORMANCE NOTE: If the stream does not implement nsIBufferedInputStream, 150 * calling readSegments may cause I/O. Therefore, you should avoid calling 151 * this function from the main thread. 152 * 153 * @param aInputStream 154 * The input stream to test. 155 */ 156 extern bool NS_InputStreamIsBuffered(nsIInputStream* aInputStream); 157 158 /** 159 * This function tests whether or not the output stream is buffered. A 160 * buffered output stream is one that implements writeSegments. The test for 161 * this is to: 162 * 1/ check whether the output stream implements nsIBufferedOutputStream; 163 * 2/ if not, call writeSegments, without actually writing any data into 164 * the stream, to verify that it functions. 165 * 166 * NOTE: If the stream is non-blocking and has no available space yet, then 167 * this test will fail. In that case, we return false even though the test is 168 * not really conclusive. 169 * 170 * PERFORMANCE NOTE: If the stream does not implement nsIBufferedOutputStream, 171 * calling writeSegments may cause I/O. Therefore, you should avoid calling 172 * this function from the main thread. 173 * 174 * @param aOutputStream 175 * The output stream to test. 176 */ 177 extern bool NS_OutputStreamIsBuffered(nsIOutputStream* aOutputStream); 178 179 /** 180 * This function is intended to be passed to nsIInputStream::ReadSegments to 181 * copy data from the nsIInputStream into a nsIOutputStream passed as the 182 * aClosure parameter to the ReadSegments function. 183 * 184 * @see nsIInputStream.idl for a description of this function's parameters. 185 */ 186 extern nsresult NS_CopySegmentToStream(nsIInputStream* aInputStream, 187 void* aClosure, const char* aFromSegment, 188 uint32_t aToOffset, uint32_t aCount, 189 uint32_t* aWriteCount); 190 191 /** 192 * This function is intended to be passed to nsIInputStream::ReadSegments to 193 * copy data from the nsIInputStream into a character buffer passed as the 194 * aClosure parameter to the ReadSegments function. The character buffer 195 * must be at least as large as the aCount parameter passed to ReadSegments. 196 * 197 * @see nsIInputStream.idl for a description of this function's parameters. 198 */ 199 extern nsresult NS_CopySegmentToBuffer(nsIInputStream* aInputStream, 200 void* aClosure, const char* aFromSegment, 201 uint32_t aToOffset, uint32_t aCount, 202 uint32_t* aWriteCount); 203 204 /** 205 * This function is intended to be passed to nsIOutputStream::WriteSegments to 206 * copy data into the nsIOutputStream from a character buffer passed as the 207 * aClosure parameter to the WriteSegments function. 208 * 209 * @see nsIOutputStream.idl for a description of this function's parameters. 210 */ 211 extern nsresult NS_CopyBufferToSegment(nsIOutputStream* aOutputStream, 212 void* aClosure, char* aToSegment, 213 uint32_t aFromOffset, uint32_t aCount, 214 uint32_t* aReadCount); 215 216 /** 217 * This function is intended to be passed to nsIOutputStream::WriteSegments to 218 * copy data into the nsIOutputStream from a nsIInputStream passed as the 219 * aClosure parameter to the WriteSegments function. 220 * 221 * @see nsIOutputStream.idl for a description of this function's parameters. 222 */ 223 extern nsresult NS_CopyStreamToSegment(nsIOutputStream* aOutputStream, 224 void* aClosure, char* aToSegment, 225 uint32_t aFromOffset, uint32_t aCount, 226 uint32_t* aReadCount); 227 228 /** 229 * This function is intended to be passed to nsIInputStream::ReadSegments to 230 * discard data from the nsIInputStream. This can be used to efficiently read 231 * data from the stream without actually copying any bytes. 232 * 233 * @see nsIInputStream.idl for a description of this function's parameters. 234 */ 235 extern nsresult NS_DiscardSegment(nsIInputStream* aInputStream, void* aClosure, 236 const char* aFromSegment, uint32_t aToOffset, 237 uint32_t aCount, uint32_t* aWriteCount); 238 239 /** 240 * This function is intended to be passed to nsIInputStream::ReadSegments to 241 * adjust the aInputStream parameter passed to a consumer's WriteSegmentFun. 242 * The aClosure parameter must be a pointer to a nsWriteSegmentThunk object. 243 * The mStream and mClosure members of that object will be passed to the mFun 244 * function, with the remainder of the parameters being what are passed to 245 * NS_WriteSegmentThunk. 246 * 247 * This function comes in handy when implementing ReadSegments in terms of an 248 * inner stream's ReadSegments. 249 */ 250 extern nsresult NS_WriteSegmentThunk(nsIInputStream* aInputStream, 251 void* aClosure, const char* aFromSegment, 252 uint32_t aToOffset, uint32_t aCount, 253 uint32_t* aWriteCount); 254 255 struct MOZ_STACK_CLASS nsWriteSegmentThunk { 256 nsCOMPtr<nsIInputStream> mStream; 257 nsWriteSegmentFun mFun; 258 void* mClosure; 259 }; 260 261 /** 262 * Read data from aInput and store in aDest. A non-zero aKeep will keep that 263 * many bytes from aDest (from the end). New data is appended after the kept 264 * bytes (if any). aDest's new length on returning from this function is 265 * aKeep + aNewBytes and is guaranteed to be less than or equal to aDest's 266 * current capacity. 267 * @param aDest the array to fill 268 * @param aInput the stream to read from 269 * @param aKeep number of bytes to keep (0 <= aKeep <= aDest.Length()) 270 * @param aNewBytes (out) number of bytes read from aInput or zero if Read() 271 * failed 272 * @return the result from aInput->Read(...) 273 */ 274 extern nsresult NS_FillArray(FallibleTArray<char>& aDest, 275 nsIInputStream* aInput, uint32_t aKeep, 276 uint32_t* aNewBytes); 277 278 /** 279 * Return true if the given stream can be directly cloned. 280 */ 281 extern bool NS_InputStreamIsCloneable(nsIInputStream* aSource); 282 283 /** 284 * Clone the provided source stream in the most efficient way possible. This 285 * first attempts to QI to nsICloneableInputStream to use Clone(). If that is 286 * not supported or its cloneable attribute is false, then a fallback clone is 287 * provided by copying the source to a pipe. In this case the caller must 288 * replace the source stream with the resulting replacement stream. The clone 289 * and the replacement stream are then cloneable using nsICloneableInputStream 290 * without duplicating memory. This fallback clone using the pipe is only 291 * performed if a replacement stream parameter is also passed in. 292 * @param aSource The input stream to clone. 293 * @param aCloneOut Required out parameter to hold resulting clone. 294 * @param aReplacementOut Optional out parameter to hold stream to replace 295 * original source stream after clone. If not 296 * provided then the fallback clone process is not 297 * supported and a non-cloneable source will result 298 * in failure. Replacement streams are non-blocking. 299 * @return NS_OK on successful clone. Error otherwise. 300 */ 301 extern nsresult NS_CloneInputStream(nsIInputStream* aSource, 302 nsIInputStream** aCloneOut, 303 nsIInputStream** aReplacementOut = nullptr); 304 305 /* 306 * This function returns a non-blocking nsIAsyncInputStream. Internally, 307 * different approaches are used based on what |aSource| is and what it 308 * implements. 309 * 310 * Note that this component takes the owninship of aSource. 311 * 312 * If the |aSource| is already a non-blocking and async stream, 313 * |aAsyncInputStream| will be equal to |aSource|. 314 * 315 * Otherwise, if |aSource| is just non-blocking, NonBlockingAsyncInputStream 316 * class is used in order to make it async. 317 * 318 * The last step is to use nsIStreamTransportService and create a pipe in order 319 * to expose a non-blocking async inputStream and read |aSource| data from 320 * a separate thread. 321 * 322 * In case we need to create a pipe, |aCloseWhenDone| will be used to create the 323 * inputTransport, |aFlags|, |aSegmentSize|, |asegmentCount| will be used to 324 * open the inputStream. If true, the input stream will be closed after it has 325 * been read. Read more in nsITransport.idl. 326 */ 327 extern nsresult NS_MakeAsyncNonBlockingInputStream( 328 already_AddRefed<nsIInputStream> aSource, 329 nsIAsyncInputStream** aAsyncInputStream, bool aCloseWhenDone = true, 330 uint32_t aFlags = 0, uint32_t aSegmentSize = 0, uint32_t aSegmentCount = 0); 331 332 #endif // !nsStreamUtils_h__ 333