1/* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18#ifndef VIRTUAL_BUFFER_H_INCLUDED
19#define VIRTUAL_BUFFER_H_INCLUDED
20
21#ifndef OSCL_TYPES_H_INCLUDED
22#include "oscl_types.h"
23#endif
24
25#ifndef OSCL_VECTOR_H_INCLUDED
26#include "oscl_vector.h"
27#endif
28
29#ifndef OSCL_REFCOUNTER_MEMFRAG_H_INCLUDED
30#include "oscl_refcounter_memfrag.h"
31#endif
32
33#ifndef OSCL_ASSERT_H_INCLUDED
34#include "oscl_assert.h"
35#endif
36
37template<class TBufferAccess>
38class VirtualBuffer
39{
40    public:
41        VirtualBuffer();
42        VirtualBuffer(const Oscl_Vector<OsclRefCounterMemFrag, OsclMemAllocator>& buffers);
43        virtual ~VirtualBuffer();
44
45        // copy constructor
46//    VirtualBuffer<TBufferAccess>(const VirtualBuffer<TBufferAccess>& original);
47
48
49        VirtualBuffer<TBufferAccess>(const VirtualBuffer<TBufferAccess>& original)
50        {
51            pCurrFrag = NULL;
52            pCurrFragPos = NULL;
53            currIndex = 0;
54
55            for (uint i = 0; i < original.vFragments.size(); i++)
56            {
57                appendBuffer(original.vFragments[i]);
58            }
59
60            currIndex = original.currIndex;
61            pCurrFrag = &vFragments[currIndex];
62            pCurrFragPos = original.pCurrFragPos;
63        }
64
65
66
67        // buffer operations
68        void appendBuffer(const OsclRefCounterMemFrag& frag);
69        void reset();
70
71        // operators
72        TBufferAccess& operator*();                         // indirection
73        VirtualBuffer& operator=(const VirtualBuffer&);     // assignment
74        operator TBufferAccess*()
75        {
76            return pCurrFragPos;
77        };  // cast
78        VirtualBuffer& operator++();                        // prefix increment
79        VirtualBuffer operator++(int);                      // postfix increment
80        VirtualBuffer& operator+=(const int increment);     // addition
81
82        // create a new virtual buffer from the current position
83        // for the specified range
84        void createSubBuffer(uint length, VirtualBuffer<TBufferAccess>& subRange);
85
86        // create a new virtual buffer from the current position
87        void createSubBuffer(VirtualBuffer<TBufferAccess>& subRange);
88
89        // copy fragments into vector
90        void copy(Oscl_Vector<OsclRefCounterMemFrag, OsclMemAllocator>& vOutFrags);
91
92        // fragment vector accessor
93        const Oscl_Vector<OsclRefCounterMemFrag, OsclMemAllocator>& fragments()
94        {
95            return vFragments;
96        }
97
98        // return the virtual length
99        uint length();
100
101    protected:
102        void advance();
103        void setCurrPointer()
104        {
105            pCurrFragPos = reinterpret_cast<TBufferAccess*>(pCurrFrag->getMemFragPtr());
106        }
107
108        Oscl_Vector<OsclRefCounterMemFrag, OsclMemAllocator> vFragments;
109        OsclRefCounterMemFrag* pCurrFrag;
110        int currIndex;
111        TBufferAccess* pCurrFragPos;
112};
113
114
115template<class TBufferAccess>
116VirtualBuffer<TBufferAccess>::VirtualBuffer()
117{
118    pCurrFrag = NULL;
119    pCurrFragPos = NULL;
120    currIndex = 0;
121}
122
123
124template<class TBufferAccess>
125VirtualBuffer<TBufferAccess>::VirtualBuffer(const Oscl_Vector<OsclRefCounterMemFrag, OsclMemAllocator>& buffers)
126{
127    OSCL_ASSERT(buffers.size() > 0);
128
129    pCurrFrag = NULL;
130    pCurrFragPos = NULL;
131    currIndex = 0;
132
133    for (uint i = 0; i < buffers.size(); i++)
134    {
135        appendBuffer(buffers[i]);
136    }
137}
138
139template<class TBufferAccess>
140VirtualBuffer<TBufferAccess>::~VirtualBuffer()
141{
142}
143
144template<class TBufferAccess>
145VirtualBuffer<TBufferAccess>& VirtualBuffer<TBufferAccess>::operator=(const VirtualBuffer & original)
146{
147    if (&original != this)
148    {
149        vFragments.clear();
150        for (uint i = 0; i < original.vFragments.size(); i++)
151        {
152            appendBuffer(original.vFragments[i]);
153        }
154
155        currIndex = original.currIndex;
156        pCurrFrag = &vFragments[currIndex];
157        pCurrFragPos = original.pCurrFragPos;
158    }
159
160    return *this;
161}
162
163template<class TBufferAccess>
164void VirtualBuffer<TBufferAccess>::appendBuffer(const OsclRefCounterMemFrag& frag)
165{
166    vFragments.push_back(frag);
167    if (pCurrFrag == NULL)
168    {
169        currIndex = 0;
170        pCurrFrag = &vFragments[currIndex];
171
172        setCurrPointer();
173    }
174    else
175    {
176        pCurrFrag = &vFragments[currIndex];
177    }
178
179}
180
181template<class TBufferAccess>
182void VirtualBuffer<TBufferAccess>::reset()
183{
184    pCurrFrag = NULL;
185    currIndex = 0;
186    vFragments.clear();
187}
188
189template<class TBufferAccess>
190TBufferAccess& VirtualBuffer<TBufferAccess>::operator*()
191{
192    OSCL_ASSERT(pCurrFragPos != NULL);
193    return *pCurrFragPos;
194}
195
196template<class TBufferAccess>
197VirtualBuffer<TBufferAccess>& VirtualBuffer<TBufferAccess>::operator++()
198{
199    advance();
200    return *this;
201}
202
203template<class TBufferAccess>
204VirtualBuffer<TBufferAccess> VirtualBuffer<TBufferAccess>::operator++(int)
205{
206    VirtualBuffer<TBufferAccess> temp(*this);
207    advance();
208    return temp;
209}
210
211template<class TBufferAccess>
212VirtualBuffer<TBufferAccess>& VirtualBuffer<TBufferAccess>::operator+=(const int increment)
213{
214    for (int i = 0; i < increment; i++)
215    {
216        advance();
217    }
218
219    return *this;
220}
221
222template<class TBufferAccess>
223void VirtualBuffer<TBufferAccess>::createSubBuffer(uint length,
224        VirtualBuffer<TBufferAccess>& subRange)
225{
226    subRange.reset();
227
228    uint bytesNeeded = length;
229
230    TBufferAccess* position = pCurrFragPos;
231    OsclRefCounterMemFrag* pFragment = pCurrFrag;
232
233    while (1 && pCurrFrag != NULL)
234    {
235        OsclRefCounterMemFrag frag(*pFragment);
236        frag.getMemFrag().ptr = position;
237        uint32 bytesInFrag = ((TBufferAccess*)pFragment->getMemFragPtr() + pFragment->getMemFragSize()) - position;
238        frag.getMemFrag().len = bytesInFrag > bytesNeeded ? bytesNeeded : bytesInFrag;
239        subRange.appendBuffer(frag);
240
241        bytesNeeded -= frag.getMemFrag().len;
242
243        if (bytesNeeded == 0)
244        {
245            break;
246        }
247
248        pFragment++;
249
250        if (pFragment != vFragments.end())
251        {
252            // move position to the front of the next buffer
253            position = reinterpret_cast<TBufferAccess*>(pFragment->getMemFragPtr());
254        }
255        else
256        {
257            // ran out of data
258            break;
259        }
260    }
261}
262
263template<class TBufferAccess>
264void VirtualBuffer<TBufferAccess>::copy(Oscl_Vector<OsclRefCounterMemFrag, OsclMemAllocator>& vOutFrags)
265{
266    for (uint i = 0; i < vFragments.size(); i++)
267    {
268        vOutFrags.push_back(vFragments[i]);
269    }
270}
271
272template<class TBufferAccess>
273void VirtualBuffer<TBufferAccess>::createSubBuffer(VirtualBuffer<TBufferAccess>& subRange)
274{
275    subRange.reset();
276    TBufferAccess* position = pCurrFragPos;
277    OsclRefCounterMemFrag* pFragment = pCurrFrag;
278
279    if (pCurrFrag == NULL)
280    {
281        //no fragment left
282        return;
283    }
284
285    while (1)
286    {
287        OsclRefCounterMemFrag frag(*pFragment);
288        frag.getMemFrag().ptr = position;
289        frag.getMemFrag().len = ((TBufferAccess*)pFragment->getMemFragPtr() + pFragment->getMemFragSize()) - position;
290        subRange.appendBuffer(frag);
291
292        pFragment++;
293
294        if (pFragment != vFragments.end())
295        {
296            // move position to the front of the next buffer
297            position = reinterpret_cast<TBufferAccess*>(pFragment->getMemFragPtr());
298        }
299        else
300        {
301            break;
302        }
303    }
304}
305
306template<class TBufferAccess>
307void VirtualBuffer<TBufferAccess>::advance()
308{
309    // advance our intra buffer pointer
310    ++pCurrFragPos;
311
312    // check if we've exhausted the current buffer
313    // NOTE: The check assumes that the len field  in the
314    //       OsclMemoryFragments is a byte count.
315    if ((TBufferAccess*)(pCurrFragPos) == (TBufferAccess*)pCurrFrag->getMemFragPtr() +
316            pCurrFrag->getMemFragSize())
317    {
318        // advance to the next fragment
319        pCurrFrag++;
320        if (pCurrFrag == vFragments.end())
321        {
322            // no fragments left
323            pCurrFrag = NULL;
324            pCurrFragPos = NULL;
325            currIndex = 0;
326            return;
327        }
328        currIndex++;
329        setCurrPointer();
330    }
331}
332
333template<class TBufferAccess>
334uint VirtualBuffer<TBufferAccess>::length()
335{
336    uint len = 0;
337
338    for (uint i = 0; i < vFragments.size(); i++)
339    {
340        len += vFragments[i].getMemFrag().len;
341    }
342
343    return len;
344}
345
346#endif // VIRTUAL_BUFFER_H_INCLUDED
347
348