nsBufferedStreams.h (5873B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef nsBufferedStreams_h__ 7 #define nsBufferedStreams_h__ 8 9 #include "nsIBufferedStreams.h" 10 #include "nsIInputStream.h" 11 #include "nsIOutputStream.h" 12 #include "nsISafeOutputStream.h" 13 #include "nsISeekableStream.h" 14 #include "nsIStreamBufferAccess.h" 15 #include "nsCOMPtr.h" 16 #include "nsIIPCSerializableInputStream.h" 17 #include "nsIAsyncInputStream.h" 18 #include "nsICloneableInputStream.h" 19 #include "nsIInputStreamLength.h" 20 #include "mozilla/Mutex.h" 21 #include "mozilla/RecursiveMutex.h" 22 23 //////////////////////////////////////////////////////////////////////////////// 24 25 class nsBufferedStream : public nsISeekableStream { 26 public: 27 NS_DECL_THREADSAFE_ISUPPORTS 28 NS_DECL_NSISEEKABLESTREAM 29 NS_DECL_NSITELLABLESTREAM 30 31 nsBufferedStream() = default; 32 33 void Close(); 34 35 protected: 36 virtual ~nsBufferedStream(); 37 38 nsresult Init(nsISupports* stream, uint32_t bufferSize); 39 nsresult GetData(nsISupports** aResult); 40 NS_IMETHOD Fill() = 0; 41 NS_IMETHOD Flush() = 0; 42 43 uint32_t mBufferSize{0}; 44 char* mBuffer MOZ_GUARDED_BY(mBufferMutex){nullptr}; 45 46 mozilla::RecursiveMutex mBufferMutex{"nsBufferedStream::mBufferMutex"}; 47 48 // mBufferStartOffset is the offset relative to the start of mStream. 49 int64_t mBufferStartOffset{0}; 50 51 // mCursor is the read cursor for input streams, or write cursor for 52 // output streams, and is relative to mBufferStartOffset. 53 uint32_t mCursor{0}; 54 55 // mFillPoint is the amount available in the buffer for input streams, 56 // or the high watermark of bytes written into the buffer, and therefore 57 // is relative to mBufferStartOffset. 58 uint32_t mFillPoint{0}; 59 60 nsCOMPtr<nsISupports> mStream; // cast to appropriate subclass 61 62 bool mBufferDisabled{false}; 63 bool mEOF{false}; // True if mStream is at EOF 64 bool mSeekable{true}; 65 uint8_t mGetBufferCount{0}; 66 }; 67 68 //////////////////////////////////////////////////////////////////////////////// 69 70 class nsBufferedInputStream final : public nsBufferedStream, 71 public nsIBufferedInputStream, 72 public nsIStreamBufferAccess, 73 public nsIIPCSerializableInputStream, 74 public nsIAsyncInputStream, 75 public nsIInputStreamCallback, 76 public nsICloneableInputStream, 77 public nsIInputStreamLength, 78 public nsIAsyncInputStreamLength, 79 public nsIInputStreamLengthCallback { 80 public: 81 NS_DECL_ISUPPORTS_INHERITED 82 NS_DECL_NSIINPUTSTREAM 83 NS_DECL_NSIBUFFEREDINPUTSTREAM 84 NS_DECL_NSISTREAMBUFFERACCESS 85 NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM 86 NS_DECL_NSIASYNCINPUTSTREAM 87 NS_DECL_NSIINPUTSTREAMCALLBACK 88 NS_DECL_NSICLONEABLEINPUTSTREAM 89 NS_DECL_NSIINPUTSTREAMLENGTH 90 NS_DECL_NSIASYNCINPUTSTREAMLENGTH 91 NS_DECL_NSIINPUTSTREAMLENGTHCALLBACK 92 93 nsBufferedInputStream() = default; 94 95 static nsresult Create(REFNSIID aIID, void** aResult); 96 97 nsIInputStream* Source() { return (nsIInputStream*)mStream.get(); } 98 99 /** 100 * If there's a reference/pointer to an nsBufferedInputStream BEFORE calling 101 * Init() AND the intent is to ultimately convert/assign that 102 * reference/pointer to an nsIInputStream, DO NOT use that initial 103 * reference/pointer. Instead, use the value of QueryInterface-ing to an 104 * nsIInputStream (and, again, the QueryInterface must be performed after 105 * Init()). This is because nsBufferedInputStream has multiple underlying 106 * nsIInputStreams (one from nsIBufferedInputStream and one from 107 * nsIAsyncInputStream), and the correct base nsIInputStream to use will be 108 * unknown until the final value of mIsAsyncInputStream is set in Init(). 109 * 110 * This method, however, does just that but also hides the QI details and 111 * will assert if called before Init(). 112 */ 113 already_AddRefed<nsIInputStream> GetInputStream(); 114 115 protected: 116 virtual ~nsBufferedInputStream() = default; 117 118 NS_IMETHOD Fill() override; 119 NS_IMETHOD Flush() override { return NS_OK; } // no-op for input streams 120 121 mozilla::Mutex mMutex MOZ_UNANNOTATED{"nsBufferedInputStream::mMutex"}; 122 123 // This value is protected by mutex. 124 nsCOMPtr<nsIInputStreamCallback> mAsyncWaitCallback; 125 126 // This value is protected by mutex. 127 nsCOMPtr<nsIInputStreamLengthCallback> mAsyncInputStreamLengthCallback; 128 129 bool mIsIPCSerializable{true}; 130 bool mIsAsyncInputStream{false}; 131 bool mIsCloneableInputStream{false}; 132 bool mIsInputStreamLength{false}; 133 bool mIsAsyncInputStreamLength{false}; 134 }; 135 136 //////////////////////////////////////////////////////////////////////////////// 137 138 class nsBufferedOutputStream : public nsBufferedStream, 139 public nsISafeOutputStream, 140 public nsIBufferedOutputStream, 141 public nsIStreamBufferAccess { 142 public: 143 NS_DECL_ISUPPORTS_INHERITED 144 NS_DECL_NSIOUTPUTSTREAM 145 NS_DECL_NSISAFEOUTPUTSTREAM 146 NS_DECL_NSIBUFFEREDOUTPUTSTREAM 147 NS_DECL_NSISTREAMBUFFERACCESS 148 149 nsBufferedOutputStream() = default; 150 151 static nsresult Create(REFNSIID aIID, void** aResult); 152 153 nsIOutputStream* Sink() { return (nsIOutputStream*)mStream.get(); } 154 155 protected: 156 virtual ~nsBufferedOutputStream() { nsBufferedOutputStream::Close(); } 157 158 NS_IMETHOD Fill() override { return NS_OK; } // no-op for output streams 159 160 nsCOMPtr<nsISafeOutputStream> mSafeStream; // QI'd from mStream 161 }; 162 163 //////////////////////////////////////////////////////////////////////////////// 164 165 #endif // nsBufferedStreams_h__