diff options
Diffstat (limited to 'netwerk/base/SimpleBuffer.cpp')
-rw-r--r-- | netwerk/base/SimpleBuffer.cpp | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/netwerk/base/SimpleBuffer.cpp b/netwerk/base/SimpleBuffer.cpp new file mode 100644 index 000000000..d0e311f77 --- /dev/null +++ b/netwerk/base/SimpleBuffer.cpp @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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/. */ + +#include "SimpleBuffer.h" +#include <algorithm> + +namespace mozilla { +namespace net { + +SimpleBuffer::SimpleBuffer() + : mStatus(NS_OK) + , mAvailable(0) +{ + mOwningThread = PR_GetCurrentThread(); +} + +nsresult SimpleBuffer::Write(char *src, size_t len) +{ + MOZ_ASSERT(PR_GetCurrentThread() == mOwningThread); + if (NS_FAILED(mStatus)) { + return mStatus; + } + + while (len > 0) { + SimpleBufferPage *p = mBufferList.getLast(); + if (p && (p->mWriteOffset == SimpleBufferPage::kSimpleBufferPageSize)) { + // no room.. make a new page + p = nullptr; + } + if (!p) { + p = new (fallible) SimpleBufferPage(); + if (!p) { + mStatus = NS_ERROR_OUT_OF_MEMORY; + return mStatus; + } + mBufferList.insertBack(p); + } + size_t roomOnPage = SimpleBufferPage::kSimpleBufferPageSize - p->mWriteOffset; + size_t toWrite = std::min(roomOnPage, len); + memcpy(p->mBuffer + p->mWriteOffset, src, toWrite); + src += toWrite; + len -= toWrite; + p->mWriteOffset += toWrite; + mAvailable += toWrite; + } + return NS_OK; +} + +size_t SimpleBuffer::Read(char *dest, size_t maxLen) +{ + MOZ_ASSERT(PR_GetCurrentThread() == mOwningThread); + if (NS_FAILED(mStatus)) { + return 0; + } + + size_t rv = 0; + for (SimpleBufferPage *p = mBufferList.getFirst(); + p && (rv < maxLen); p = mBufferList.getFirst()) { + size_t avail = p->mWriteOffset - p->mReadOffset; + size_t toRead = std::min(avail, (maxLen - rv)); + memcpy(dest + rv, p->mBuffer + p->mReadOffset, toRead); + rv += toRead; + p->mReadOffset += toRead; + if (p->mReadOffset == p->mWriteOffset) { + p->remove(); + delete p; + } + } + + MOZ_ASSERT(mAvailable >= rv); + mAvailable -= rv; + return rv; +} + +size_t SimpleBuffer::Available() +{ + MOZ_ASSERT(PR_GetCurrentThread() == mOwningThread); + return NS_SUCCEEDED(mStatus) ? mAvailable : 0; +} + +void SimpleBuffer::Clear() +{ + MOZ_ASSERT(PR_GetCurrentThread() == mOwningThread); + SimpleBufferPage *p; + while ((p = mBufferList.popFirst())) { + delete p; + } + mAvailable = 0; +} + +} // namespace net +} // namespace mozilla |