Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 : #include "nsPreloadedStream.h"
7 : #include "nsIRunnable.h"
8 :
9 : #include "nsThreadUtils.h"
10 : #include <algorithm>
11 :
12 : namespace mozilla {
13 : namespace net {
14 :
15 0 : NS_IMPL_ISUPPORTS(nsPreloadedStream,
16 : nsIInputStream,
17 : nsIAsyncInputStream)
18 :
19 0 : nsPreloadedStream::nsPreloadedStream(nsIAsyncInputStream *aStream,
20 0 : const char *data, uint32_t datalen)
21 : : mStream(aStream),
22 : mOffset(0),
23 0 : mLen(datalen)
24 : {
25 0 : mBuf = (char *) moz_xmalloc(datalen);
26 0 : memcpy(mBuf, data, datalen);
27 0 : }
28 :
29 0 : nsPreloadedStream::~nsPreloadedStream()
30 : {
31 0 : free(mBuf);
32 0 : }
33 :
34 : NS_IMETHODIMP
35 0 : nsPreloadedStream::Close()
36 : {
37 0 : mLen = 0;
38 0 : return mStream->Close();
39 : }
40 :
41 :
42 : NS_IMETHODIMP
43 0 : nsPreloadedStream::Available(uint64_t *_retval)
44 : {
45 0 : uint64_t avail = 0;
46 :
47 0 : nsresult rv = mStream->Available(&avail);
48 0 : if (NS_FAILED(rv))
49 0 : return rv;
50 0 : *_retval = avail + mLen;
51 0 : return NS_OK;
52 : }
53 :
54 : NS_IMETHODIMP
55 0 : nsPreloadedStream::Read(char *aBuf, uint32_t aCount,
56 : uint32_t *_retval)
57 : {
58 0 : if (!mLen)
59 0 : return mStream->Read(aBuf, aCount, _retval);
60 :
61 0 : uint32_t toRead = std::min(mLen, aCount);
62 0 : memcpy(aBuf, mBuf + mOffset, toRead);
63 0 : mOffset += toRead;
64 0 : mLen -= toRead;
65 0 : *_retval = toRead;
66 0 : return NS_OK;
67 : }
68 :
69 : NS_IMETHODIMP
70 0 : nsPreloadedStream::ReadSegments(nsWriteSegmentFun aWriter,
71 : void *aClosure, uint32_t aCount,
72 : uint32_t *result)
73 : {
74 0 : if (!mLen)
75 0 : return mStream->ReadSegments(aWriter, aClosure, aCount, result);
76 :
77 0 : *result = 0;
78 0 : while (mLen > 0 && aCount > 0) {
79 0 : uint32_t toRead = std::min(mLen, aCount);
80 0 : uint32_t didRead = 0;
81 : nsresult rv;
82 :
83 0 : rv = aWriter(this, aClosure, mBuf + mOffset, *result, toRead, &didRead);
84 :
85 0 : if (NS_FAILED(rv))
86 0 : return NS_OK;
87 :
88 0 : *result += didRead;
89 0 : mOffset += didRead;
90 0 : mLen -= didRead;
91 0 : aCount -= didRead;
92 : }
93 :
94 0 : return NS_OK;
95 : }
96 :
97 : NS_IMETHODIMP
98 0 : nsPreloadedStream::IsNonBlocking(bool *_retval)
99 : {
100 0 : return mStream->IsNonBlocking(_retval);
101 : }
102 :
103 : NS_IMETHODIMP
104 0 : nsPreloadedStream::CloseWithStatus(nsresult aStatus)
105 : {
106 0 : mLen = 0;
107 0 : return mStream->CloseWithStatus(aStatus);
108 : }
109 :
110 : class RunOnThread : public Runnable
111 : {
112 : public:
113 0 : RunOnThread(nsIAsyncInputStream* aStream, nsIInputStreamCallback* aCallback)
114 0 : : Runnable("net::RunOnThread")
115 : , mStream(aStream)
116 0 : , mCallback(aCallback)
117 : {
118 0 : }
119 :
120 0 : virtual ~RunOnThread() {}
121 :
122 0 : NS_IMETHOD Run() override
123 : {
124 0 : mCallback->OnInputStreamReady(mStream);
125 0 : return NS_OK;
126 : }
127 :
128 : private:
129 : nsCOMPtr<nsIAsyncInputStream> mStream;
130 : nsCOMPtr<nsIInputStreamCallback> mCallback;
131 : };
132 :
133 : NS_IMETHODIMP
134 0 : nsPreloadedStream::AsyncWait(nsIInputStreamCallback *aCallback,
135 : uint32_t aFlags,
136 : uint32_t aRequestedCount,
137 : nsIEventTarget *aEventTarget)
138 : {
139 0 : if (!mLen)
140 0 : return mStream->AsyncWait(aCallback, aFlags, aRequestedCount,
141 0 : aEventTarget);
142 :
143 0 : if (!aCallback)
144 0 : return NS_OK;
145 :
146 0 : if (!aEventTarget)
147 0 : return aCallback->OnInputStreamReady(this);
148 :
149 : nsCOMPtr<nsIRunnable> event =
150 0 : new RunOnThread(this, aCallback);
151 0 : return aEventTarget->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
152 : }
153 :
154 : } // namespace net
155 9 : } // namespace mozilla
|