1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Mozilla Foundation.
19 : * Portions created by the Initial Developer are Copyright (C) 2010 2011
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Patrick McManus <mcmanus@ducksong.com>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "nsPreloadedStream.h"
40 : #include "nsIRunnable.h"
41 :
42 : #include "nsThreadUtils.h"
43 : #include "nsAlgorithm.h"
44 : #include "prmem.h"
45 :
46 : namespace mozilla {
47 : namespace net {
48 :
49 0 : NS_IMPL_THREADSAFE_ISUPPORTS2(nsPreloadedStream,
50 : nsIInputStream,
51 : nsIAsyncInputStream)
52 :
53 0 : nsPreloadedStream::nsPreloadedStream(nsIAsyncInputStream *aStream,
54 : const char *data, PRUint32 datalen)
55 : : mStream(aStream),
56 : mOffset(0),
57 0 : mLen(datalen)
58 : {
59 0 : mBuf = (char *) moz_xmalloc(datalen);
60 0 : memcpy(mBuf, data, datalen);
61 0 : }
62 :
63 0 : nsPreloadedStream::~nsPreloadedStream()
64 : {
65 0 : moz_free(mBuf);
66 0 : }
67 :
68 : NS_IMETHODIMP
69 0 : nsPreloadedStream::Close()
70 : {
71 0 : mLen = 0;
72 0 : return mStream->Close();
73 : }
74 :
75 :
76 : NS_IMETHODIMP
77 0 : nsPreloadedStream::Available(PRUint32 *_retval NS_OUTPARAM)
78 : {
79 0 : PRUint32 avail = 0;
80 :
81 0 : nsresult rv = mStream->Available(&avail);
82 0 : if (NS_FAILED(rv))
83 0 : return rv;
84 0 : *_retval = avail + mLen;
85 0 : return NS_OK;
86 : }
87 :
88 : NS_IMETHODIMP
89 0 : nsPreloadedStream::Read(char *aBuf, PRUint32 aCount,
90 : PRUint32 *_retval NS_OUTPARAM)
91 : {
92 0 : if (!mLen)
93 0 : return mStream->Read(aBuf, aCount, _retval);
94 :
95 0 : PRUint32 toRead = NS_MIN(mLen, aCount);
96 0 : memcpy(aBuf, mBuf + mOffset, toRead);
97 0 : mOffset += toRead;
98 0 : mLen -= toRead;
99 0 : *_retval = toRead;
100 0 : return NS_OK;
101 : }
102 :
103 : NS_IMETHODIMP
104 0 : nsPreloadedStream::ReadSegments(nsWriteSegmentFun aWriter,
105 : void *aClosure, PRUint32 aCount,
106 : PRUint32 *result)
107 : {
108 0 : if (!mLen)
109 0 : return mStream->ReadSegments(aWriter, aClosure, aCount, result);
110 :
111 0 : *result = 0;
112 0 : while (mLen > 0 && aCount > 0) {
113 0 : PRUint32 toRead = NS_MIN(mLen, aCount);
114 0 : PRUint32 didRead = 0;
115 : nsresult rv;
116 :
117 0 : rv = aWriter(this, aClosure, mBuf + mOffset, *result, toRead, &didRead);
118 :
119 0 : if (NS_FAILED(rv))
120 0 : return NS_OK;
121 :
122 0 : *result += didRead;
123 0 : mOffset += didRead;
124 0 : mLen -= didRead;
125 0 : aCount -= didRead;
126 : }
127 :
128 0 : return NS_OK;
129 : }
130 :
131 : NS_IMETHODIMP
132 0 : nsPreloadedStream::IsNonBlocking(bool *_retval NS_OUTPARAM)
133 : {
134 0 : return mStream->IsNonBlocking(_retval);
135 : }
136 :
137 : NS_IMETHODIMP
138 0 : nsPreloadedStream::CloseWithStatus(nsresult aStatus)
139 : {
140 0 : mLen = 0;
141 0 : return mStream->CloseWithStatus(aStatus);
142 : }
143 :
144 : class RunOnThread : public nsRunnable
145 : {
146 : public:
147 0 : RunOnThread(nsIAsyncInputStream *aStream,
148 : nsIInputStreamCallback *aCallback)
149 : : mStream(aStream),
150 0 : mCallback(aCallback) {}
151 :
152 0 : virtual ~RunOnThread() {}
153 :
154 0 : NS_IMETHOD Run()
155 : {
156 0 : mCallback->OnInputStreamReady(mStream);
157 0 : return NS_OK;
158 : }
159 :
160 : private:
161 : nsCOMPtr<nsIAsyncInputStream> mStream;
162 : nsCOMPtr<nsIInputStreamCallback> mCallback;
163 : };
164 :
165 : NS_IMETHODIMP
166 0 : nsPreloadedStream::AsyncWait(nsIInputStreamCallback *aCallback,
167 : PRUint32 aFlags,
168 : PRUint32 aRequestedCount,
169 : nsIEventTarget *aEventTarget)
170 : {
171 0 : if (!mLen)
172 0 : return mStream->AsyncWait(aCallback, aFlags, aRequestedCount,
173 0 : aEventTarget);
174 :
175 0 : if (!aCallback)
176 0 : return NS_OK;
177 :
178 0 : if (!aEventTarget)
179 0 : return aCallback->OnInputStreamReady(this);
180 :
181 : nsCOMPtr<nsIRunnable> event =
182 0 : new RunOnThread(this, aCallback);
183 0 : return aEventTarget->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
184 : }
185 :
186 : } // namespace net
187 : } // namespace mozilla
|