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