#pragma once
#include "FileSystem.h"
#include <runtime/ArrayBuffer.h>
#include <wtf/Forward.h>
#include <wtf/RefCounted.h>
#include <wtf/ThreadSafeRefCounted.h>
#include <wtf/Variant.h>
#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>
#if USE(CF)
#include <wtf/RetainPtr.h>
#endif
#if USE(SOUP)
#include "GUniquePtrSoup.h"
#endif
#if USE(FOUNDATION)
OBJC_CLASS NSArray;
OBJC_CLASS NSData;
#endif
namespace WebCore {
class SharedBufferDataView;
class WEBCORE_EXPORT SharedBuffer : public RefCounted<SharedBuffer> {
public:
static Ref<SharedBuffer> create() { return adoptRef(*new SharedBuffer); }
static Ref<SharedBuffer> create(const char* data, size_t size) { return adoptRef(*new SharedBuffer(data, size)); }
static Ref<SharedBuffer> create(const unsigned char* data, size_t size) { return adoptRef(*new SharedBuffer(data, size)); }
static RefPtr<SharedBuffer> createWithContentsOfFile(const String& filePath);
static Ref<SharedBuffer> create(Vector<char>&&);
#if USE(FOUNDATION)
RetainPtr<NSData> createNSData() const;
RetainPtr<NSArray> createNSDataArray() const;
static Ref<SharedBuffer> create(NSData *);
#endif
#if USE(CF)
RetainPtr<CFDataRef> createCFData() const;
static Ref<SharedBuffer> create(CFDataRef);
void append(CFDataRef);
#endif
#if USE(SOUP)
GUniquePtr<SoupBuffer> createSoupBuffer(unsigned offset = 0, unsigned size = 0);
static Ref<SharedBuffer> wrapSoupBuffer(SoupBuffer*);
#endif
const char* data() const;
RefPtr<ArrayBuffer> tryCreateArrayBuffer() const;
size_t size() const { return m_size; }
bool isEmpty() const { return !size(); }
void append(const SharedBuffer&);
void append(const char*, size_t);
void append(Vector<char>&&);
void clear();
Ref<SharedBuffer> copy() const;
class DataSegment : public ThreadSafeRefCounted<DataSegment> {
public:
const char* data() const;
size_t size() const;
static Ref<DataSegment> create(Vector<char>&& data) { return adoptRef(*new DataSegment(WTFMove(data))); }
#if USE(CF)
static Ref<DataSegment> create(RetainPtr<CFDataRef>&& data) { return adoptRef(*new DataSegment(WTFMove(data))); }
#endif
#if USE(SOUP)
static Ref<DataSegment> create(GUniquePtr<SoupBuffer>&& data) { return adoptRef(*new DataSegment(WTFMove(data))); }
#endif
static Ref<DataSegment> create(MappedFileData&& data) { return adoptRef(*new DataSegment(WTFMove(data))); }
private:
DataSegment(Vector<char>&& data)
: m_immutableData(WTFMove(data)) { }
#if USE(CF)
DataSegment(RetainPtr<CFDataRef>&& data)
: m_immutableData(WTFMove(data)) { }
#endif
#if USE(SOUP)
DataSegment(GUniquePtr<SoupBuffer>&& data)
: m_immutableData(WTFMove(data)) { }
#endif
DataSegment(MappedFileData&& data)
: m_immutableData(WTFMove(data)) { }
Variant<Vector<char>,
#if USE(CF)
RetainPtr<CFDataRef>,
#endif
#if USE(SOUP)
GUniquePtr<SoupBuffer>,
#endif
MappedFileData> m_immutableData;
friend class SharedBuffer;
};
struct DataSegmentVectorEntry {
size_t beginPosition;
Ref<DataSegment> segment;
};
using DataSegmentVector = Vector<DataSegmentVectorEntry, 1>;
DataSegmentVector::const_iterator begin() const { return m_segments.begin(); }
DataSegmentVector::const_iterator end() const { return m_segments.end(); }
SharedBufferDataView getSomeData(size_t position) const;
void hintMemoryNotNeededSoon() const;
private:
explicit SharedBuffer() = default;
explicit SharedBuffer(const char*, size_t);
explicit SharedBuffer(const unsigned char*, size_t);
explicit SharedBuffer(Vector<char>&&);
explicit SharedBuffer(MappedFileData&&);
#if USE(CF)
explicit SharedBuffer(CFDataRef);
#endif
#if USE(SOUP)
explicit SharedBuffer(SoupBuffer*);
#endif
void combineIntoOneSegment() const;
static RefPtr<SharedBuffer> createFromReadingFile(const String& filePath);
size_t m_size { 0 };
mutable DataSegmentVector m_segments;
#if !ASSERT_DISABLED
mutable bool m_hasBeenCombinedIntoOneSegment { false };
bool internallyConsistent() const;
#endif
};
class WEBCORE_EXPORT SharedBufferDataView {
public:
SharedBufferDataView(Ref<SharedBuffer::DataSegment>&&, size_t);
size_t size() const;
const char* data() const;
private:
size_t m_positionWithinSegment;
Ref<SharedBuffer::DataSegment> m_segment;
};
RefPtr<SharedBuffer> utf8Buffer(const String&);
}