1/*
2 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#ifndef SharedBuffer_h
28#define SharedBuffer_h
29
30#include <wtf/Forward.h>
31#include <wtf/OwnPtr.h>
32#include <wtf/RefCounted.h>
33#include <wtf/Vector.h>
34#include <wtf/text/WTFString.h>
35
36#if USE(CF)
37#include <wtf/RetainPtr.h>
38#endif
39
40#if PLATFORM(MAC)
41OBJC_CLASS NSData;
42#endif
43
44namespace WebCore {
45
46class PurgeableBuffer;
47
48class SharedBuffer : public RefCounted<SharedBuffer> {
49public:
50    static PassRefPtr<SharedBuffer> create() { return adoptRef(new SharedBuffer); }
51    static PassRefPtr<SharedBuffer> create(size_t size) { return adoptRef(new SharedBuffer(size)); }
52    static PassRefPtr<SharedBuffer> create(const char* c, int i) { return adoptRef(new SharedBuffer(c, i)); }
53    static PassRefPtr<SharedBuffer> create(const unsigned char* c, int i) { return adoptRef(new SharedBuffer(c, i)); }
54
55    static PassRefPtr<SharedBuffer> createWithContentsOfFile(const String& filePath);
56
57    static PassRefPtr<SharedBuffer> adoptVector(Vector<char>& vector);
58
59    // The buffer must be in non-purgeable state before adopted to a SharedBuffer.
60    // It will stay that way until released.
61    static PassRefPtr<SharedBuffer> adoptPurgeableBuffer(PassOwnPtr<PurgeableBuffer>);
62
63    ~SharedBuffer();
64
65#if PLATFORM(MAC)
66    NSData *createNSData();
67    static PassRefPtr<SharedBuffer> wrapNSData(NSData *data);
68#endif
69#if USE(CF)
70    CFDataRef createCFData();
71    static PassRefPtr<SharedBuffer> wrapCFData(CFDataRef);
72#endif
73
74    // Calling this function will force internal segmented buffers
75    // to be merged into a flat buffer. Use getSomeData() whenever possible
76    // for better performance.
77    const char* data() const;
78
79    unsigned size() const;
80
81
82    bool isEmpty() const { return !size(); }
83
84    void append(SharedBuffer*);
85    void append(const char*, unsigned);
86    void append(const Vector<char>&);
87
88    void clear();
89    const char* platformData() const;
90    unsigned platformDataSize() const;
91
92#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
93    void append(CFDataRef);
94#endif
95
96    PassRefPtr<SharedBuffer> copy() const;
97
98    bool hasPurgeableBuffer() const { return m_purgeableBuffer.get(); }
99
100    // Ensure this buffer has no other clients before calling this.
101    PassOwnPtr<PurgeableBuffer> releasePurgeableBuffer();
102
103    // Return the number of consecutive bytes after "position". "data"
104    // points to the first byte.
105    // Return 0 when no more data left.
106    // When extracting all data with getSomeData(), the caller should
107    // repeat calling it until it returns 0.
108    // Usage:
109    //      const char* segment;
110    //      unsigned pos = 0;
111    //      while (unsigned length = sharedBuffer->getSomeData(segment, pos)) {
112    //          // Use the data. for example: decoder->decode(segment, length);
113    //          pos += length;
114    //      }
115    unsigned getSomeData(const char*& data, unsigned position = 0) const;
116
117    void createPurgeableBuffer() const;
118
119    void tryReplaceContentsWithPlatformBuffer(SharedBuffer*);
120
121private:
122    SharedBuffer();
123    explicit SharedBuffer(size_t);
124    SharedBuffer(const char*, int);
125    SharedBuffer(const unsigned char*, int);
126
127    // Calling this function will force internal segmented buffers
128    // to be merged into a flat buffer. Use getSomeData() whenever possible
129    // for better performance.
130    // As well, be aware that this method does *not* return any purgeable
131    // memory, which can be a source of bugs.
132    const Vector<char>& buffer() const;
133
134    void clearPlatformData();
135    void maybeTransferPlatformData();
136    bool hasPlatformData() const;
137
138    unsigned m_size;
139    mutable Vector<char> m_buffer;
140    mutable Vector<char*> m_segments;
141    mutable OwnPtr<PurgeableBuffer> m_purgeableBuffer;
142#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
143    mutable Vector<RetainPtr<CFDataRef> > m_dataArray;
144    void copyDataArrayAndClear(char *destination, unsigned bytesToCopy) const;
145    unsigned copySomeDataFromDataArray(const char*& someData, unsigned position) const;
146    const char *singleDataArrayBuffer() const;
147#endif
148#if USE(CF)
149    explicit SharedBuffer(CFDataRef);
150    RetainPtr<CFDataRef> m_cfData;
151#endif
152};
153
154PassRefPtr<SharedBuffer> utf8Buffer(const String&);
155
156} // namespace WebCore
157
158#endif // SharedBuffer_h
159