#include "config.h"
#include "platform/SharedBuffer.h"
-#include "platform/PurgeableBuffer.h"
-#include "wtf/PassOwnPtr.h"
#include "wtf/unicode/Unicode.h"
#include "wtf/unicode/UTF8.h"
#include "wtf/MainThread.h"
#endif
-using namespace std;
-
-namespace WebCore {
+namespace blink {
static const unsigned segmentSize = 0x1000;
static const unsigned segmentPositionMask = 0x0FFF;
SharedBuffer::SharedBuffer()
: m_size(0)
+ , m_buffer(PurgeableVector::NotPurgeable)
{
#ifdef SHARED_BUFFER_STATS
didCreateSharedBuffer(this);
SharedBuffer::SharedBuffer(size_t size)
: m_size(size)
- , m_buffer(size)
+ , m_buffer(PurgeableVector::NotPurgeable)
{
+ m_buffer.reserveCapacity(size);
+ m_buffer.grow(size);
#ifdef SHARED_BUFFER_STATS
didCreateSharedBuffer(this);
#endif
SharedBuffer::SharedBuffer(const char* data, int size)
: m_size(0)
+ , m_buffer(PurgeableVector::NotPurgeable)
{
// FIXME: Use unsigned consistently, and check for invalid casts when calling into SharedBuffer from other code.
if (size < 0)
#endif
}
+SharedBuffer::SharedBuffer(const char* data, unsigned size, PurgeableVector::PurgeableOption purgeable)
+ : m_size(0)
+ , m_buffer(purgeable)
+{
+ append(data, size);
+
+#ifdef SHARED_BUFFER_STATS
+ didCreateSharedBuffer(this);
+#endif
+}
+
SharedBuffer::SharedBuffer(const unsigned char* data, int size)
: m_size(0)
+ , m_buffer(PurgeableVector::NotPurgeable)
{
// FIXME: Use unsigned consistently, and check for invalid casts when calling into SharedBuffer from other code.
if (size < 0)
PassRefPtr<SharedBuffer> SharedBuffer::adoptVector(Vector<char>& vector)
{
RefPtr<SharedBuffer> buffer = create();
- buffer->m_buffer.swap(vector);
+ buffer->m_buffer.adopt(vector);
buffer->m_size = buffer->m_buffer.size();
return buffer.release();
}
-PassRefPtr<SharedBuffer> SharedBuffer::adoptPurgeableBuffer(PassOwnPtr<PurgeableBuffer> purgeableBuffer)
-{
- ASSERT(!purgeableBuffer->isPurgeable());
- RefPtr<SharedBuffer> buffer = create();
- buffer->m_purgeableBuffer = purgeableBuffer;
- return buffer.release();
-}
-
unsigned SharedBuffer::size() const
{
- if (m_purgeableBuffer)
- return m_purgeableBuffer->size();
-
return m_size;
}
-void SharedBuffer::createPurgeableBuffer() const
-{
- if (m_purgeableBuffer)
- return;
-
- m_purgeableBuffer = PurgeableBuffer::create(buffer().data(), m_size);
-}
-
const char* SharedBuffer::data() const
{
- if (m_purgeableBuffer)
- return m_purgeableBuffer->data();
-
- return this->buffer().data();
+ mergeSegmentsIntoBuffer();
+ return m_buffer.data();
}
-void SharedBuffer::moveTo(Vector<char>& result)
-{
- ASSERT(result.isEmpty());
- if (m_purgeableBuffer) {
- result.reserveCapacity(m_purgeableBuffer->size());
- result.append(m_purgeableBuffer->data(), m_purgeableBuffer->size());
- clear();
- return;
- }
-
- unsigned bufferSize = m_buffer.size();
- if (m_size == bufferSize) {
- m_buffer.swap(result);
- clear();
- return;
- }
-
- result.reserveCapacity(m_size);
-
- const char* segment = 0;
- unsigned position = 0;
- while (unsigned segmentSize = getSomeData(segment, position)) {
- result.append(segment, segmentSize);
- position += segmentSize;
- }
- ASSERT(result.size() == m_size);
- clear();
- return;
-}
-
-void SharedBuffer::append(SharedBuffer* data)
+void SharedBuffer::append(PassRefPtr<SharedBuffer> data)
{
const char* segment;
size_t position = 0;
void SharedBuffer::append(const char* data, unsigned length)
{
- ASSERT(!m_purgeableBuffer);
+ ASSERT(isLocked());
if (!length)
return;
+ ASSERT(m_size >= m_buffer.size());
unsigned positionInSegment = offsetInSegment(m_size - m_buffer.size());
m_size += length;
if (m_size <= segmentSize) {
- // No need to use segments for small resource data
- if (m_buffer.isEmpty())
- m_buffer.reserveInitialCapacity(length);
+ // No need to use segments for small resource data.
m_buffer.append(data, length);
return;
}
segment = m_segments.last() + positionInSegment;
unsigned segmentFreeSpace = segmentSize - positionInSegment;
- unsigned bytesToCopy = min(length, segmentFreeSpace);
+ unsigned bytesToCopy = std::min(length, segmentFreeSpace);
for (;;) {
memcpy(segment, data, bytesToCopy);
data += bytesToCopy;
segment = allocateSegment();
m_segments.append(segment);
- bytesToCopy = min(length, segmentSize);
+ bytesToCopy = std::min(length, segmentSize);
}
}
m_segments.clear();
m_size = 0;
-
m_buffer.clear();
- m_purgeableBuffer.clear();
}
PassRefPtr<SharedBuffer> SharedBuffer::copy() const
{
RefPtr<SharedBuffer> clone(adoptRef(new SharedBuffer));
- if (m_purgeableBuffer) {
- clone->append(data(), size());
- return clone.release();
- }
-
clone->m_size = m_size;
clone->m_buffer.reserveCapacity(m_size);
clone->m_buffer.append(m_buffer.data(), m_buffer.size());
return clone.release();
}
-PassOwnPtr<PurgeableBuffer> SharedBuffer::releasePurgeableBuffer()
-{
- ASSERT(hasOneRef());
- return m_purgeableBuffer.release();
-}
-
-const Vector<char>& SharedBuffer::buffer() const
+void SharedBuffer::mergeSegmentsIntoBuffer() const
{
unsigned bufferSize = m_buffer.size();
if (m_size > bufferSize) {
- m_buffer.resize(m_size);
- char* destination = m_buffer.data() + bufferSize;
+ m_buffer.reserveCapacity(m_size);
unsigned bytesLeft = m_size - bufferSize;
for (unsigned i = 0; i < m_segments.size(); ++i) {
- unsigned bytesToCopy = min(bytesLeft, segmentSize);
- memcpy(destination, m_segments[i], bytesToCopy);
- destination += bytesToCopy;
+ unsigned bytesToCopy = std::min(bytesLeft, segmentSize);
+ m_buffer.append(m_segments[i], bytesToCopy);
bytesLeft -= bytesToCopy;
freeSegment(m_segments[i]);
}
m_segments.clear();
}
- return m_buffer;
}
unsigned SharedBuffer::getSomeData(const char*& someData, unsigned position) const
{
+ ASSERT(isLocked());
unsigned totalSize = size();
if (position >= totalSize) {
someData = 0;
return 0;
}
- if (m_purgeableBuffer) {
- ASSERT_WITH_SECURITY_IMPLICATION(position < size());
- someData = data() + position;
- return totalSize - position;
- }
-
ASSERT_WITH_SECURITY_IMPLICATION(position < m_size);
unsigned consecutiveSize = m_buffer.size();
if (position < consecutiveSize) {
unsigned segment = segmentIndex(position);
if (segment < segments) {
unsigned bytesLeft = totalSize - consecutiveSize;
- unsigned segmentedSize = min(maxSegmentedSize, bytesLeft);
+ unsigned segmentedSize = std::min(maxSegmentedSize, bytesLeft);
unsigned positionInSegment = offsetInSegment(position);
someData = m_segments[segment] + positionInSegment;
{
RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::createUninitialized(static_cast<unsigned>(size()), 1);
+ if (!arrayBuffer)
+ return nullptr;
+
const char* segment = 0;
unsigned position = 0;
while (unsigned segmentSize = getSomeData(segment, position)) {
if (position != arrayBuffer->byteLength()) {
ASSERT_NOT_REACHED();
// Don't return the incomplete ArrayBuffer.
- return 0;
+ return nullptr;
}
return arrayBuffer;
}
-} // namespace WebCore
+PassRefPtr<SkData> SharedBuffer::getAsSkData() const
+{
+ unsigned bufferLength = size();
+ SkData* data = SkData::NewUninitialized(bufferLength);
+ char* buffer = static_cast<char*>(data->writable_data());
+ const char* segment = 0;
+ unsigned position = 0;
+ while (unsigned segmentSize = getSomeData(segment, position)) {
+ memcpy(buffer + position, segment, segmentSize);
+ position += segmentSize;
+ }
+
+ if (position != bufferLength) {
+ ASSERT_NOT_REACHED();
+ // Don't return the incomplete SkData.
+ return nullptr;
+ }
+ return adoptRef(data);
+}
+
+bool SharedBuffer::lock()
+{
+ return m_buffer.lock();
+}
+
+void SharedBuffer::unlock()
+{
+ mergeSegmentsIntoBuffer();
+ m_buffer.unlock();
+}
+
+bool SharedBuffer::isLocked() const
+{
+ return m_buffer.isLocked();
+}
+
+} // namespace blink