Source code

Revision control

Other Tools

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