diff options
Diffstat (limited to 'src/thirdparty/BaseClasses/wxlist.h')
-rw-r--r-- | src/thirdparty/BaseClasses/wxlist.h | 553 |
1 files changed, 553 insertions, 0 deletions
diff --git a/src/thirdparty/BaseClasses/wxlist.h b/src/thirdparty/BaseClasses/wxlist.h new file mode 100644 index 000000000..900792883 --- /dev/null +++ b/src/thirdparty/BaseClasses/wxlist.h @@ -0,0 +1,553 @@ +//------------------------------------------------------------------------------
+// File: WXList.h
+//
+// Desc: DirectShow base classes - defines a non-MFC generic template list
+// class.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------------------------
+
+
+/* A generic list of pointers to objects.
+ No storage management or copying is done on the objects pointed to.
+ Objectives: avoid using MFC libraries in ndm kernel mode and
+ provide a really useful list type.
+
+ The class is thread safe in that separate threads may add and
+ delete items in the list concurrently although the application
+ must ensure that constructor and destructor access is suitably
+ synchronised. An application can cause deadlock with operations
+ which use two lists by simultaneously calling
+ list1->Operation(list2) and list2->Operation(list1). So don't!
+
+ The names must not conflict with MFC classes as an application
+ may use both.
+ */
+
+#ifndef __WXLIST__
+#define __WXLIST__
+
+ /* A POSITION represents (in some fashion that's opaque) a cursor
+ on the list that can be set to identify any element. NULL is
+ a valid value and several operations regard NULL as the position
+ "one step off the end of the list". (In an n element list there
+ are n+1 places to insert and NULL is that "n+1-th" value).
+ The POSITION of an element in the list is only invalidated if
+ that element is deleted. Move operations may mean that what
+ was a valid POSITION in one list is now a valid POSITION in
+ a different list.
+
+ Some operations which at first sight are illegal are allowed as
+ harmless no-ops. For instance RemoveHead is legal on an empty
+ list and it returns NULL. This allows an atomic way to test if
+ there is an element there, and if so, get it. The two operations
+ AddTail and RemoveHead thus implement a MONITOR (See Hoare's paper).
+
+ Single element operations return POSITIONs, non-NULL means it worked.
+ whole list operations return a BOOL. TRUE means it all worked.
+
+ This definition is the same as the POSITION type for MFCs, so we must
+ avoid defining it twice.
+ */
+#ifndef __AFX_H__
+struct __POSITION { int unused; };
+typedef __POSITION* POSITION;
+#endif
+
+const int DEFAULTCACHE = 10; /* Default node object cache size */
+
+/* A class representing one node in a list.
+ Each node knows a pointer to it's adjacent nodes and also a pointer
+ to the object that it looks after.
+ All of these pointers can be retrieved or set through member functions.
+*/
+class CBaseList
+#ifdef _DEBUG
+ : public CBaseObject
+#endif
+{
+ /* Making these classes inherit from CBaseObject does nothing
+ functionally but it allows us to check there are no memory
+ leaks in debug builds.
+ */
+
+public:
+
+#ifdef _DEBUG
+ class CNode : public CBaseObject {
+#else
+ class CNode {
+#endif
+
+ CNode *m_pPrev; /* Previous node in the list */
+ CNode *m_pNext; /* Next node in the list */
+ void *m_pObject; /* Pointer to the object */
+
+ public:
+
+ /* Constructor - initialise the object's pointers */
+ CNode()
+#ifdef _DEBUG
+ : CBaseObject(NAME("List node"))
+#endif
+ {
+ };
+
+
+ /* Return the previous node before this one */
+ __out CNode *Prev() const { return m_pPrev; };
+
+
+ /* Return the next node after this one */
+ __out CNode *Next() const { return m_pNext; };
+
+
+ /* Set the previous node before this one */
+ void SetPrev(__in_opt CNode *p) { m_pPrev = p; };
+
+
+ /* Set the next node after this one */
+ void SetNext(__in_opt CNode *p) { m_pNext = p; };
+
+
+ /* Get the pointer to the object for this node */
+ __out void *GetData() const { return m_pObject; };
+
+
+ /* Set the pointer to the object for this node */
+ void SetData(__in void *p) { m_pObject = p; };
+ };
+
+ class CNodeCache
+ {
+ public:
+ CNodeCache(INT iCacheSize) : m_iCacheSize(iCacheSize),
+ m_pHead(NULL),
+ m_iUsed(0)
+ {};
+ ~CNodeCache() {
+ CNode *pNode = m_pHead;
+ while (pNode) {
+ CNode *pCurrent = pNode;
+ pNode = pNode->Next();
+ delete pCurrent;
+ }
+ };
+ void AddToCache(__inout CNode *pNode)
+ {
+ if (m_iUsed < m_iCacheSize) {
+ pNode->SetNext(m_pHead);
+ m_pHead = pNode;
+ m_iUsed++;
+ } else {
+ delete pNode;
+ }
+ };
+ CNode *RemoveFromCache()
+ {
+ CNode *pNode = m_pHead;
+ if (pNode != NULL) {
+ m_pHead = pNode->Next();
+ m_iUsed--;
+ ASSERT(m_iUsed >= 0);
+ } else {
+ ASSERT(m_iUsed == 0);
+ }
+ return pNode;
+ };
+ private:
+ INT m_iCacheSize;
+ INT m_iUsed;
+ CNode *m_pHead;
+ };
+
+protected:
+
+ CNode* m_pFirst; /* Pointer to first node in the list */
+ CNode* m_pLast; /* Pointer to the last node in the list */
+ LONG m_Count; /* Number of nodes currently in the list */
+
+private:
+
+ CNodeCache m_Cache; /* Cache of unused node pointers */
+
+private:
+
+ /* These override the default copy constructor and assignment
+ operator for all list classes. They are in the private class
+ declaration section so that anybody trying to pass a list
+ object by value will generate a compile time error of
+ "cannot access the private member function". If these were
+ not here then the compiler will create default constructors
+ and assignment operators which when executed first take a
+ copy of all member variables and then during destruction
+ delete them all. This must not be done for any heap
+ allocated data.
+ */
+ CBaseList(const CBaseList &refList);
+ CBaseList &operator=(const CBaseList &refList);
+
+public:
+
+ CBaseList(__in_opt LPCTSTR pName,
+ INT iItems);
+
+ CBaseList(__in_opt LPCTSTR pName);
+#ifdef UNICODE
+ CBaseList(__in_opt LPCSTR pName,
+ INT iItems);
+
+ CBaseList(__in_opt LPCSTR pName);
+#endif
+ ~CBaseList();
+
+ /* Remove all the nodes from *this i.e. make the list empty */
+ void RemoveAll();
+
+
+ /* Return a cursor which identifies the first element of *this */
+ __out_opt POSITION GetHeadPositionI() const;
+
+
+ /* Return a cursor which identifies the last element of *this */
+ __out_opt POSITION GetTailPositionI() const;
+
+
+ /* Return the number of objects in *this */
+ int GetCountI() const;
+
+protected:
+ /* Return the pointer to the object at rp,
+ Update rp to the next node in *this
+ but make it NULL if it was at the end of *this.
+ This is a wart retained for backwards compatibility.
+ GetPrev is not implemented.
+ Use Next, Prev and Get separately.
+ */
+ __out void *GetNextI(__inout POSITION& rp) const;
+
+
+ /* Return a pointer to the object at p
+ Asking for the object at NULL will return NULL harmlessly.
+ */
+ __out_opt void *GetI(__in_opt POSITION p) const;
+ __out void *GetValidI(__in POSITION p) const;
+
+public:
+ /* return the next / prev position in *this
+ return NULL when going past the end/start.
+ Next(NULL) is same as GetHeadPosition()
+ Prev(NULL) is same as GetTailPosition()
+ An n element list therefore behaves like a n+1 element
+ cycle with NULL at the start/end.
+
+ !!WARNING!! - This handling of NULL is DIFFERENT from GetNext.
+
+ Some reasons are:
+ 1. For a list of n items there are n+1 positions to insert
+ These are conveniently encoded as the n POSITIONs and NULL.
+ 2. If you are keeping a list sorted (fairly common) and you
+ search forward for an element to insert before and don't
+ find it you finish up with NULL as the element before which
+ to insert. You then want that NULL to be a valid POSITION
+ so that you can insert before it and you want that insertion
+ point to mean the (n+1)-th one that doesn't have a POSITION.
+ (symmetrically if you are working backwards through the list).
+ 3. It simplifies the algebra which the methods generate.
+ e.g. AddBefore(p,x) is identical to AddAfter(Prev(p),x)
+ in ALL cases. All the other arguments probably are reflections
+ of the algebraic point.
+ */
+ __out_opt POSITION Next(__in_opt POSITION pos) const
+ {
+ if (pos == NULL) {
+ return (POSITION) m_pFirst;
+ }
+ CNode *pn = (CNode *) pos;
+ return (POSITION) pn->Next();
+ } //Next
+
+ // See Next
+ __out_opt POSITION Prev(__in_opt POSITION pos) const
+ {
+ if (pos == NULL) {
+ return (POSITION) m_pLast;
+ }
+ CNode *pn = (CNode *) pos;
+ return (POSITION) pn->Prev();
+ } //Prev
+
+
+ /* Return the first position in *this which holds the given
+ pointer. Return NULL if the pointer was not not found.
+ */
+protected:
+ __out_opt POSITION FindI( __in void * pObj) const;
+
+ // ??? Should there be (or even should there be only)
+ // ??? POSITION FindNextAfter(void * pObj, POSITION p)
+ // ??? And of course FindPrevBefore too.
+ // ??? List.Find(&Obj) then becomes List.FindNextAfter(&Obj, NULL)
+
+
+ /* Remove the first node in *this (deletes the pointer to its
+ object from the list, does not free the object itself).
+ Return the pointer to its object.
+ If *this was already empty it will harmlessly return NULL.
+ */
+ __out_opt void *RemoveHeadI();
+
+
+ /* Remove the last node in *this (deletes the pointer to its
+ object from the list, does not free the object itself).
+ Return the pointer to its object.
+ If *this was already empty it will harmlessly return NULL.
+ */
+ __out_opt void *RemoveTailI();
+
+
+ /* Remove the node identified by p from the list (deletes the pointer
+ to its object from the list, does not free the object itself).
+ Asking to Remove the object at NULL will harmlessly return NULL.
+ Return the pointer to the object removed.
+ */
+ __out_opt void *RemoveI(__in_opt POSITION p);
+
+ /* Add single object *pObj to become a new last element of the list.
+ Return the new tail position, NULL if it fails.
+ If you are adding a COM objects, you might want AddRef it first.
+ Other existing POSITIONs in *this are still valid
+ */
+ __out_opt POSITION AddTailI(__in void * pObj);
+public:
+
+
+ /* Add all the elements in *pList to the tail of *this.
+ This duplicates all the nodes in *pList (i.e. duplicates
+ all its pointers to objects). It does not duplicate the objects.
+ If you are adding a list of pointers to a COM object into the list
+ it's a good idea to AddRef them all it when you AddTail it.
+ Return TRUE if it all worked, FALSE if it didn't.
+ If it fails some elements may have been added.
+ Existing POSITIONs in *this are still valid
+
+ If you actually want to MOVE the elements, use MoveToTail instead.
+ */
+ BOOL AddTail(__in CBaseList *pList);
+
+
+ /* Mirror images of AddHead: */
+
+ /* Add single object to become a new first element of the list.
+ Return the new head position, NULL if it fails.
+ Existing POSITIONs in *this are still valid
+ */
+protected:
+ __out_opt POSITION AddHeadI(__in void * pObj);
+public:
+
+ /* Add all the elements in *pList to the head of *this.
+ Same warnings apply as for AddTail.
+ Return TRUE if it all worked, FALSE if it didn't.
+ If it fails some of the objects may have been added.
+
+ If you actually want to MOVE the elements, use MoveToHead instead.
+ */
+ BOOL AddHead(__in CBaseList *pList);
+
+
+ /* Add the object *pObj to *this after position p in *this.
+ AddAfter(NULL,x) adds x to the start - equivalent to AddHead
+ Return the position of the object added, NULL if it failed.
+ Existing POSITIONs in *this are undisturbed, including p.
+ */
+protected:
+ __out_opt POSITION AddAfterI(__in_opt POSITION p, __in void * pObj);
+public:
+
+ /* Add the list *pList to *this after position p in *this
+ AddAfter(NULL,x) adds x to the start - equivalent to AddHead
+ Return TRUE if it all worked, FALSE if it didn't.
+ If it fails, some of the objects may be added
+ Existing POSITIONs in *this are undisturbed, including p.
+ */
+ BOOL AddAfter(__in_opt POSITION p, __in CBaseList *pList);
+
+
+ /* Mirror images:
+ Add the object *pObj to this-List after position p in *this.
+ AddBefore(NULL,x) adds x to the end - equivalent to AddTail
+ Return the position of the new object, NULL if it fails
+ Existing POSITIONs in *this are undisturbed, including p.
+ */
+ protected:
+ __out_opt POSITION AddBeforeI(__in_opt POSITION p, __in void * pObj);
+ public:
+
+ /* Add the list *pList to *this before position p in *this
+ AddAfter(NULL,x) adds x to the start - equivalent to AddHead
+ Return TRUE if it all worked, FALSE if it didn't.
+ If it fails, some of the objects may be added
+ Existing POSITIONs in *this are undisturbed, including p.
+ */
+ BOOL AddBefore(__in_opt POSITION p, __in CBaseList *pList);
+
+
+ /* Note that AddAfter(p,x) is equivalent to AddBefore(Next(p),x)
+ even in cases where p is NULL or Next(p) is NULL.
+ Similarly for mirror images etc.
+ This may make it easier to argue about programs.
+ */
+
+
+
+ /* The following operations do not copy any elements.
+ They move existing blocks of elements around by switching pointers.
+ They are fairly efficient for long lists as for short lists.
+ (Alas, the Count slows things down).
+
+ They split the list into two parts.
+ One part remains as the original list, the other part
+ is appended to the second list. There are eight possible
+ variations:
+ Split the list {after/before} a given element
+ keep the {head/tail} portion in the original list
+ append the rest to the {head/tail} of the new list.
+
+ Since After is strictly equivalent to Before Next
+ we are not in serious need of the Before/After variants.
+ That leaves only four.
+
+ If you are processing a list left to right and dumping
+ the bits that you have processed into another list as
+ you go, the Tail/Tail variant gives the most natural result.
+ If you are processing in reverse order, Head/Head is best.
+
+ By using NULL positions and empty lists judiciously either
+ of the other two can be built up in two operations.
+
+ The definition of NULL (see Next/Prev etc) means that
+ degenerate cases include
+ "move all elements to new list"
+ "Split a list into two lists"
+ "Concatenate two lists"
+ (and quite a few no-ops)
+
+ !!WARNING!! The type checking won't buy you much if you get list
+ positions muddled up - e.g. use a POSITION that's in a different
+ list and see what a mess you get!
+ */
+
+ /* Split *this after position p in *this
+ Retain as *this the tail portion of the original *this
+ Add the head portion to the tail end of *pList
+ Return TRUE if it all worked, FALSE if it didn't.
+
+ e.g.
+ foo->MoveToTail(foo->GetHeadPosition(), bar);
+ moves one element from the head of foo to the tail of bar
+ foo->MoveToTail(NULL, bar);
+ is a no-op, returns NULL
+ foo->MoveToTail(foo->GetTailPosition, bar);
+ concatenates foo onto the end of bar and empties foo.
+
+ A better, except excessively long name might be
+ MoveElementsFromHeadThroughPositionToOtherTail
+ */
+ BOOL MoveToTail(__in_opt POSITION pos, __in CBaseList *pList);
+
+
+ /* Mirror image:
+ Split *this before position p in *this.
+ Retain in *this the head portion of the original *this
+ Add the tail portion to the start (i.e. head) of *pList
+
+ e.g.
+ foo->MoveToHead(foo->GetTailPosition(), bar);
+ moves one element from the tail of foo to the head of bar
+ foo->MoveToHead(NULL, bar);
+ is a no-op, returns NULL
+ foo->MoveToHead(foo->GetHeadPosition, bar);
+ concatenates foo onto the start of bar and empties foo.
+ */
+ BOOL MoveToHead(__in_opt POSITION pos, __in CBaseList *pList);
+
+
+ /* Reverse the order of the [pointers to] objects in *this
+ */
+ void Reverse();
+
+
+ /* set cursor to the position of each element of list in turn */
+ #define TRAVERSELIST(list, cursor) \
+ for ( cursor = (list).GetHeadPosition() \
+ ; cursor!=NULL \
+ ; cursor = (list).Next(cursor) \
+ )
+
+
+ /* set cursor to the position of each element of list in turn
+ in reverse order
+ */
+ #define REVERSETRAVERSELIST(list, cursor) \
+ for ( cursor = (list).GetTailPosition() \
+ ; cursor!=NULL \
+ ; cursor = (list).Prev(cursor) \
+ )
+
+}; // end of class declaration
+
+template<class OBJECT> class CGenericList : public CBaseList
+{
+public:
+ CGenericList(__in_opt LPCTSTR pName,
+ INT iItems,
+ BOOL bLock = TRUE,
+ BOOL bAlert = FALSE) :
+ CBaseList(pName, iItems) {
+ UNREFERENCED_PARAMETER(bAlert);
+ UNREFERENCED_PARAMETER(bLock);
+ };
+ CGenericList(__in_opt LPCTSTR pName) :
+ CBaseList(pName) {
+ };
+
+ __out_opt POSITION GetHeadPosition() const { return (POSITION)m_pFirst; }
+ __out_opt POSITION GetTailPosition() const { return (POSITION)m_pLast; }
+ int GetCount() const { return m_Count; }
+
+ __out OBJECT *GetNext(__inout POSITION& rp) const { return (OBJECT *) GetNextI(rp); }
+
+ __out_opt OBJECT *Get(__in_opt POSITION p) const { return (OBJECT *) GetI(p); }
+ __out OBJECT *GetValid(__in POSITION p) const { return (OBJECT *) GetValidI(p); }
+ __out_opt OBJECT *GetHead() const { return Get(GetHeadPosition()); }
+
+ __out_opt OBJECT *RemoveHead() { return (OBJECT *) RemoveHeadI(); }
+
+ __out_opt OBJECT *RemoveTail() { return (OBJECT *) RemoveTailI(); }
+
+ __out_opt OBJECT *Remove(__in_opt POSITION p) { return (OBJECT *) RemoveI(p); }
+ __out_opt POSITION AddBefore(__in_opt POSITION p, __in OBJECT * pObj) { return AddBeforeI(p, pObj); }
+ __out_opt POSITION AddAfter(__in_opt POSITION p, __in OBJECT * pObj) { return AddAfterI(p, pObj); }
+ __out_opt POSITION AddHead(__in OBJECT * pObj) { return AddHeadI(pObj); }
+ __out_opt POSITION AddTail(__in OBJECT * pObj) { return AddTailI(pObj); }
+ BOOL AddTail(__in CGenericList<OBJECT> *pList)
+ { return CBaseList::AddTail((CBaseList *) pList); }
+ BOOL AddHead(__in CGenericList<OBJECT> *pList)
+ { return CBaseList::AddHead((CBaseList *) pList); }
+ BOOL AddAfter(__in_opt POSITION p, __in CGenericList<OBJECT> *pList)
+ { return CBaseList::AddAfter(p, (CBaseList *) pList); };
+ BOOL AddBefore(__in_opt POSITION p, __in CGenericList<OBJECT> *pList)
+ { return CBaseList::AddBefore(p, (CBaseList *) pList); };
+ __out_opt POSITION Find( __in OBJECT * pObj) const { return FindI(pObj); }
+}; // end of class declaration
+
+
+
+/* These define the standard list types */
+
+typedef CGenericList<CBaseObject> CBaseObjectList;
+typedef CGenericList<IUnknown> CBaseInterfaceList;
+
+#endif /* __WXLIST__ */
+
|