SharedBufferCF.cpp [plain text]
#include "config.h"
#include "SharedBuffer.h"
#include "PurgeableBuffer.h"
#include <wtf/cf/TypeCasts.h>
#if ENABLE(DISK_IMAGE_CACHE)
#include "DiskImageCacheIOS.h"
#endif
namespace WebCore {
SharedBuffer::SharedBuffer(CFDataRef cfData)
: m_size(0)
, m_buffer(adoptRef(new DataBuffer))
, m_shouldUsePurgeableMemory(false)
#if ENABLE(DISK_IMAGE_CACHE)
, m_isMemoryMapped(false)
, m_diskImageCacheId(DiskImageCache::invalidDiskCacheId)
, m_notifyMemoryMappedCallback(nullptr)
, m_notifyMemoryMappedCallbackData(nullptr)
#endif
, m_cfData(cfData)
{
}
#if !USE(FOUNDATION)
RetainPtr<CFDataRef> SharedBuffer::createCFData()
{
if (m_cfData)
return m_cfData;
const Vector<char>& contiguousBuffer = buffer();
return adoptCF(CFDataCreate(0, reinterpret_cast<const UInt8*>(contiguousBuffer.data()), contiguousBuffer.size()));
}
#endif
PassRefPtr<SharedBuffer> SharedBuffer::wrapCFData(CFDataRef data)
{
return adoptRef(new SharedBuffer(data));
}
bool SharedBuffer::hasPlatformData() const
{
return m_cfData;
}
const char* SharedBuffer::platformData() const
{
return reinterpret_cast<const char*>(CFDataGetBytePtr(m_cfData.get()));
}
unsigned SharedBuffer::platformDataSize() const
{
return CFDataGetLength(m_cfData.get());
}
void SharedBuffer::maybeTransferPlatformData()
{
if (!m_cfData)
return;
ASSERT(!m_size);
RetainPtr<CFDataRef> cfData = adoptCF(m_cfData.leakRef());
append(reinterpret_cast<const char*>(CFDataGetBytePtr(cfData.get())), CFDataGetLength(cfData.get()));
}
void SharedBuffer::clearPlatformData()
{
m_cfData = 0;
}
void SharedBuffer::tryReplaceContentsWithPlatformBuffer(SharedBuffer* newContents)
{
if (!newContents->m_cfData)
return;
clear();
m_cfData = newContents->m_cfData;
}
bool SharedBuffer::maybeAppendPlatformData(SharedBuffer* newContents)
{
if (size() || !newContents->m_cfData)
return false;
m_cfData = newContents->m_cfData;
return true;
}
#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
PassRefPtr<SharedBuffer> SharedBuffer::wrapCFDataArray(CFArrayRef cfDataArray)
{
return adoptRef(new SharedBuffer(cfDataArray));
}
SharedBuffer::SharedBuffer(CFArrayRef cfDataArray)
: m_size(0)
, m_buffer(adoptRef(new DataBuffer))
, m_shouldUsePurgeableMemory(false)
#if ENABLE(DISK_IMAGE_CACHE)
, m_isMemoryMapped(false)
, m_diskImageCacheId(DiskImageCache::invalidDiskCacheId)
, m_notifyMemoryMappedCallback(nullptr)
, m_notifyMemoryMappedCallbackData(nullptr)
#endif
, m_cfData(nullptr)
{
CFIndex dataArrayCount = CFArrayGetCount(cfDataArray);
for (CFIndex index = 0; index < dataArrayCount; ++index)
append(checked_cf_cast<CFDataRef>(CFArrayGetValueAtIndex(cfDataArray, index)));
}
void SharedBuffer::append(CFDataRef data)
{
ASSERT(data);
m_dataArray.append(data);
m_size += CFDataGetLength(data);
}
void SharedBuffer::copyBufferAndClear(char* destination, unsigned bytesToCopy) const
{
if (m_dataArray.isEmpty())
return;
CFIndex bytesLeft = bytesToCopy;
Vector<RetainPtr<CFDataRef>>::const_iterator end = m_dataArray.end();
for (Vector<RetainPtr<CFDataRef>>::const_iterator it = m_dataArray.begin(); it != end; ++it) {
CFIndex dataLen = CFDataGetLength(it->get());
ASSERT(bytesLeft >= dataLen);
memcpy(destination, CFDataGetBytePtr(it->get()), dataLen);
destination += dataLen;
bytesLeft -= dataLen;
}
m_dataArray.clear();
}
unsigned SharedBuffer::copySomeDataFromDataArray(const char*& someData, unsigned position) const
{
Vector<RetainPtr<CFDataRef>>::const_iterator end = m_dataArray.end();
unsigned totalOffset = 0;
for (Vector<RetainPtr<CFDataRef>>::const_iterator it = m_dataArray.begin(); it != end; ++it) {
unsigned dataLen = static_cast<unsigned>(CFDataGetLength(it->get()));
ASSERT(totalOffset <= position);
unsigned localOffset = position - totalOffset;
if (localOffset < dataLen) {
someData = reinterpret_cast<const char *>(CFDataGetBytePtr(it->get())) + localOffset;
return dataLen - localOffset;
}
totalOffset += dataLen;
}
return 0;
}
const char *SharedBuffer::singleDataArrayBuffer() const
{
if (m_buffer->data.size())
return 0;
if (m_dataArray.size() != 1)
return 0;
return reinterpret_cast<const char*>(CFDataGetBytePtr(m_dataArray.at(0).get()));
}
bool SharedBuffer::maybeAppendDataArray(SharedBuffer* data)
{
if (m_buffer->data.size() || m_cfData || !data->m_dataArray.size())
return false;
#if !ASSERT_DISABLED
unsigned originalSize = size();
#endif
for (auto cfData : data->m_dataArray)
append(cfData.get());
ASSERT(size() == originalSize + data->size());
return true;
}
#endif
}