Ap4List.h

Go to the documentation of this file.
00001 /*****************************************************************
00002 |
00003 |    AP4 - Lists
00004 |
00005 |    Copyright 2002-2006 Gilles Boccon-Gibod & Julien Boeuf
00006 |
00007 |
00008 |    This file is part of Bento4/AP4 (MP4 Atom Processing Library).
00009 |
00010 |    Unless you have obtained Bento4 under a difference license,
00011 |    this version of Bento4 is Bento4|GPL.
00012 |    Bento4|GPL is free software; you can redistribute it and/or modify
00013 |    it under the terms of the GNU General Public License as published by
00014 |    the Free Software Foundation; either version 2, or (at your option)
00015 |    any later version.
00016 |
00017 |    Bento4|GPL is distributed in the hope that it will be useful,
00018 |    but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 |    GNU General Public License for more details.
00021 |
00022 |    You should have received a copy of the GNU General Public License
00023 |    along with Bento4|GPL; see the file COPYING.  If not, write to the
00024 |    Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
00025 |    02111-1307, USA.
00026 |
00027  ****************************************************************/
00028 
00029 #ifndef _AP4_LIST_H_
00030 #define _AP4_LIST_H_
00031 
00032 /*----------------------------------------------------------------------
00033 |   includes
00034 +---------------------------------------------------------------------*/
00035 #include "Ap4Types.h"
00036 #include "Ap4Results.h"
00037 
00038 /*----------------------------------------------------------------------
00039 |   forward references
00040 +---------------------------------------------------------------------*/
00041 template <typename T> class AP4_List;
00042 
00043 /*----------------------------------------------------------------------
00044 |   AP4_List
00045 +---------------------------------------------------------------------*/
00046 template <typename T> 
00047 class AP4_List 
00048 {
00049 public:
00050     // types
00051     class Item 
00052     {
00053     public:
00054         // types
00055         class Operator 
00056         {
00057         public:
00058             // methods
00059             virtual ~Operator() {}
00060             virtual AP4_Result Action(T* data) const = 0;
00061         };
00062 
00063         class Finder 
00064         {
00065         public:
00066             // methods
00067             virtual ~Finder() {}
00068             virtual AP4_Result Test(T* data) const = 0;
00069         };
00070 
00071         // methods
00072         Item(T* data) : m_Data(data), m_Next(0), m_Prev(0) {}
00073        ~Item() {}
00074         Item* GetNext() { return m_Next; }
00075         Item* GetPrev() { return m_Prev; }
00076         T*    GetData() { return m_Data; }
00077 
00078     private:
00079         // members
00080         T*    m_Data;
00081         Item* m_Next;
00082         Item* m_Prev;
00083 
00084         // friends
00085         friend class AP4_List;
00086     };
00087 
00088     // methods
00089                  AP4_List<T>(): m_ItemCount(0), m_Head(0), m_Tail(0) {}
00090     virtual     ~AP4_List<T>();
00091     AP4_Result   Add(T* data);
00092     AP4_Result   Add(Item* item);
00093     AP4_Result   Remove(T* data);
00094     AP4_Result   Insert(Item* where, T* data);
00095     AP4_Result   Get(AP4_Ordinal idx, T*& data) const;
00096     AP4_Result   PopHead(T*& data);
00097     AP4_Result   Apply(const typename Item::Operator& op) const;
00098     AP4_Result   ApplyUntilFailure(const typename Item::Operator& op) const;
00099     AP4_Result   ApplyUntilSuccess(const typename Item::Operator& op) const ;
00100     AP4_Result   ReverseApply(const typename Item::Operator& op) const;
00101     AP4_Result   Find(const typename Item::Finder& finder, T*& data) const;
00102     AP4_Result   ReverseFind(const typename Item::Finder& finder, T*& data) const;
00103     AP4_Result   DeleteReferences();
00104     AP4_Cardinal ItemCount() const { return m_ItemCount; }
00105     Item*        FirstItem() const { return m_Head; }
00106     Item*        LastItem()  const { return m_Tail; }
00107  
00108 protected:
00109     // members
00110     AP4_Cardinal m_ItemCount;
00111     Item*        m_Head;
00112     Item*        m_Tail;
00113     
00114 private:
00115     // these cannot be used
00116     AP4_List<T>(const AP4_List<T>&);
00117     AP4_List<T>& operator=(const AP4_List<T>&);
00118 };
00119 
00120 /*----------------------------------------------------------------------
00121 |   AP4_List<T>::~AP4_List<T>
00122 +---------------------------------------------------------------------*/
00123 template <typename T>
00124 AP4_List<T>::~AP4_List()
00125 {
00126     Item* item = m_Head;
00127  
00128     while (item) {
00129         Item* next = item->m_Next;
00130         delete item;
00131         item = next;
00132     }
00133 }
00134  
00135 /*----------------------------------------------------------------------
00136 |   AP4_List<T>::Add
00137 +---------------------------------------------------------------------*/
00138 template <typename T>
00139 inline
00140 AP4_Result
00141 AP4_List<T>::Add(T* data)
00142 {
00143     return Add(new Item(data));
00144 }
00145 
00146 /*----------------------------------------------------------------------
00147 |   AP4_List<T>::Add
00148 +---------------------------------------------------------------------*/
00149 template <typename T>
00150 AP4_Result
00151 AP4_List<T>::Add(Item* item)
00152 {
00153     // add element at the tail
00154     if (m_Tail) {
00155         item->m_Prev = m_Tail;
00156         item->m_Next = NULL;
00157         m_Tail->m_Next = item;
00158         m_Tail = item;
00159     } else {
00160         m_Head = item;
00161         m_Tail = item;
00162         item->m_Next = NULL;
00163         item->m_Prev = NULL;
00164     }
00165 
00166     // one more item in the list now
00167     m_ItemCount++;
00168  
00169     return AP4_SUCCESS;
00170 }
00171 
00172 /*----------------------------------------------------------------------
00173 |   AP4_List<T>::Remove
00174 +---------------------------------------------------------------------*/
00175 template <typename T>
00176 AP4_Result
00177 AP4_List<T>::Remove(T* data)
00178 {
00179     Item* item = m_Head;
00180 
00181     while (item) {
00182         if (item->m_Data == data) {
00183             // delete item
00184             if (item->m_Prev) {
00185                 // item is not the head
00186                 if (item->m_Next) {
00187                     // item is not the tail
00188                     item->m_Next->m_Prev = item->m_Prev;
00189                     item->m_Prev->m_Next = item->m_Next;
00190                 } else {
00191                     // item is the tail
00192                     m_Tail = item->m_Prev;
00193                     m_Tail->m_Next = NULL;
00194                 }
00195             } else {
00196                 // item is the head
00197                 m_Head = item->m_Next;
00198                 if (m_Head) {
00199                     // item is not the tail
00200                     m_Head->m_Prev = NULL;
00201                 } else {
00202                     // item is also the tail
00203                     m_Tail = NULL;
00204                 }
00205             }
00206 
00207             // delete the item
00208             delete item;
00209 
00210             // one less item in the list now
00211             m_ItemCount--;
00212 
00213             return AP4_SUCCESS;
00214         }
00215         item = item->m_Next;
00216     }
00217  
00218     return AP4_ERROR_NO_SUCH_ITEM;
00219 }
00220 
00221 /*----------------------------------------------------------------------
00222 |   AP4_List<T>::Insert
00223 +---------------------------------------------------------------------*/
00224 template <typename T>
00225 AP4_Result
00226 AP4_List<T>::Insert(Item* where, T* data)
00227 {
00228     Item* item = new Item(data);
00229 
00230     if (where == NULL) {
00231         // insert as the head
00232         if (m_Head) {
00233             // replace the current head
00234             item->m_Prev = NULL;
00235             item->m_Next = m_Head;
00236             m_Head->m_Prev = item;
00237             m_Head = item;
00238         } else {
00239             // this item becomes the head and tail
00240             m_Head = item;
00241             m_Tail = item;
00242             item->m_Next = NULL;
00243             item->m_Prev = NULL;
00244         }
00245     } else {
00246         // insert after the 'where' item
00247         if (where == m_Tail) {
00248             // add the item at the end
00249             return Add(item);
00250         } else {
00251             // update the links
00252             item->m_Prev = where;
00253             item->m_Next = where->m_Next;
00254             where->m_Next->m_Prev = item;
00255             where->m_Next = item;
00256         }
00257     }
00258 
00259     // one more item in the list now
00260     ++m_ItemCount;
00261 
00262     return AP4_SUCCESS;
00263 }
00264 
00265 /*----------------------------------------------------------------------
00266 |   AP4_List<T>::Get
00267 +---------------------------------------------------------------------*/
00268 template <typename T>
00269 AP4_Result
00270 AP4_List<T>::Get(AP4_Ordinal idx, T*& data) const
00271 {
00272     Item* item = m_Head;
00273 
00274     if (idx < m_ItemCount) {
00275         while (idx--) item = item->m_Next;
00276         data = item->m_Data;
00277         return AP4_SUCCESS;
00278     } else {
00279         data = NULL;
00280         return AP4_ERROR_NO_SUCH_ITEM;
00281     }
00282 }
00283 
00284 /*----------------------------------------------------------------------
00285 |   AP4_List<T>::PopHead
00286 +---------------------------------------------------------------------*/
00287 template <typename T>
00288 AP4_Result
00289 AP4_List<T>::PopHead(T*& data)
00290 {
00291     // check that we have at least one item
00292     if (m_Head == NULL) {
00293         return AP4_ERROR_LIST_EMPTY;
00294     }
00295 
00296     // remove the item and return it
00297     data = m_Head->m_Data;
00298     Item* head = m_Head;
00299     m_Head = m_Head->m_Next;
00300     if (m_Head) {
00301         m_Head->m_Prev = NULL;
00302     } else {
00303         m_Tail = NULL;
00304     }
00305 
00306     // delete item
00307     delete head;
00308 
00309     // one less item in the list now
00310     m_ItemCount--;
00311  
00312     return AP4_SUCCESS;
00313 }
00314 
00315 /*----------------------------------------------------------------------
00316 |   AP4_List<T>::Apply
00317 +---------------------------------------------------------------------*/
00318 template <typename T>
00319 inline 
00320 AP4_Result
00321 AP4_List<T>::Apply(const typename Item::Operator& op) const
00322 {
00323     Item* item = m_Head;
00324  
00325     while (item) {
00326         op.Action(item->m_Data);
00327         item = item->m_Next;
00328     }
00329 
00330     return AP4_SUCCESS;
00331 }
00332 
00333 /*----------------------------------------------------------------------
00334 |   AP4_List<T>::ApplyUntilFailure
00335 +---------------------------------------------------------------------*/
00336 template <typename T>
00337 inline 
00338 AP4_Result
00339 AP4_List<T>::ApplyUntilFailure(const typename Item::Operator& op) const
00340 {
00341     Item* item = m_Head;
00342  
00343     while (item) {
00344         AP4_Result result;
00345         result = op.Action(item->m_Data);
00346         if (result != AP4_SUCCESS) return result;
00347         item = item->m_Next;
00348     }
00349 
00350     return AP4_SUCCESS;
00351 }
00352 
00353 /*----------------------------------------------------------------------
00354 |   AP4_List<T>::ApplyUntilSuccess
00355 +---------------------------------------------------------------------*/
00356 template <typename T>
00357 inline 
00358 AP4_Result
00359 AP4_List<T>::ApplyUntilSuccess(const typename Item::Operator& op) const
00360 {
00361     Item* item = m_Head;
00362  
00363     while (item) {
00364         AP4_Result result;
00365         result = op.Action(item->m_Data);
00366         if (result == AP4_SUCCESS) return AP4_SUCCESS;
00367         item = item->m_Next;
00368     }
00369 
00370     return AP4_FAILURE;
00371 }
00372 
00373 /*----------------------------------------------------------------------
00374 |   AP4_List<T>::ReverseApply
00375 +---------------------------------------------------------------------*/
00376 template <typename T>
00377 inline 
00378 AP4_Result
00379 AP4_List<T>::ReverseApply(const typename Item::Operator& op) const
00380 {
00381     Item* item = m_Tail;
00382  
00383     while (item) {
00384         if (op.Action(item->m_Data) != AP4_SUCCESS) {
00385             return AP4_ERROR_LIST_OPERATION_ABORTED;
00386         }
00387         item = item->m_Prev;
00388     }
00389 
00390     return AP4_SUCCESS;
00391 }
00392 
00393 /*----------------------------------------------------------------------
00394 |   AP4_List<T>::Find
00395 +---------------------------------------------------------------------*/
00396 template <typename T>
00397 inline 
00398 AP4_Result
00399 AP4_List<T>::Find(const typename Item::Finder& finder, T*& data) const
00400 {
00401     Item* item = m_Head;
00402  
00403     while (item) {
00404         if (finder.Test(item->m_Data) == AP4_SUCCESS) {
00405             data = item->m_Data;
00406             return AP4_SUCCESS;
00407         }
00408         item = item->m_Next;
00409     }
00410 
00411     data = NULL;
00412     return AP4_ERROR_NO_SUCH_ITEM;
00413 }
00414 
00415 /*----------------------------------------------------------------------
00416 |   AP4_List<T>::ReverseFind
00417 +---------------------------------------------------------------------*/
00418 template <typename T>
00419 inline 
00420 AP4_Result
00421 AP4_List<T>::ReverseFind(const typename Item::Finder& finder, T*& data) const
00422 {
00423     Item* item = m_Tail;
00424  
00425     while (item) {
00426         if (finder.Test(item->m_Data) == AP4_SUCCESS) {
00427             data = item->m_Data;
00428             return AP4_SUCCESS;
00429         }
00430         item = item->m_Prev;
00431     }
00432 
00433     data = NULL;
00434     return AP4_ERROR_NO_SUCH_ITEM;
00435 }
00436 
00437 /*----------------------------------------------------------------------
00438 |   AP4_List<T>::DeleteReferences
00439 +---------------------------------------------------------------------*/
00440 template <typename T>
00441 inline 
00442 AP4_Result
00443 AP4_List<T>::DeleteReferences()
00444 {
00445     Item* item = m_Head;
00446  
00447     while (item) {
00448         Item* next = item->m_Next;
00449         delete item->m_Data;
00450         delete item;
00451         item = next;
00452     }
00453 
00454     // no more items
00455     m_Head = m_Tail = NULL;
00456     m_ItemCount = 0;
00457 
00458     return AP4_SUCCESS;
00459 }
00460 
00461 #endif // _AP4_LIST_H_
00462 
00463 
00464 
00465 
00466 
00467 
00468 
00469 
00470 
00471 
00472 
00473 
00474 

Generated on Thu Mar 15 16:06:11 2007 for Bento4 MP4 SDK by  doxygen 1.5.1-p1