DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (b6d82b1a6b02)

VCS Links

Line Code
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
/* -*- 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"

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

class nsBufferedStream : public nsISeekableStream {
 public:
  NS_DECL_THREADSAFE_ISUPPORTS
  NS_DECL_NSISEEKABLESTREAM
  NS_DECL_NSITELLABLESTREAM

  nsBufferedStream();

  nsresult 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;
  char* mBuffer;

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

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

  // 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;

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

  bool mBufferDisabled;
  bool mEOF;  // True if mStream is at EOF
  uint8_t mGetBufferCount;
};

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

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();

  static nsresult Create(nsISupports* aOuter, 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;

  template <typename M>
  void SerializeInternal(mozilla::ipc::InputStreamParams& aParams,
                         FileDescriptorArray& aFileDescriptors,
                         bool aDelayedStart, uint32_t aMaxSize,
                         uint32_t* aSizeUsed, M* aManager);

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

  mozilla::Mutex mMutex;

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

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

  bool mIsIPCSerializable;
  bool mIsAsyncInputStream;
  bool mIsCloneableInputStream;
  bool mIsInputStreamLength;
  bool mIsAsyncInputStreamLength;
};

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

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() : nsBufferedStream() {}

  static nsresult Create(nsISupports* aOuter, 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__