1/*
2* Copyright (C) 2012 Google Inc. All rights reserved.
3*
4* Redistribution and use in source and binary forms, with or without
5* modification, are permitted provided that the following conditions are
6* met:
7*
8*     * Redistributions of source code must retain the above copyright
9* notice, this list of conditions and the following disclaimer.
10*     * Redistributions in binary form must reproduce the above
11* copyright notice, this list of conditions and the following disclaimer
12* in the documentation and/or other materials provided with the
13* distribution.
14*     * Neither the name of Google Inc. nor the names of its
15* contributors may be used to endorse or promote products derived from
16* this software without specific prior written permission.
17*
18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*/
30
31#ifndef WTF_StreamBuffer_h
32#define WTF_StreamBuffer_h
33
34#include "wtf/Deque.h"
35#include "wtf/PassOwnPtr.h"
36
37namespace WTF {
38
39template <typename T, size_t BlockSize> class StreamBuffer {
40private:
41    typedef Vector<T> Block;
42public:
43    StreamBuffer()
44        : m_size(0)
45        , m_readOffset(0)
46    {
47    }
48
49    ~StreamBuffer()
50    {
51    }
52
53    bool isEmpty() const { return !size(); }
54
55    void append(const T* data, size_t size)
56    {
57        if (!size)
58            return;
59
60        m_size += size;
61        while (size) {
62            if (!m_buffer.size() || m_buffer.last()->size() == BlockSize)
63                m_buffer.append(adoptPtr(new Block));
64            size_t appendSize = std::min(BlockSize - m_buffer.last()->size(), size);
65            m_buffer.last()->append(data, appendSize);
66            data += appendSize;
67            size -= appendSize;
68        }
69    }
70
71    // This function consume data in the fist block.
72    // Specified size must be less than over equal to firstBlockSize().
73    void consume(size_t size)
74    {
75        ASSERT(m_size >= size);
76        if (!m_size)
77            return;
78
79        ASSERT(m_buffer.size() > 0);
80        ASSERT(m_readOffset + size <= m_buffer.first()->size());
81        m_readOffset += size;
82        m_size -= size;
83        if (m_readOffset >= m_buffer.first()->size()) {
84            m_readOffset = 0;
85            m_buffer.removeFirst();
86        }
87    }
88
89    size_t size() const { return m_size; }
90
91    const T* firstBlockData() const
92    {
93        if (!m_size)
94            return 0;
95        ASSERT(m_buffer.size() > 0);
96        return &m_buffer.first()->data()[m_readOffset];
97    }
98
99    size_t firstBlockSize() const
100    {
101        if (!m_size)
102            return 0;
103        ASSERT(m_buffer.size() > 0);
104        return m_buffer.first()->size() - m_readOffset;
105    }
106
107private:
108    size_t m_size;
109    size_t m_readOffset;
110    Deque<OwnPtr<Block> > m_buffer;
111};
112
113} // namespace WTF
114
115using WTF::StreamBuffer;
116
117#endif // WTF_StreamBuffer_h
118