SharedBufferCF.cpp [plain text]
#include "config.h"
#include "SharedBuffer.h"
#include <wtf/OSAllocator.h>
#include <wtf/cf/TypeCastsCF.h>
namespace WebCore {
SharedBuffer::SharedBuffer(CFDataRef cfData)
: m_buffer(adoptRef(*new DataBuffer))
, m_cfData(cfData)
, m_vnodeToken(VNodeTracker::singleton().token())
{
}
#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
Ref<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::hintMemoryNotNeededSoon()
{
if (!hasPlatformData())
return;
OSAllocator::hintMemoryNotNeededSoon(const_cast<char*>(platformData()), platformDataSize());
}
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;
}
bool SharedBuffer::tryReplaceContentsWithPlatformBuffer(SharedBuffer& newContents)
{
if (!newContents.m_cfData)
return false;
clear();
m_cfData = newContents.m_cfData;
return true;
}
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)
Ref<SharedBuffer> SharedBuffer::wrapCFDataArray(CFArrayRef cfDataArray)
{
return adoptRef(*new SharedBuffer(cfDataArray));
}
SharedBuffer::SharedBuffer(CFArrayRef cfDataArray)
: m_buffer(adoptRef(*new DataBuffer))
, 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;
for (auto& cfData : m_dataArray) {
CFIndex dataLen = CFDataGetLength(cfData.get());
ASSERT(bytesLeft >= dataLen);
memcpy(destination, CFDataGetBytePtr(cfData.get()), dataLen);
destination += dataLen;
bytesLeft -= dataLen;
}
m_dataArray.clear();
}
unsigned SharedBuffer::copySomeDataFromDataArray(const char*& someData, unsigned position) const
{
unsigned totalOffset = 0;
for (auto& cfData : m_dataArray) {
unsigned dataLen = static_cast<unsigned>(CFDataGetLength(cfData.get()));
ASSERT(totalOffset <= position);
unsigned localOffset = position - totalOffset;
if (localOffset < dataLen) {
someData = reinterpret_cast<const char *>(CFDataGetBytePtr(cfData.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
}