123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853 |
- #ifndef Array_H
- #define Array_H
- #include "Betriebssystem.h"
- #include <stdexcept>
- #include "Text.h"
- #include "ReferenceCounter.h"
- namespace Framework
- {
- template< class TYP >
- //! Ein Eintrag in einer Linked List
- struct ArrayEintrag
- {
- TYP var;
- bool set = false;
- ArrayEintrag< TYP > *next = 0;
- //! Setzt den Eintrag auf die Werte des anderen Eintrages
- ArrayEintrag &operator=( ArrayEintrag &r )
- {
- var = r.var;
- set = r.set;
- next = r.next;
- return *this;
- }
- //! Gibt den aktuell gespeicherten Wert zurück
- operator TYP()
- {
- if( !set )
- {
- Text err = "Index out of Range Exception File: ";
- err += __FILE__;
- err += " Line: ";
- err += __LINE__;
- throw std::out_of_range( (char *)err );
- }
- return var;
- }
- //! inkrementiert durch die Linked List durch
- ArrayEintrag< TYP > &operator++() //! prefix
- {
- if( !next )
- {
- ArrayEintrag<TYP> tmp;
- tmp.set = 0;
- tmp.next = 0;
- *this = tmp;
- return *this;
- }
- *this = *next;
- return *next;
- }
- //! inkrementiert durch die Linked List durch
- ArrayEintrag< TYP > &operator++( int ) //! postfix
- {
- if( !next )
- {
- ArrayEintrag<TYP> tmp;
- tmp.set = 0;
- tmp.next = 0;
- *this = tmp;
- return *this;
- }
- *this = *next;
- return *next;
- }
- #ifdef WIN32
- #pragma warning( once : 26495 )
- };
- #else
- };
- #endif
- template< class TYP >
- class Iterator
- {
- private:
- ArrayEintrag< TYP > *current;
- public:
- Iterator( ArrayEintrag< TYP > *start )
- {
- current = start;
- while( current && !current->set )
- {
- current = current->next;
- }
- }
- Iterator( const Iterator &it )
- {
- current = it.current;
- }
- Iterator< TYP > &operator=( Iterator< TYP > r )
- {
- current = r.current;
- return *this;
- }
- bool hasNext()
- {
- ArrayEintrag< TYP > *next = current->next;
- while( next && !next->set )
- {
- next = next->next;
- }
- return next != 0;
- }
- Iterator< TYP > next()
- {
- if( !current )
- {
- Text err = "Index out of Range Exception File: ";
- err += __FILE__;
- err += " Line: ";
- err += __LINE__;
- throw std::out_of_range( (char *)err );
- }
- return Iterator( current->next );
- }
- operator bool()
- {
- return current != 0;
- }
- operator TYP()
- {
- if( !current || !current->set )
- {
- Text err = "Index out of Range Exception File: ";
- err += __FILE__;
- err += " Line: ";
- err += __LINE__;
- throw std::out_of_range( (char *)err );
- }
- return current->var;
- }
- Iterator< TYP > &operator++() //! prefix
- {
- do
- {
- if( current )
- current = current->next;
- } while( current && !current->set );
- return *this;
- }
- Iterator< TYP > operator++( int ) //! postfix
- {
- Iterator< TYP > temp( *this );
- do
- {
- if( current )
- current = current->next;
- } while( current && !current->set );
- return temp;
- }
- TYP operator->()
- {
- if( !current || !current->set )
- {
- Text err = "Index out of Range Exception File: ";
- err += __FILE__;
- err += " Line: ";
- err += __LINE__;
- throw std::out_of_range( (char *)err );
- }
- return current->var;
- }
- TYP val()
- {
- if( !current || !current->set )
- {
- Text err = "Index out of Range Exception File: ";
- err += __FILE__;
- err += " Line: ";
- err += __LINE__;
- throw std::out_of_range( (char *)err );
- }
- return current->var;
- }
- void set( TYP val )
- {
- if( current )
- {
- current->var = val;
- current->set = true;
- }
- else
- {
- Text err = "Index out of Range Exception File: ";
- err += __FILE__;
- err += " Line: ";
- err += __LINE__;
- throw std::out_of_range( (char *)err );
- }
- }
- };
- #define _ val()
- template< class TYP >
- //! Eine Linked List von Klassen, die kein Reference Counting berteiben
- class Array : public virtual ReferenceCounter
- {
- private:
- ArrayEintrag< TYP > *entries;
- public:
- //! Erstellt eine neue Linked List
- Array() noexcept
- : ReferenceCounter()
- {
- entries = new ArrayEintrag< TYP >();
- entries->set = 0;
- entries->next = 0;
- }
- //! Kopiert eine Linked list
- //!
- Array( const Array &arr )
- : ReferenceCounter()
- {
- entries = new ArrayEintrag< TYP >();
- entries->set = 0;
- entries->next = 0;
- int anz = arr.getEintragAnzahl();
- for( int i = 0; i < anz; i++ )
- add( arr.get( i ) );
- }
- //! Leert und löscht die Linked List
- ~Array()
- {
- leeren();
- delete entries;
- }
- //! Hängt ein Element ans Ende der Liste an
- //! \param t Das neue Element
- void add( TYP t )
- {
- for( ArrayEintrag< TYP > *e = entries; 1; e = e->next )
- {
- if( !e->set && !e->next )
- {
- e->var = t;
- e->set = 1;
- break;
- }
- if( !e->next )
- {
- e->next = new ArrayEintrag< TYP >();
- e->next->set = 0;
- e->next->next = 0;
- }
- }
- }
- //! Fügt ein Element bei einer bestimmten Position in die Liste ein
- //! \param t das neue Element
- //! \param i Die Position, wo das Element eingefügt wird (danach der Index des neuen Elementes)
- void add( TYP t, int i )
- {
- if( i < 0 )
- return;
- ArrayEintrag< TYP > *e = entries;
- for( int a = 0; a < i; ++a )
- {
- if( !e->next )
- {
- ArrayEintrag< TYP > *ne = new ArrayEintrag< TYP >();
- ne->set = 0;
- ne->next = 0;
- e->next = ne;
- }
- e = e->next;
- }
- ArrayEintrag< TYP > *ne = new ArrayEintrag< TYP >();
- ne->var = e->var;
- ne->set = e->set;
- ne->next = e->next;
- e->next = ne;
- e->var = t;
- e->set = 1;
- }
- //! Setzt den Wert des i-ten Eintrags
- //! \param t der Neue Wert
- //! \param i Der Index des Eintrages der gesetzt werden soll
- void set( TYP t, int i )
- {
- if( i < 0 )
- return;
- ArrayEintrag< TYP > *e = entries;
- for( int a = 0; a < i; ++a )
- {
- if( !e->next )
- {
- ArrayEintrag< TYP > *ne = new ArrayEintrag< TYP >();
- ne->set = 0;
- ne->next = 0;
- e->next = ne;
- }
- e = e->next;
- }
- e->var = t;
- e->set = 1;
- }
- //! Verändert die Position des i-ten Elementes in der Liste
- //! \param i Der Index des Elementes, welches verschoben werden soll
- //! \param p Die Zielposition des Elementes (danach der neue Index des Elementes)
- void setPosition( int i, int p )
- {
- if( i < 0 || p < 0 || i == p )
- return;
- ArrayEintrag< TYP > *e = entries;
- ArrayEintrag< TYP > *ve = 0;
- for( int a = 0; a < i; ++a )
- {
- if( !e->next )
- return;
- ve = e;
- e = e->next;
- }
- ArrayEintrag< TYP > *e2 = entries == e ? e->next : entries;
- ArrayEintrag< TYP > *ve2 = 0;
- for( int a = 0; a < p; ++a )
- {
- if( !e2 )
- return;
- ve2 = e2;
- if( e2->next == e )
- e2 = e->next;
- else
- e2 = e2->next;
- }
- if( !e )
- return;
- if( !ve2 )
- entries = e;
- else
- ve2->next = e;
- if( ve )
- ve->next = e->next;
- else
- entries = e->next;
- e->next = e2;
- }
- //! Löscht ein Bestimmtes Element
- //! \param i Der Index des Elementes das gelöscht werden soll
- void remove( int i )
- {
- if( i < 0 )
- return;
- ArrayEintrag< TYP > *e = entries;
- for( int a = 0; a < i; ++a )
- {
- if( !e->next )
- return;
- e = e->next;
- }
- if( !e )
- return;
- if( e->next )
- {
- e->var = e->next->var;
- e->set = e->next->set;
- }
- else
- e->set = 0;
- ArrayEintrag< TYP > *del = e->next;
- if( e->next )
- e->next = e->next->next;
- else
- e->next = 0;
- if( del )
- {
- del->set = 0;
- del->next = 0;
- delete del;
- }
- }
- //! Löscht ein Bestimmtes Element
- //! \param i Der Index des Elementes das gelöscht werden soll
- void removeValue( TYP value )
- {
- ArrayEintrag< TYP > *e = entries;
- for( int a = 0; e->var != value; ++a )
- {
- if( !e->next )
- return;
- e = e->next;
- }
- if( !e )
- return;
- if( e->next )
- {
- e->var = e->next->var;
- e->set = e->next->set;
- }
- else
- e->set = 0;
- ArrayEintrag< TYP > *del = e->next;
- if( e->next )
- e->next = e->next->next;
- else
- e->next = 0;
- if( del )
- {
- del->set = 0;
- del->next = 0;
- delete del;
- }
- }
- //! Vertauscht zwei Elemente in der Liste
- //! \param vi Der Index des ersten Elementes
- //! \param ni Der Index des zweiten Elementes
- void tausch( int vi, int ni )
- {
- if( vi < 0 || ni < 0 )
- return;
- TYP tmp = get( ni );
- set( get( vi ), ni );
- set( tmp, vi );
- }
- //! Löscht alle Elemente der Liste
- void leeren()
- {
- ArrayEintrag< TYP > *e2 = 0;
- for( ArrayEintrag< TYP > *e = entries; e; e = e->next )
- {
- delete e2;
- e2 = e;
- }
- delete e2;
- entries = new ArrayEintrag< TYP >();
- entries->set = 0;
- entries->next = 0;
- }
- //! Gibt einen Iterator zurück.
- //! Mit ++ kann durch die Liste iteriert werden
- Iterator< TYP > getIterator() const
- {
- return Iterator< TYP >( entries );
- }
- //! Gibt zurück, wie viele Elemente in der Liste sind
- int getEintragAnzahl() const
- {
- int i = 0;
- for( auto it = getIterator(); it; it++ )
- ++i;
- return i;
- }
- //! Gibt den Wert des i-ten Elementes zurück
- //! \param i Der index des gesuchten Elementes
- //! throws:
- //! \param std:out_of_range wenn i < 0 oder i >= getEintragAnzahl()
- TYP get( int i ) const
- {
- if( i < 0 )
- {
- Text err = "Index out of Range Exception File: ";
- err += __FILE__;
- err += " Line: ";
- err += __LINE__;
- err += " Index: ";
- err += i;
- throw std::out_of_range( (char *)err );
- }
- ArrayEintrag< TYP > *e = entries;
- for( int a = 0; a < i && e; ++a )
- e = e->next;
- if( e && e->set )
- return e->var;
- Text err = "Index out of Range Exception File: ";
- err += __FILE__;
- err += " Line: ";
- err += __LINE__;
- err += " Index: ";
- err += i;
- throw std::out_of_range( (char *)err );
- }
- //! Überprüft, ob ein Element in der Liste enthalten ist
- //! \param i Der Index des gesuchten Elementes
- //! \return (true), wenn der Index vorhanden ist. (false) sonnst
- bool hat( int i ) const
- {
- if( i < 0 )
- return 0;
- ArrayEintrag< TYP > *e = entries;
- for( int a = 0; a < i && e; ++a )
- e = e->next;
- if( e && e->set )
- return 1;
- return 0;
- }
- //! Gibt den Index eines Wertes zurück
- //! \param t Der Wert, nach dem gesucht werden soll
- int getWertIndex( TYP t ) const
- {
- int ret = 0;
- for( ArrayEintrag< TYP > *e = entries; e; e = e->next )
- {
- if( e->set && e->var == t )
- return ret;
- ++ret;
- }
- return -1;
- }
- Array &operator=( const Array &arr )
- {
- leeren();
- int anz = arr.getEintragAnzahl();
- for( int i = 0; i < anz; i++ )
- add( arr.get( i ) );
- return *this;
- }
- };
- template< class TYP >
- //! Eine Linked List von Zeigern auf Zeichnunge, die Reference Counting berteiben
- class RCArray : public virtual ReferenceCounter
- {
- private:
- ArrayEintrag< TYP * > *entries;
- public:
- //! Erstellt eine neue Linked List
- RCArray() noexcept
- : ReferenceCounter()
- {
- entries = new ArrayEintrag< TYP * >();
- entries->set = 0;
- entries->next = 0;
- }
- //! Kopiert eine Linked list
- RCArray( const RCArray &arr )
- : ReferenceCounter()
- {
- entries = new ArrayEintrag< TYP * >();
- entries->set = 0;
- entries->next = 0;
- int anz = arr.getEintragAnzahl();
- for( int i = 0; i < anz; i++ )
- add( arr.get( i ) );
- ref = 1;
- }
- //! Leert und löscht die Linked List
- ~RCArray()
- {
- leeren();
- delete entries;
- }
- //! Hängt ein Element ans Ende der Liste an
- //! \param t Das neue Element
- void add( TYP *t )
- {
- for( ArrayEintrag< TYP * > *e = entries; 1; e = e->next )
- {
- if( !e->set && !e->next )
- {
- e->var = t;
- e->set = 1;
- break;
- }
- if( !e->next )
- {
- e->next = new ArrayEintrag< TYP * >();
- if( e->next->set && e->next->var )
- e->next->var->release();
- e->next->set = 0;
- e->next->next = 0;
- }
- }
- }
- //! Fügt ein Element bei einer bestimmten Position in die Liste ein
- //! \param t das neue Element
- //! \param i Die Position, wo das Element eingefügt wird (danach der Index des neuen Elementes)
- void add( TYP *t, int i )
- {
- if( i < 0 )
- {
- if( t )
- t->release();
- return;
- }
- ArrayEintrag< TYP * > *e = entries;
- for( int a = 0; a < i; ++a )
- {
- if( !e->next )
- {
- ArrayEintrag< TYP * > *ne = new ArrayEintrag< TYP * >();
- ne->set = 0;
- ne->next = 0;
- e->next = ne;
- }
- e = e->next;
- }
- ArrayEintrag< TYP * > *ne = new ArrayEintrag< TYP * >();
- ne->var = e->var;
- ne->set = e->set;
- ne->next = e->next;
- e->next = ne;
- e->var = t;
- e->set = 1;
- }
- //! Setzt den Wert des i-ten Eintrags
- //! \param t der Neue Wert
- //! \param i Der Index des Eintrages der gesetzt werden soll
- void set( TYP *t, int i )
- {
- if( i < 0 )
- {
- if( t )
- t->release();
- return;
- }
- ArrayEintrag< TYP * > *e = entries;
- for( int a = 0; a < i; ++a )
- {
- if( !e->next )
- {
- ArrayEintrag< TYP * > *ne = new ArrayEintrag< TYP * >();
- ne->set = 0;
- ne->next = 0;
- e->next = ne;
- }
- e = e->next;
- }
- if( e->set && e->var )
- e->var->release();
- e->var = t;
- e->set = 1;
- }
- //! Verändert die Position des i-ten Elementes in der Liste
- //! \param i Der Index des Elementes, welches verschoben werden soll
- //! \param p Die Zielposition des Elementes (danach der neue Index des Elementes)
- void setPosition( int i, int p )
- {
- if( i < 0 || p < 0 || i == p )
- return;
- ArrayEintrag< TYP * > *ve = 0;
- ArrayEintrag< TYP * > *e = entries;
- for( int a = 0; a < i; ++a )
- {
- if( !e->next )
- return;
- ve = e;
- e = e->next;
- }
- ArrayEintrag< TYP * > *e2 = entries == e ? e->next : entries;
- ArrayEintrag< TYP * > *ve2 = 0;
- for( int a = 0; a < p; ++a )
- {
- if( !e2 )
- return;
- ve2 = e2;
- if( e2->next == e )
- e2 = e->next;
- else
- e2 = e2->next;
- }
- if( !e )
- return;
- if( !ve2 )
- entries = e;
- else
- ve2->next = e;
- if( ve )
- ve->next = e->next;
- else
- entries = e->next;
- e->next = e2;
- }
- //! Löscht ein Bestimmtes Element
- //! \param i Der Index des Elementes das gelöscht werden soll
- void remove( int i )
- {
- if( i < 0 )
- return;
- ArrayEintrag< TYP * > *e = entries;
- for( int a = 0; a < i; ++a )
- {
- if( !e->next )
- return;
- e = e->next;
- }
- if( !e )
- return;
- if( e->next )
- {
- if( e->set && e->var )
- e->var->release();
- e->var = e->next->var;
- e->set = e->next->set;
- }
- else
- {
- if( e->set && e->var )
- e->var->release();
- e->set = 0;
- }
- ArrayEintrag< TYP * > *del = e->next;
- if( e->next )
- e->next = e->next->next;
- else
- e->next = 0;
- if( del )
- {
- del->set = 0;
- del->next = 0;
- delete del;
- }
- }
- //! Vertauscht zwei Elemente in der Liste
- //! \param vi Der Index des ersten Elementes
- //! \param ni Der Index des zweiten Elementes
- void tausch( int vi, int ni )
- {
- if( vi < 0 || ni < 0 )
- return;
- TYP *tmp = get( ni );
- set( get( vi ), ni );
- set( tmp, vi );
- }
- //! Löscht alle Elemente der Liste
- void leeren()
- {
- ArrayEintrag< TYP * > *e2 = 0;
- for( ArrayEintrag< TYP * > *e = entries; e; e = e->next )
- {
- if( e2 && e2->var && e2->set )
- e2->var->release();
- delete e2;
- e2 = e;
- }
- if( e2 && e2->var && e2->set )
- e2->var->release();
- delete e2;
- entries = new ArrayEintrag< TYP * >();
- entries->set = 0;
- entries->next = 0;
- }
- //! Gibt einen Iterator zurück.
- //! Mit ++ kann durch die Liste iteriert werden
- Iterator< TYP * > getIterator() const
- {
- return Iterator< TYP * >( entries );
- }
- //! Gibt zurück, wie viele Elemente in der Liste sind
- int getEintragAnzahl() const
- {
- int i = 0;
- for( auto it = getIterator(); it; it++ )
- ++i;
- return i;
- }
- int getLastIndex() const
- {
- int index = 0;
- ArrayEintrag< TYP * > *e = entries;
- for( ; e; ++index )
- e = e->next;
- return index - 1;
- }
- //! Gibt den Wert des i-ten Elementes zurück mit erhöhtem Reference Counter
- //! \param i Der index des gesuchten Elementes, (0) wenn der Index nicht existiert
- TYP *get( int i ) const
- {
- if( i < 0 )
- return (TYP *)0;
- ArrayEintrag< TYP * > *e = entries;
- for( int a = 0; a < i && e; ++a )
- e = e->next;
- if( e && e->set && e->var )
- return dynamic_cast<TYP *>( e->var->getThis() );
- return (TYP *)0;
- }
- //! Gibt den Wert des i-ten Elementes zurück ohne erhöhten Reference Counter
- //! \param i Der index des gesuchten Elementes, (0) wenn der Index nicht existiert
- TYP *z( int i ) const //! gibt den index - ten T zurück
- {
- if( i < 0 )
- return (TYP *)0;
- ArrayEintrag< TYP * > *e = entries;
- for( int a = 0; a < i && e; ++a )
- e = e->next;
- if( e && e->set && e->var )
- return (TYP *)e->var;
- return (TYP *)0;
- }
- //! Überprüft, ob ein Element in der Liste enthalten ist
- //! \param i Der Index des gesuchten Elementes
- //! \return (true), wenn der Index vorhanden ist. (false) sonnst
- bool hat( int i ) const
- {
- if( i < 0 )
- return 0;
- ArrayEintrag< TYP * > *e = entries;
- for( int a = 0; a < i && e; ++a )
- e = e->next;
- if( e && e->set )
- return 1;
- return 0;
- }
- RCArray &operator=( const RCArray &arr )
- {
- leeren();
- int anz = arr.getEintragAnzahl();
- for( int i = 0; i < anz; i++ )
- add( arr.get( i ) );
- return *this;
- }
- };
- }
- #endif
|