1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "SimpleBuffer.h"
8 #include <algorithm>
9 
10 namespace mozilla {
11 namespace net {
12 
SimpleBuffer()13 SimpleBuffer::SimpleBuffer() : mStatus(NS_OK), mAvailable(0) {}
14 
Write(char * src,size_t len)15 nsresult SimpleBuffer::Write(char* src, size_t len) {
16   NS_ASSERT_OWNINGTHREAD(SimpleBuffer);
17   if (NS_FAILED(mStatus)) {
18     return mStatus;
19   }
20 
21   while (len > 0) {
22     SimpleBufferPage* p = mBufferList.getLast();
23     if (p && (p->mWriteOffset == SimpleBufferPage::kSimpleBufferPageSize)) {
24       // no room.. make a new page
25       p = nullptr;
26     }
27     if (!p) {
28       p = new (fallible) SimpleBufferPage();
29       if (!p) {
30         mStatus = NS_ERROR_OUT_OF_MEMORY;
31         return mStatus;
32       }
33       mBufferList.insertBack(p);
34     }
35     size_t roomOnPage =
36         SimpleBufferPage::kSimpleBufferPageSize - p->mWriteOffset;
37     size_t toWrite = std::min(roomOnPage, len);
38     memcpy(p->mBuffer + p->mWriteOffset, src, toWrite);
39     src += toWrite;
40     len -= toWrite;
41     p->mWriteOffset += toWrite;
42     mAvailable += toWrite;
43   }
44   return NS_OK;
45 }
46 
Read(char * dest,size_t maxLen)47 size_t SimpleBuffer::Read(char* dest, size_t maxLen) {
48   NS_ASSERT_OWNINGTHREAD(SimpleBuffer);
49   if (NS_FAILED(mStatus)) {
50     return 0;
51   }
52 
53   size_t rv = 0;
54   for (SimpleBufferPage* p = mBufferList.getFirst(); p && (rv < maxLen);
55        p = mBufferList.getFirst()) {
56     size_t avail = p->mWriteOffset - p->mReadOffset;
57     size_t toRead = std::min(avail, (maxLen - rv));
58     memcpy(dest + rv, p->mBuffer + p->mReadOffset, toRead);
59     rv += toRead;
60     p->mReadOffset += toRead;
61     if (p->mReadOffset == p->mWriteOffset) {
62       p->remove();
63       delete p;
64     }
65   }
66 
67   MOZ_ASSERT(mAvailable >= rv);
68   mAvailable -= rv;
69   return rv;
70 }
71 
Available()72 size_t SimpleBuffer::Available() {
73   NS_ASSERT_OWNINGTHREAD(SimpleBuffer);
74   return NS_SUCCEEDED(mStatus) ? mAvailable : 0;
75 }
76 
Clear()77 void SimpleBuffer::Clear() {
78   NS_ASSERT_OWNINGTHREAD(SimpleBuffer);
79   SimpleBufferPage* p;
80   while ((p = mBufferList.popFirst())) {
81     delete p;
82   }
83   mAvailable = 0;
84 }
85 
86 }  // namespace net
87 }  // namespace mozilla
88