15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/SharedBuffer.h"
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/PurgeableBuffer.h"
317757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/PassOwnPtr.h"
327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/unicode/Unicode.h"
337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/unicode/UTF8.h"
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
35521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#undef SHARED_BUFFER_STATS
36521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
37521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#ifdef SHARED_BUFFER_STATS
38521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/DataLog.h"
39521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/MainThread.h"
40521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#endif
41521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace std;
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const unsigned segmentSize = 0x1000;
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const unsigned segmentPositionMask = 0x0FFF;
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline unsigned segmentIndex(unsigned position)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return position / segmentSize;
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline unsigned offsetInSegment(unsigned position)
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return position & segmentPositionMask;
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline char* allocateSegment()
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return static_cast<char*>(fastMalloc(segmentSize));
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline void freeSegment(char* p)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    fastFree(p);
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
69521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#ifdef SHARED_BUFFER_STATS
70521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
71521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)static Mutex& statsMutex()
72521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
73521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    DEFINE_STATIC_LOCAL(Mutex, mutex, ());
74521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    return mutex;
75521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
76521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
77521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)static HashSet<SharedBuffer*>& liveBuffers()
78521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
79521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    DEFINE_STATIC_LOCAL(HashSet<SharedBuffer*>, buffers, ());
80521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    return buffers;
81521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
82521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
83521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)static bool sizeComparator(SharedBuffer* a, SharedBuffer* b)
84521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
85521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    return a->size() > b->size();
86521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
87521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
88521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)static CString snippetForBuffer(SharedBuffer* sharedBuffer)
89521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
90521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    const unsigned kMaxSnippetLength = 64;
91521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    char* snippet = 0;
92521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    unsigned snippetLength = std::min(sharedBuffer->size(), kMaxSnippetLength);
93521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    CString result = CString::newUninitialized(snippetLength, snippet);
94521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
95521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    const char* segment;
96521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    unsigned offset = 0;
97521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    while (unsigned segmentLength = sharedBuffer->getSomeData(segment, offset)) {
98521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        unsigned length = std::min(segmentLength, snippetLength - offset);
99521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        memcpy(snippet + offset, segment, length);
100521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        offset += segmentLength;
101521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        if (offset >= snippetLength)
102521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            break;
103521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    }
104521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
105521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    for (unsigned i = 0; i < snippetLength; ++i) {
106521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        if (!isASCIIPrintable(snippet[i]))
107521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            snippet[i] = '?';
108521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    }
109521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
110521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    return result;
111521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
112521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
113521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)static void printStats(void*)
114521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
115521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    MutexLocker locker(statsMutex());
116521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    Vector<SharedBuffer*> buffers;
117521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    for (HashSet<SharedBuffer*>::const_iterator iter = liveBuffers().begin(); iter != liveBuffers().end(); ++iter)
118521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        buffers.append(*iter);
119521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    std::sort(buffers.begin(), buffers.end(), sizeComparator);
120521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
121521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    dataLogF("---- Shared Buffer Stats ----\n");
122521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    for (size_t i = 0; i < buffers.size() && i < 64; ++i) {
123521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        CString snippet = snippetForBuffer(buffers[i]);
124521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        dataLogF("Buffer size=%8u %s\n", buffers[i]->size(), snippet.data());
125521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    }
126521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
127521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
128521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)static void didCreateSharedBuffer(SharedBuffer* buffer)
129521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
130521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    MutexLocker locker(statsMutex());
131521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    liveBuffers().add(buffer);
132521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
133521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    callOnMainThread(printStats, 0);
134521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
135521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
136521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)static void willDestroySharedBuffer(SharedBuffer* buffer)
137521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
138521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    MutexLocker locker(statsMutex());
139521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    liveBuffers().remove(buffer);
140521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
141521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
142521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#endif
143521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SharedBuffer::SharedBuffer()
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_size(0)
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
147521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#ifdef SHARED_BUFFER_STATS
148521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    didCreateSharedBuffer(this);
149521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#endif
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SharedBuffer::SharedBuffer(size_t size)
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_size(size)
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_buffer(size)
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
156521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#ifdef SHARED_BUFFER_STATS
157521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    didCreateSharedBuffer(this);
158521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#endif
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SharedBuffer::SharedBuffer(const char* data, int size)
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_size(0)
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: Use unsigned consistently, and check for invalid casts when calling into SharedBuffer from other code.
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (size < 0)
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        CRASH();
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    append(data, size);
169521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
170521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#ifdef SHARED_BUFFER_STATS
171521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    didCreateSharedBuffer(this);
172521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#endif
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SharedBuffer::SharedBuffer(const unsigned char* data, int size)
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_size(0)
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: Use unsigned consistently, and check for invalid casts when calling into SharedBuffer from other code.
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (size < 0)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        CRASH();
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    append(reinterpret_cast<const char*>(data), size);
183521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
184521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#ifdef SHARED_BUFFER_STATS
185521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    didCreateSharedBuffer(this);
186521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#endif
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
18802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SharedBuffer::~SharedBuffer()
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clear();
192521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
193521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#ifdef SHARED_BUFFER_STATS
194521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    willDestroySharedBuffer(this);
195521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#endif
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<SharedBuffer> SharedBuffer::adoptVector(Vector<char>& vector)
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<SharedBuffer> buffer = create();
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    buffer->m_buffer.swap(vector);
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    buffer->m_size = buffer->m_buffer.size();
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return buffer.release();
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20602772c6a72f1ee0b226341a4f4439970c29fc861Ben MurdochPassRefPtr<SharedBuffer> SharedBuffer::adoptPurgeableBuffer(PassOwnPtr<PurgeableBuffer> purgeableBuffer)
20702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!purgeableBuffer->isPurgeable());
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<SharedBuffer> buffer = create();
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    buffer->m_purgeableBuffer = purgeableBuffer;
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return buffer.release();
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned SharedBuffer::size() const
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_purgeableBuffer)
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_purgeableBuffer->size();
21802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_size;
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
222926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SharedBuffer::createPurgeableBuffer() const
223926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (m_purgeableBuffer)
225926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
226926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
227926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_purgeableBuffer = PurgeableBuffer::create(buffer().data(), m_size);
228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
229926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const char* SharedBuffer::data() const
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_purgeableBuffer)
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_purgeableBuffer->data();
23402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
235926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return this->buffer().data();
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
238e6d4491e48613634a83c1957c72759da80987961Ben Murdochvoid SharedBuffer::moveTo(Vector<char>& result)
239e6d4491e48613634a83c1957c72759da80987961Ben Murdoch{
240e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    ASSERT(result.isEmpty());
241e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    if (m_purgeableBuffer) {
242e6d4491e48613634a83c1957c72759da80987961Ben Murdoch        result.reserveCapacity(m_purgeableBuffer->size());
243e6d4491e48613634a83c1957c72759da80987961Ben Murdoch        result.append(m_purgeableBuffer->data(), m_purgeableBuffer->size());
244e6d4491e48613634a83c1957c72759da80987961Ben Murdoch        clear();
245e6d4491e48613634a83c1957c72759da80987961Ben Murdoch        return;
246e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    }
247e6d4491e48613634a83c1957c72759da80987961Ben Murdoch
248e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    unsigned bufferSize = m_buffer.size();
249e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    if (m_size == bufferSize) {
250e6d4491e48613634a83c1957c72759da80987961Ben Murdoch        m_buffer.swap(result);
251e6d4491e48613634a83c1957c72759da80987961Ben Murdoch        clear();
252e6d4491e48613634a83c1957c72759da80987961Ben Murdoch        return;
253e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    }
254e6d4491e48613634a83c1957c72759da80987961Ben Murdoch
255e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    result.reserveCapacity(m_size);
256e6d4491e48613634a83c1957c72759da80987961Ben Murdoch
257e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    const char* segment = 0;
258e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    unsigned position = 0;
259e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    while (unsigned segmentSize = getSomeData(segment, position)) {
260e6d4491e48613634a83c1957c72759da80987961Ben Murdoch        result.append(segment, segmentSize);
261e6d4491e48613634a83c1957c72759da80987961Ben Murdoch        position += segmentSize;
262e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    }
263e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    ASSERT(result.size() == m_size);
264e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    clear();
265e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    return;
266e6d4491e48613634a83c1957c72759da80987961Ben Murdoch}
267e6d4491e48613634a83c1957c72759da80987961Ben Murdoch
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SharedBuffer::append(SharedBuffer* data)
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const char* segment;
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t position = 0;
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (size_t length = data->getSomeData(segment, position)) {
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(segment, length);
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        position += length;
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SharedBuffer::append(const char* data, unsigned length)
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!m_purgeableBuffer);
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!length)
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned positionInSegment = offsetInSegment(m_size - m_buffer.size());
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_size += length;
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_size <= segmentSize) {
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // No need to use segments for small resource data
289926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (m_buffer.isEmpty())
290926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            m_buffer.reserveInitialCapacity(length);
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_buffer.append(data, length);
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    char* segment;
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!positionInSegment) {
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        segment = allocateSegment();
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_segments.append(segment);
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        segment = m_segments.last() + positionInSegment;
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned segmentFreeSpace = segmentSize - positionInSegment;
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned bytesToCopy = min(length, segmentFreeSpace);
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (;;) {
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        memcpy(segment, data, bytesToCopy);
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (static_cast<unsigned>(length) == bytesToCopy)
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        length -= bytesToCopy;
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data += bytesToCopy;
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        segment = allocateSegment();
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_segments.append(segment);
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bytesToCopy = min(length, segmentSize);
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SharedBuffer::append(const Vector<char>& data)
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    append(data.data(), data.size());
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SharedBuffer::clear()
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < m_segments.size(); ++i)
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        freeSegment(m_segments[i]);
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_segments.clear();
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_size = 0;
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_buffer.clear();
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_purgeableBuffer.clear();
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<SharedBuffer> SharedBuffer::copy() const
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<SharedBuffer> clone(adoptRef(new SharedBuffer));
33853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (m_purgeableBuffer) {
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        clone->append(data(), size());
340e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return clone.release();
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clone->m_size = m_size;
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clone->m_buffer.reserveCapacity(m_size);
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clone->m_buffer.append(m_buffer.data(), m_buffer.size());
346e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (!m_segments.isEmpty()) {
347e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        const char* segment = 0;
348e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        unsigned position = m_buffer.size();
349e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        while (unsigned segmentSize = getSomeData(segment, position)) {
350e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            clone->m_buffer.append(segment, segmentSize);
351e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            position += segmentSize;
352e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        }
353e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        ASSERT(position == clone->size());
354e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
355e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return clone.release();
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassOwnPtr<PurgeableBuffer> SharedBuffer::releasePurgeableBuffer()
35902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
36002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    ASSERT(hasOneRef());
36102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    return m_purgeableBuffer.release();
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const Vector<char>& SharedBuffer::buffer() const
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned bufferSize = m_buffer.size();
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_size > bufferSize) {
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_buffer.resize(m_size);
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        char* destination = m_buffer.data() + bufferSize;
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned bytesLeft = m_size - bufferSize;
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i < m_segments.size(); ++i) {
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            unsigned bytesToCopy = min(bytesLeft, segmentSize);
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            memcpy(destination, m_segments[i], bytesToCopy);
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            destination += bytesToCopy;
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bytesLeft -= bytesToCopy;
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            freeSegment(m_segments[i]);
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_segments.clear();
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_buffer;
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned SharedBuffer::getSomeData(const char*& someData, unsigned position) const
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned totalSize = size();
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (position >= totalSize) {
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        someData = 0;
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
39153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (m_purgeableBuffer) {
392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ASSERT_WITH_SECURITY_IMPLICATION(position < size());
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        someData = data() + position;
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return totalSize - position;
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
397926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT_WITH_SECURITY_IMPLICATION(position < m_size);
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned consecutiveSize = m_buffer.size();
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (position < consecutiveSize) {
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        someData = m_buffer.data() + position;
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return consecutiveSize - position;
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
40302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    position -= consecutiveSize;
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned segments = m_segments.size();
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned maxSegmentedSize = segments * segmentSize;
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned segment = segmentIndex(position);
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (segment < segments) {
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned bytesLeft = totalSize - consecutiveSize;
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned segmentedSize = min(maxSegmentedSize, bytesLeft);
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned positionInSegment = offsetInSegment(position);
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        someData = m_segments[segment] + positionInSegment;
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return segment == segments - 1 ? segmentedSize - position : segmentSize - positionInSegment;
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_NOT_REACHED();
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)PassRefPtr<ArrayBuffer> SharedBuffer::getAsArrayBuffer() const
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::createUninitialized(static_cast<unsigned>(size()), 1);
4235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
4245267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    const char* segment = 0;
4255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    unsigned position = 0;
4265267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    while (unsigned segmentSize = getSomeData(segment, position)) {
4275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        memcpy(static_cast<char*>(arrayBuffer->data()) + position, segment, segmentSize);
4285267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        position += segmentSize;
4295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
4305267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
4315267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (position != arrayBuffer->byteLength()) {
4325267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        ASSERT_NOT_REACHED();
4335267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        // Don't return the incomplete ArrayBuffer.
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
4355267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4375267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return arrayBuffer;
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
441