123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846 |
- #ifndef Array_H
- #define Array_H
- #include <functional>
- #include <stdexcept>
- #include "Errors.h"
- #include "ReferenceCounter.h"
- #include "Text.h"
- namespace Framework
- {
- template<class TYP>
- //! Ein Eintrag in einer Linked List
- struct ArrayEintrag
- {
- TYP var;
- bool set;
- ArrayEintrag<TYP>* next;
- ArrayEintrag()
- : var(),
- set(0),
- 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(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;
- std::function<ArrayEintrag<TYP>*(ArrayEintrag<TYP>* removed)> onRemove;
- public:
- Iterator(ArrayEintrag<TYP>* start,
- std::function<ArrayEintrag<TYP>*(ArrayEintrag<TYP>* removed)>
- onRemove)
- {
- this->onRemove = onRemove;
- current = start;
- while (current && !current->set)
- {
- current = current->next;
- }
- }
- Iterator(const Iterator& it)
- {
- onRemove = it.onRemove;
- current = it.current;
- }
- ~Iterator()
- {
- current = 0;
- }
- Iterator<TYP>& operator=(Iterator<TYP> r)
- {
- onRemove = r.onRemove;
- current = r.current;
- return *this;
- }
- bool hasNext()
- {
- ArrayEintrag<TYP>* next = current->next;
- while (next && !next->set)
- {
- next = next->next;
- }
- return next != 0;
- }
- TYP operator*()
- {
- return current->var;
- }
- Iterator<TYP> next()
- {
- if (!current)
- {
- Text err = "Index out of Range Exception File: ";
- err += __FILE__;
- err += " Line: ";
- err += __LINE__;
- throw std::out_of_range(err);
- }
- return Iterator(current->next, onRemove);
- }
- 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(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(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(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(err);
- }
- }
- bool operator!=(Iterator<TYP>& r)
- {
- return current != r.current;
- }
- void remove()
- {
- current = onRemove(current);
- }
- };
- #define _ val()
- template<class TYP>
- //! Eine Linked List von Klassen, die kein Reference Counting berteiben
- class Array : public virtual ReferenceCounter
- {
- private:
- ArrayEintrag<TYP>* entries;
- ArrayEintrag<TYP>* last;
- int count;
- std::function<ArrayEintrag<TYP>*(ArrayEintrag<TYP>* removed)> onRemove;
- public:
- //! Erstellt eine neue Linked List
- Array() noexcept
- : ReferenceCounter()
- {
- entries = new ArrayEintrag<TYP>();
- entries->set = 0;
- entries->next = 0;
- last = entries;
- count = 0;
- onRemove = [this](ArrayEintrag<TYP>* entry) {
- if (!entry) return (ArrayEintrag<TYP>*)0;
- if (entry->next)
- {
- entry->var = entry->next->var;
- entry->set = entry->next->set;
- }
- else
- entry->set = 0;
- ArrayEintrag<TYP>* del = entry->next;
- if (entry->next)
- entry->next = entry->next->next;
- else
- entry->next = 0;
- if (del)
- {
- del->set = 0;
- del->next = 0;
- if (last == del) last = entry;
- delete del;
- }
- count--;
- return entry->set ? entry : 0;
- };
- }
- //! Kopiert eine Linked list
- //!
- Array(const Array& arr)
- : Array()
- {
- 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)
- {
- if (!last->set)
- {
- last->var = t;
- last->set = 1;
- count++;
- return;
- }
- last->next = new ArrayEintrag<TYP>();
- last = last->next;
- last->set = 1;
- last->var = t;
- count++;
- }
- //! 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 || i > count)
- throwOutOfRange(__FILE__, __LINE__, i, count);
- if (i == count)
- {
- add(t);
- return;
- }
- ArrayEintrag<TYP>* e = entries;
- for (int a = 0; a < i; ++a)
- 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;
- if (last->next) last = last->next;
- count++;
- }
- //! 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 || i >= count)
- throwOutOfRange(__FILE__, __LINE__, i, count);
- ArrayEintrag<TYP>* e = entries;
- for (int a = 0; a < i; ++a)
- 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 == p) return;
- if (i < 0 || p < 0 || i >= count || p >= count)
- throwOutOfRange(__FILE__, __LINE__, i, count);
- ArrayEintrag<TYP>* e = entries;
- ArrayEintrag<TYP>* ve = 0;
- for (int a = 0; a < i; ++a)
- {
- ve = e;
- e = e->next;
- }
- ArrayEintrag<TYP>* e2 = entries == e ? e->next : entries;
- ArrayEintrag<TYP>* ve2 = 0;
- for (int a = 0; a < p; ++a)
- {
- ve2 = e2;
- if (e2->next == e)
- e2 = e->next;
- else
- e2 = e2->next;
- }
- if (e == last)
- last = e2;
- else if (e2 == last)
- last = e;
- 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 || i >= count)
- throwOutOfRange(__FILE__, __LINE__, i, count);
- ArrayEintrag<TYP>* e = entries;
- for (int a = 0; a < i; ++a)
- e = e->next;
- onRemove(e);
- }
- //! Löscht ein Bestimmtes Element
- //! \param i Der Index des Elementes das gelöscht werden soll
- void removeValue(TYP value)
- {
- ArrayEintrag<TYP>* e = entries;
- while (e->var != value)
- {
- 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;
- if (last == del) last = e;
- delete del;
- }
- count--;
- }
- //! 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)
- {
- 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;
- last = entries;
- count = 0;
- }
- //! Gibt einen Iterator zurück.
- //! Mit ++ kann durch die Liste iteriert werden
- Iterator<TYP> begin() const
- {
- return Iterator<TYP>(entries, onRemove);
- }
- Iterator<TYP> end() const
- {
- return Iterator<TYP>(0, onRemove);
- }
- //! Gibt zurück, wie viele Elemente in der Liste sind
- int getEintragAnzahl() const
- {
- return count;
- }
- //! 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 || i >= count)
- throwOutOfRange(__FILE__, __LINE__, i, count);
- ArrayEintrag<TYP>* e = entries;
- for (int a = 0; a < i && e; ++a)
- e = e->next;
- return e->var;
- }
- //! Ü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
- {
- return i >= 0 && i < count;
- }
- //! 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;
- ArrayEintrag<TYP*>* last;
- int count;
- std::function<ArrayEintrag<TYP*>*(ArrayEintrag<TYP*>* removed)>
- onRemove;
- public:
- //! Erstellt eine neue Linked List
- RCArray() noexcept
- : ReferenceCounter()
- {
- entries = new ArrayEintrag<TYP*>();
- entries->var = 0;
- entries->set = 0;
- entries->next = 0;
- last = entries;
- count = 0;
- onRemove = [this](ArrayEintrag<TYP*>* entry) {
- if (!entry) return (ArrayEintrag<TYP*>*)0;
- if (entry->next)
- {
- if (entry->set && entry->var) entry->var->release();
- entry->var = entry->next->var;
- entry->set = entry->next->set;
- }
- else
- {
- if (entry->set && entry->var) entry->var->release();
- entry->set = 0;
- }
- ArrayEintrag<TYP*>* del = entry->next;
- if (entry->next)
- entry->next = entry->next->next;
- else
- entry->next = 0;
- if (del)
- {
- del->var = 0;
- del->set = 0;
- del->next = 0;
- if (last == del) last = entry;
- delete del;
- }
- count--;
- return entry->set ? entry : 0;
- };
- }
- //! Kopiert eine Linked list
- RCArray(const RCArray& arr)
- : RCArray()
- {
- int anz = arr.getEintragAnzahl();
- for (int i = 0; i < anz; i++)
- add(arr.get(i));
- }
- //! 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)
- {
- count++;
- if (!last->set)
- {
- last->var = t;
- last->set = 1;
- return;
- }
- last->next = new ArrayEintrag<TYP*>();
- last = last->next;
- last->var = t;
- last->set = 1;
- }
- //! 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 || i > count)
- throwOutOfRange(__FILE__, __LINE__, i, count);
- if (i == count)
- {
- add(t);
- return;
- }
- ArrayEintrag<TYP*>* e = entries;
- for (int a = 0; a < i; ++a)
- 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;
- if (last->next) last = last->next;
- count++;
- }
- //! 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 || i >= count)
- throwOutOfRange(__FILE__, __LINE__, i, count);
- ArrayEintrag<TYP*>* e = entries;
- for (int a = 0; a < i; ++a)
- 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 == p) return;
- if (i < 0 || p < 0 || i >= count || p >= count)
- throwOutOfRange(__FILE__, __LINE__, i, count);
- ArrayEintrag<TYP*>* ve = 0;
- ArrayEintrag<TYP*>* e = entries;
- for (int a = 0; a < i; ++a)
- {
- ve = e;
- e = e->next;
- }
- ArrayEintrag<TYP*>* e2 = entries == e ? e->next : entries;
- ArrayEintrag<TYP*>* ve2 = 0;
- for (int a = 0; a < p; ++a)
- {
- ve2 = e2;
- if (e2->next == e)
- e2 = e->next;
- else
- e2 = e2->next;
- }
- if (last == e)
- last = e2;
- else if (last == e2)
- last = e;
- 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 || i >= count)
- throwOutOfRange(__FILE__, __LINE__, i, count);
- ArrayEintrag<TYP*>* e = entries;
- for (int a = 0; a < i; ++a)
- e = e->next;
- 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;
- if (last == del) last = e;
- delete del;
- }
- count--;
- }
- //! 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()
- {
- for (ArrayEintrag<TYP*>* e = entries; e;)
- {
- if (e && e->var && e->set) e->var->release();
- auto tmp = e->next;
- delete e;
- e = tmp;
- }
- entries = new ArrayEintrag<TYP*>();
- entries->set = 0;
- entries->next = 0;
- last = entries;
- count = 0;
- }
- //! Gibt einen Iterator zurück.
- //! Mit ++ kann durch die Liste iteriert werden
- Iterator<TYP*> begin() const
- {
- return Iterator<TYP*>(entries, onRemove);
- }
- Iterator<TYP*> end() const
- {
- return Iterator<TYP*>(0, onRemove);
- }
- //! Gibt zurück, wie viele Elemente in der Liste sind
- int getEintragAnzahl() const
- {
- return count;
- }
- int getLastIndex() const
- {
- return count - 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 || i >= count)
- throwOutOfRange(__FILE__, __LINE__, i, count);
- 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 || i >= count)
- throwOutOfRange(__FILE__, __LINE__, i, count);
- 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
- {
- return i >= 0 && i < count;
- }
- RCArray& operator=(const RCArray& arr)
- {
- leeren();
- int anz = arr.getEintragAnzahl();
- for (int i = 0; i < anz; i++)
- add(arr.get(i));
- return *this;
- }
- };
- } // namespace Framework
- #endif
|