diff options
Diffstat (limited to 'db/mork/src/morkDeque.h')
-rw-r--r-- | db/mork/src/morkDeque.h | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/db/mork/src/morkDeque.h b/db/mork/src/morkDeque.h new file mode 100644 index 0000000000..4375ecf029 --- /dev/null +++ b/db/mork/src/morkDeque.h @@ -0,0 +1,239 @@ +/************************************************************************* +This software is part of a public domain IronDoc source code distribution, +and is provided on an "AS IS" basis, with all risks borne by the consumers +or users of the IronDoc software. There are no warranties, guarantees, or +promises about quality of any kind; and no remedies for failure exist. + +Permission is hereby granted to use this IronDoc software for any purpose +at all, without need for written agreements, without royalty or license +fees, and without fees or obligations of any other kind. Anyone can use, +copy, change and distribute this software for any purpose, and nothing is +required, implicitly or otherwise, in exchange for this usage. + +You cannot apply your own copyright to this software, but otherwise you +are encouraged to enjoy the use of this software in any way you see fit. +However, it would be rude to remove names of developers from the code. +(IronDoc is also known by the short name "Fe" and a longer name "Ferrum", +which are used interchangeably with the name IronDoc in the sources.) +*************************************************************************/ +/* + * File: morkDeque.h + * Contains: Ferrum deque (double ended queue (linked list)) + * + * Copied directly from public domain IronDoc, with minor naming tweaks: + * Designed and written by David McCusker, but all this code is public domain. + * There are no warranties, no guarantees, no promises, and no remedies. + */ + +#ifndef _MORKDEQUE_ +#define _MORKDEQUE_ 1 + +#ifndef _MORK_ +#include "mork.h" +#endif + +/*============================================================================= + * morkNext: linked list node for very simple, singly-linked list + */ + +class morkNext /*d*/ { +public: + morkNext* mNext_Link; + +public: + morkNext(int inZero) : mNext_Link( 0 ) { } + + morkNext(morkNext* ioLink) : mNext_Link( ioLink ) { } + + morkNext(); // mNext_Link( 0 ), { } + +public: + morkNext* GetNextLink() const { return mNext_Link; } + +public: // link memory management methods + static void* MakeNewNext(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev); + void ZapOldNext(morkEnv* ev, nsIMdbHeap* ioHeap); + +public: // link memory management operators + void* operator new(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev) CPP_THROW_NEW + { return morkNext::MakeNewNext(inSize, ioHeap, ev); } + + void operator delete(void* ioAddress) // DO NOT CALL THIS, hope to crash: + { ((morkNext*) 0)->ZapOldNext((morkEnv*) 0, (nsIMdbHeap*) 0); } // boom +}; + +/*============================================================================= + * morkList: simple, singly-linked list + */ + +/*| morkList: a list of singly-linked members (instances of morkNext), where +**| the number of list members might be so numerous that we must about cost +**| for two pointer link slots per member (as happens with morkLink). +**| +**|| morkList is intended to support lists of changes in morkTable, where we +**| are worried about the space cost of representing such changes. (Later we +**| can use an array instead, when we get even more worried, to avoid cost +**| of link slots at all, per member). +**| +**|| Do NOT create cycles in links using this list class, since we do not +**| deal with them very nicely. +|*/ +class morkList /*d*/ { +public: + morkNext* mList_Head; // first link in the list + morkNext* mList_Tail; // last link in the list + +public: + morkNext* GetListHead() const { return mList_Head; } + morkNext* GetListTail() const { return mList_Tail; } + + mork_bool IsListEmpty() const { return ( mList_Head == 0 ); } + mork_bool HasListMembers() const { return ( mList_Head != 0 ); } + +public: + morkList(); // : mList_Head( 0 ), mList_Tail( 0 ) { } + + void CutAndZapAllListMembers(morkEnv* ev, nsIMdbHeap* ioHeap); + // make empty list, zapping every member by calling ZapOldNext() + + void CutAllListMembers(); + // just make list empty, dropping members without zapping + +public: + morkNext* PopHead(); // cut head of list + + // Note we don't support PopTail(), so use morkDeque if you need that. + + void PushHead(morkNext* ioLink); // add to head of list + void PushTail(morkNext* ioLink); // add to tail of list +}; + +/*============================================================================= + * morkLink: linked list node embedded in objs to allow insertion in morkDeques + */ + +class morkLink /*d*/ { +public: + morkLink* mLink_Next; + morkLink* mLink_Prev; + +public: + morkLink(int inZero) : mLink_Next( 0 ), mLink_Prev( 0 ) { } + + morkLink(); // mLink_Next( 0 ), mLink_Prev( 0 ) { } + +public: + morkLink* Next() const { return mLink_Next; } + morkLink* Prev() const { return mLink_Prev; } + + void SelfRefer() { mLink_Next = mLink_Prev = this; } + void Clear() { mLink_Next = mLink_Prev = 0; } + + void AddBefore(morkLink* old) + { + ((old)->mLink_Prev->mLink_Next = (this))->mLink_Prev = (old)->mLink_Prev; + ((this)->mLink_Next = (old))->mLink_Prev = this; + } + + void AddAfter(morkLink* old) + { + ((old)->mLink_Next->mLink_Prev = (this))->mLink_Next = (old)->mLink_Next; + ((this)->mLink_Prev = (old))->mLink_Next = this; + } + + void Remove() + { + (mLink_Prev->mLink_Next = mLink_Next)->mLink_Prev = mLink_Prev; + } + +public: // link memory management methods + static void* MakeNewLink(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev); + void ZapOldLink(morkEnv* ev, nsIMdbHeap* ioHeap); + +public: // link memory management operators + void* operator new(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev) CPP_THROW_NEW + { return morkLink::MakeNewLink(inSize, ioHeap, ev); } + +}; + +/*============================================================================= + * morkDeque: doubly linked list modeled after VAX queue instructions + */ + +class morkDeque /*d*/ { +public: + morkLink mDeque_Head; + +public: // construction + morkDeque(); // { mDeque_Head.SelfRefer(); } + +public:// methods + morkLink* RemoveFirst(); + + morkLink* RemoveLast(); + + morkLink* At(mork_pos index) const ; /* one-based, not zero-based */ + + mork_pos IndexOf(const morkLink* inMember) const; + /* one-based index ; zero means member is not in deque */ + + mork_num Length() const; + + /* the following method is more efficient for long lists: */ + int LengthCompare(mork_num inCount) const; + /* -1: length < count, 0: length == count, 1: length > count */ + +public: // inlines + + mork_bool IsEmpty()const + { return (mDeque_Head.mLink_Next == (morkLink*) &mDeque_Head); } + + morkLink* After(const morkLink* old) const + { return (((old)->mLink_Next != &mDeque_Head)? + (old)->mLink_Next : (morkLink*) 0); } + + morkLink* Before(const morkLink* old) const + { return (((old)->mLink_Prev != &mDeque_Head)? + (old)->mLink_Prev : (morkLink*) 0); } + + morkLink* First() const + { return ((mDeque_Head.mLink_Next != &mDeque_Head)? + mDeque_Head.mLink_Next : (morkLink*) 0); } + + morkLink* Last() const + { return ((mDeque_Head.mLink_Prev != &mDeque_Head)? + mDeque_Head.mLink_Prev : (morkLink*) 0); } + +/* +From IronDoc documentation for AddFirst: ++--------+ +--------+ +--------+ +--------+ +--------+ +| h.next |-->| b.next | | h.next |-->| a.next |-->| b.next | ++--------+ +--------+ ==> +--------+ +--------+ +--------+ +| h.prev |<--| b.prev | | h.prev |<--| a.prev |<--| b.prev | ++--------+ +--------+ +--------+ +--------+ +--------+ +*/ + + void AddFirst(morkLink* in) /*i*/ + { + ( (mDeque_Head.mLink_Next->mLink_Prev = + (in))->mLink_Next = mDeque_Head.mLink_Next, + ((in)->mLink_Prev = &mDeque_Head)->mLink_Next = (in) ); + } +/* +From IronDoc documentation for AddLast: ++--------+ +--------+ +--------+ +--------+ +--------+ +| y.next |-->| h.next | | y.next |-->| z.next |-->| h.next | ++--------+ +--------+ ==> +--------+ +--------+ +--------+ +| y.prev |<--| h.prev | | y.prev |<--| z.prev |<--| h.prev | ++--------+ +--------+ +--------+ +--------+ +--------+ +*/ + + void AddLast(morkLink* in) + { + ( (mDeque_Head.mLink_Prev->mLink_Next = + (in))->mLink_Prev = mDeque_Head.mLink_Prev, + ((in)->mLink_Next = &mDeque_Head)->mLink_Prev = (in) ); + } +}; + +#endif /* _MORKDEQUE_ */ |