summaryrefslogtreecommitdiffstats
path: root/netwerk/base/nsBufferedStreams.h
blob: 929c54420983bfb26bacbc8e92ada1a701be2d97 (plain)
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
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef nsBufferedStreams_h__
#define nsBufferedStreams_h__

#include "nsIBufferedStreams.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsISafeOutputStream.h"
#include "nsISeekableStream.h"
#include "nsIStreamBufferAccess.h"
#include "nsCOMPtr.h"
#include "nsIIPCSerializableInputStream.h"
#include "nsIAsyncInputStream.h"
#include "nsICloneableInputStream.h"
#include "nsIInputStreamLength.h"
#include "mozilla/Mutex.h"
#include "mozilla/RecursiveMutex.h"

////////////////////////////////////////////////////////////////////////////////

class nsBufferedStream : public nsISeekableStream {
 public:
  NS_DECL_THREADSAFE_ISUPPORTS
  NS_DECL_NSISEEKABLESTREAM
  NS_DECL_NSITELLABLESTREAM

  nsBufferedStream() = default;

  void Close();

 protected:
  virtual ~nsBufferedStream();

  nsresult Init(nsISupports* stream, uint32_t bufferSize);
  nsresult GetData(nsISupports** aResult);
  NS_IMETHOD Fill() = 0;
  NS_IMETHOD Flush() = 0;

  uint32_t mBufferSize{0};
  char* mBuffer MOZ_GUARDED_BY(mBufferMutex){nullptr};

  mozilla::RecursiveMutex mBufferMutex{"nsBufferedStream::mBufferMutex"};

  // mBufferStartOffset is the offset relative to the start of mStream.
  int64_t mBufferStartOffset{0};

  // mCursor is the read cursor for input streams, or write cursor for
  // output streams, and is relative to mBufferStartOffset.
  uint32_t mCursor{0};

  // mFillPoint is the amount available in the buffer for input streams,
  // or the high watermark of bytes written into the buffer, and therefore
  // is relative to mBufferStartOffset.
  uint32_t mFillPoint{0};

  nsCOMPtr<nsISupports> mStream;  // cast to appropriate subclass

  bool mBufferDisabled{false};
  bool mEOF{false};  // True if mStream is at EOF
  bool mSeekable{true};
  uint8_t mGetBufferCount{0};
};

////////////////////////////////////////////////////////////////////////////////

class nsBufferedInputStream final : public nsBufferedStream,
                                    public nsIBufferedInputStream,
                                    public nsIStreamBufferAccess,
                                    public nsIIPCSerializableInputStream,
                                    public nsIAsyncInputStream,
                                    public nsIInputStreamCallback,
                                    public nsICloneableInputStream,
                                    public nsIInputStreamLength,
                                    public nsIAsyncInputStreamLength,
                                    public nsIInputStreamLengthCallback {
 public:
  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_NSIINPUTSTREAM
  NS_DECL_NSIBUFFEREDINPUTSTREAM
  NS_DECL_NSISTREAMBUFFERACCESS
  NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
  NS_DECL_NSIASYNCINPUTSTREAM
  NS_DECL_NSIINPUTSTREAMCALLBACK
  NS_DECL_NSICLONEABLEINPUTSTREAM
  NS_DECL_NSIINPUTSTREAMLENGTH
  NS_DECL_NSIASYNCINPUTSTREAMLENGTH
  NS_DECL_NSIINPUTSTREAMLENGTHCALLBACK

  nsBufferedInputStream() = default;

  static nsresult Create(REFNSIID aIID, void** aResult);

  nsIInputStream* Source() { return (nsIInputStream*)mStream.get(); }

  /**
   * If there's a reference/pointer to an nsBufferedInputStream BEFORE calling
   * Init() AND the intent is to ultimately convert/assign that
   * reference/pointer to an nsIInputStream, DO NOT use that initial
   * reference/pointer. Instead, use the value of QueryInterface-ing to an
   * nsIInputStream (and, again, the QueryInterface must be performed after
   * Init()). This is because nsBufferedInputStream has multiple underlying
   * nsIInputStreams (one from nsIBufferedInputStream and one from
   * nsIAsyncInputStream), and the correct base nsIInputStream to use will be
   * unknown until the final value of mIsAsyncInputStream is set in Init().
   *
   * This method, however, does just that but also hides the QI details and
   * will assert if called before Init().
   */
  already_AddRefed<nsIInputStream> GetInputStream();

 protected:
  virtual ~nsBufferedInputStream() = default;

  NS_IMETHOD Fill() override;
  NS_IMETHOD Flush() override { return NS_OK; }  // no-op for input streams

  mozilla::Mutex mMutex MOZ_UNANNOTATED{"nsBufferedInputStream::mMutex"};

  // This value is protected by mutex.
  nsCOMPtr<nsIInputStreamCallback> mAsyncWaitCallback;

  // This value is protected by mutex.
  nsCOMPtr<nsIInputStreamLengthCallback> mAsyncInputStreamLengthCallback;

  bool mIsIPCSerializable{true};
  bool mIsAsyncInputStream{false};
  bool mIsCloneableInputStream{false};
  bool mIsInputStreamLength{false};
  bool mIsAsyncInputStreamLength{false};
};

////////////////////////////////////////////////////////////////////////////////

class nsBufferedOutputStream : public nsBufferedStream,
                               public nsISafeOutputStream,
                               public nsIBufferedOutputStream,
                               public nsIStreamBufferAccess {
 public:
  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_NSIOUTPUTSTREAM
  NS_DECL_NSISAFEOUTPUTSTREAM
  NS_DECL_NSIBUFFEREDOUTPUTSTREAM
  NS_DECL_NSISTREAMBUFFERACCESS

  nsBufferedOutputStream() = default;

  static nsresult Create(REFNSIID aIID, void** aResult);

  nsIOutputStream* Sink() { return (nsIOutputStream*)mStream.get(); }

 protected:
  virtual ~nsBufferedOutputStream() { nsBufferedOutputStream::Close(); }

  NS_IMETHOD Fill() override { return NS_OK; }  // no-op for output streams

  nsCOMPtr<nsISafeOutputStream> mSafeStream;  // QI'd from mStream
};

////////////////////////////////////////////////////////////////////////////////

#endif  // nsBufferedStreams_h__