void SharedBuffer::markAsMemoryMapped() { ASSERT(!isMemoryMapped()); m_isMemoryMapped = true; unsigned savedSize = size(); clear(); m_size = savedSize; if (m_notifyMemoryMappedCallback) m_notifyMemoryMappedCallback(this, SharedBuffer::Succeeded, m_notifyMemoryMappedCallbackData); }
const Vector<char>& SharedBuffer::buffer() const { #if ENABLE(DISK_IMAGE_CACHE) ASSERT(!isMemoryMapped()); #endif unsigned bufferSize = m_buffer.size(); if (m_size > bufferSize) { m_buffer.resize(m_size); copyBufferAndClear(m_buffer.data() + bufferSize, m_size - bufferSize); } return m_buffer; }
const Vector<char>& SharedBuffer::buffer() const { #if ENABLE(DISK_IMAGE_CACHE) ASSERT(!isMemoryMapped()); #endif unsigned bufferSize = m_buffer->data.size(); if (m_size > bufferSize) { duplicateDataBufferIfNecessary(); m_buffer->data.resize(m_size); copyBufferAndClear(m_buffer->data.data() + bufferSize, m_size - bufferSize); } return m_buffer->data; }
void SharedBuffer::append(const char* data, unsigned length) { ASSERT(!m_purgeableBuffer); #if ENABLE(DISK_IMAGE_CACHE) ASSERT(!isMemoryMapped()); #endif if (!length) return; maybeTransferPlatformData(); #if !USE(NETWORK_CFDATA_ARRAY_CALLBACK) unsigned positionInSegment = offsetInSegment(m_size - m_buffer->data.size()); m_size += length; if (m_size <= segmentSize) { // No need to use segments for small resource data if (m_buffer->data.isEmpty()) m_buffer->data.reserveInitialCapacity(length); appendToDataBuffer(data, length); return; } char* segment; if (!positionInSegment) { segment = allocateSegment(); m_segments.append(segment); } else segment = m_segments.last() + positionInSegment; unsigned segmentFreeSpace = segmentSize - positionInSegment; unsigned bytesToCopy = std::min(length, segmentFreeSpace); for (;;) { memcpy(segment, data, bytesToCopy); if (static_cast<unsigned>(length) == bytesToCopy) break; length -= bytesToCopy; data += bytesToCopy; segment = allocateSegment(); m_segments.append(segment); bytesToCopy = std::min(length, segmentSize); } #else m_size += length; if (m_buffer->data.isEmpty()) m_buffer->data.reserveInitialCapacity(length); appendToDataBuffer(data, length); #endif }
SharedBuffer::MemoryMappingState SharedBuffer::allowToBeMemoryMapped() { if (isMemoryMapped()) return SharedBuffer::SuccessAlreadyMapped; if (isAllowedToBeMemoryMapped()) return SharedBuffer::PreviouslyQueuedForMapping; m_diskImageCacheId = diskImageCache().writeItem(this); if (m_diskImageCacheId == DiskImageCache::invalidDiskCacheId) return SharedBuffer::FailureCacheFull; return SharedBuffer::QueuedForMapping; }
unsigned SharedBuffer::getSomeData(const char*& someData, unsigned position) const { unsigned totalSize = size(); if (position >= totalSize) { someData = 0; return 0; } #if ENABLE(DISK_IMAGE_CACHE) ASSERT(position < size()); if (isMemoryMapped()) { const char* data = static_cast<const char*>(diskImageCache().dataForItem(m_diskImageCacheId)); someData = data + position; return size() - position; } #endif if (hasPlatformData() || 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->data.size(); if (position < consecutiveSize) { someData = m_buffer->data.data() + position; return consecutiveSize - position; } position -= consecutiveSize; #if !USE(NETWORK_CFDATA_ARRAY_CALLBACK) unsigned segments = m_segments.size(); unsigned maxSegmentedSize = segments * segmentSize; unsigned segment = segmentIndex(position); if (segment < segments) { unsigned bytesLeft = totalSize - consecutiveSize; unsigned segmentedSize = std::min(maxSegmentedSize, bytesLeft); unsigned positionInSegment = offsetInSegment(position); someData = m_segments[segment] + positionInSegment; return segment == segments - 1 ? segmentedSize - position : segmentSize - positionInSegment; } ASSERT_NOT_REACHED(); return 0; #else return copySomeDataFromDataArray(someData, position); #endif }
const char* SharedBuffer::data() const { #if ENABLE(DISK_IMAGE_CACHE) if (isMemoryMapped()) return static_cast<const char*>(diskImageCache().dataForItem(m_diskImageCacheId)); #endif if (hasPlatformData()) return platformData(); #if USE(NETWORK_CFDATA_ARRAY_CALLBACK) if (const char* buffer = singleDataArrayBuffer()) return buffer; #endif createPurgeableBuffer(); if (m_purgeableBuffer) return m_purgeableBuffer->data(); return this->buffer().data(); }