2 İşlemeler 14ac2dfc35 ... dcc59f9131

Yazar SHA1 Mesaj Tarih
  Kolja Strohm dcc59f9131 add CriticalLock that unlocks automatically if the current scope is left 11 ay önce
  Kolja Strohm 2e9d6d994a improve performance of text operations 11 ay önce
4 değiştirilmiş dosya ile 354 ekleme ve 194 silme
  1. 13 2
      Critical.cpp
  2. 13 0
      Critical.h
  3. 287 191
      Text.cpp
  4. 41 1
      Text.h

+ 13 - 2
Critical.cpp

@@ -26,7 +26,7 @@ Critical::~Critical()
 
 
 pthread_t CachedCurrentThread()
 pthread_t CachedCurrentThread()
 {
 {
-    volatile thread_local static  pthread_t t = GetCurrentThread();
+    volatile thread_local static pthread_t t = GetCurrentThread();
     return (pthread_t)t;
     return (pthread_t)t;
 }
 }
 
 
@@ -151,4 +151,15 @@ void Synchronizer::notifyAll()
 int Synchronizer::getNumberOfWaitingThreads() const
 int Synchronizer::getNumberOfWaitingThreads() const
 {
 {
     return numWaiting;
     return numWaiting;
-}
+}
+
+Framework::CriticalLock::CriticalLock(Critical* critical)
+{
+    this->critical = critical;
+    critical->lock();
+}
+
+Framework::CriticalLock::~CriticalLock()
+{
+    critical->unlock();
+}

+ 13 - 0
Critical.h

@@ -34,6 +34,19 @@ namespace Framework
         DLLEXPORT const Thread* zOwner() const;
         DLLEXPORT const Thread* zOwner() const;
     };
     };
 
 
+    class CriticalLock
+    {
+    private:
+        Critical* critical;
+
+    public:
+        DLLEXPORT CriticalLock(Critical* critical);
+        DLLEXPORT ~CriticalLock();
+    };
+
+#define LOCK(x)     CriticalLock _lock(x)
+#define LOCKN(x, i) CriticalLock _lock_##i(x)
+
     class Synchronizer
     class Synchronizer
     {
     {
     private:
     private:

+ 287 - 191
Text.cpp

@@ -7,6 +7,7 @@
 #ifndef WIN32
 #ifndef WIN32
 #    include <string.h>
 #    include <string.h>
 #endif
 #endif
+#include "Regex.h"
 
 
 using namespace Framework;
 using namespace Framework;
 
 
@@ -36,38 +37,58 @@ FlushingOStream::~FlushingOStream()
     onDestroy();
     onDestroy();
 }
 }
 
 
+Text::Text(char* t, int l)
+    : Text()
+{
+    setTextZ(t, l); // Text setzen
+}
+
 // inhalt der Text Klasse aus Text.h
 // inhalt der Text Klasse aus Text.h
 // Konstruktor
 // Konstruktor
 Text::Text()
 Text::Text()
     : ReferenceCounter(),
     : ReferenceCounter(),
       txt(0),
       txt(0),
+      length(0),
       suchGBeg(0),
       suchGBeg(0),
       suchGEnd(0),
       suchGEnd(0),
       precision(-1),
       precision(-1),
-      stringWriter(DynamicBuffer([this](std::stringbuf& buf) {
-          std::string str = buf.str();
-          this->append(str.c_str());
-          buf.str("");
-          return 0;
-      }))
+      stringWriter(0)
 {
 {
     setText("");
     setText("");
 }
 }
 
 
 Text::Text(const Text& txt)
 Text::Text(const Text& txt)
-    : Text()
+    : ReferenceCounter(),
+      txt(0),
+      length(0),
+      suchGBeg(0),
+      suchGEnd(0),
+      precision(-1),
+      stringWriter(0)
 {
 {
-    setText(txt);
+    setText(txt, txt.length);
 }
 }
 
 
 Text::Text(const char* t)
 Text::Text(const char* t)
-    : Text()
+    : ReferenceCounter(),
+      txt(0),
+      length(0),
+      suchGBeg(0),
+      suchGEnd(0),
+      precision(-1),
+      stringWriter(0)
 {
 {
     setText(t); // Text setzen
     setText(t); // Text setzen
 }
 }
 
 
 Text::Text(int zahl)
 Text::Text(int zahl)
-    : Text()
+    : ReferenceCounter(),
+      txt(0),
+      length(0),
+      suchGBeg(0),
+      suchGEnd(0),
+      precision(-1),
+      stringWriter(0)
 {
 {
     *this = zahl;
     *this = zahl;
 }
 }
@@ -91,14 +112,21 @@ Text::Text(float num)
 // Destruktor
 // Destruktor
 Text::~Text()
 Text::~Text()
 {
 {
+    if (stringWriter) delete stringWriter;
     delete[] txt;
     delete[] txt;
 }
 }
 
 
+void Framework::Text::setTextZ(char* t, int l)
+{
+    delete[] txt; // alter Text löschen
+    length = l;
+    txt = t; // neuen Text erstellen
+}
+
 void Text::toUpperCase()
 void Text::toUpperCase()
 {
 {
     if (!txt) return;
     if (!txt) return;
-    int len = textLength(txt);
-    for (int i = 0; i < len; i++)
+    for (int i = 0; i < length; i++)
     {
     {
         if (txt[i] >= 'a' && txt[i] <= 'z') txt[i] = (char)(txt[i] - 32);
         if (txt[i] >= 'a' && txt[i] <= 'z') txt[i] = (char)(txt[i] - 32);
         switch (txt[i])
         switch (txt[i])
@@ -119,8 +147,7 @@ void Text::toUpperCase()
 void Text::toLowerCase()
 void Text::toLowerCase()
 {
 {
     if (!txt) return;
     if (!txt) return;
-    int len = textLength(txt);
-    for (int i = 0; i < len; i++)
+    for (int i = 0; i < length; i++)
     {
     {
         if (txt[i] >= 'A' && txt[i] <= 'Z') txt[i] = (char)(txt[i] + 32);
         if (txt[i] >= 'A' && txt[i] <= 'Z') txt[i] = (char)(txt[i] + 32);
         switch (txt[i])
         switch (txt[i])
@@ -149,22 +176,23 @@ void Text::setSuchGrenzen(
 
 
 void Text::setText(const char* t) // ersetzt den Text
 void Text::setText(const char* t) // ersetzt den Text
 {
 {
-    delete[] txt;                   // alter Text löschen
-    int l = (int)textLength(t);     // Länge des neuen Textes ermitteln
-    txt = new char[(__int64)l + 1]; // neuen Text erstellen
-    for (int i = 0; i < l; ++i)     // Text befüllen
+    delete[] txt;                        // alter Text löschen
+    length = (int)textLength(t);         // Länge des neuen Textes ermitteln
+    txt = new char[(__int64)length + 1]; // neuen Text erstellen
+    for (int i = 0; i < length; ++i)     // Text befüllen
         txt[i] = t[i];
         txt[i] = t[i];
-    txt[l] = '\0'; // Textende Festlegen
+    txt[length] = '\0'; // Textende Festlegen
 }
 }
 
 
 // unconstant
 // unconstant
 void Text::setText(const char* t, int l) // ersetzt den Text
 void Text::setText(const char* t, int l) // ersetzt den Text
 {
 {
-    delete[] txt;                   // alter Text löschen
-    txt = new char[(__int64)l + 1]; // neuen Text erstellen
-    for (int i = 0; i < l; ++i)     // Text befüllen
+    delete[] txt; // alter Text löschen
+    length = l;
+    txt = new char[(__int64)length + 1]; // neuen Text erstellen
+    for (int i = 0; i < length; ++i)     // Text befüllen
         txt[i] = t[i];
         txt[i] = t[i];
-    txt[l] = '\0'; // Textende Festlegen
+    txt[length] = '\0'; // Textende Festlegen
 }
 }
 
 
 void Text::setText(Text* t)
 void Text::setText(Text* t)
@@ -180,63 +208,55 @@ void Text::append(char c) // h
 
 
 void Text::append(const char* t) // hängt an den Text an
 void Text::append(const char* t) // hängt an den Text an
 {
 {
-    int tl = (int)textLength(t);                 // länge der übergabe
-    int txl = getLength();                       // länge des Textes
-    char* res = new char[(__int64)tl + txl + 1]; // neuen Text erstellen
-    for (int i = 0; i < txl; ++i)                // mit jetzigem Text füllen
+    int tl = (int)textLength(t);                    // länge der übergabe
+    char* res = new char[(__int64)tl + length + 1]; // neuen Text erstellen
+    for (int i = 0; i < length; ++i)                // mit jetzigem Text füllen
         res[i] = txt[i];
         res[i] = txt[i];
     for (int i = 0; i < tl; ++i) // Übergabe anhängen
     for (int i = 0; i < tl; ++i) // Übergabe anhängen
-        res[txl + i] = t[i];
-    res[txl + tl] = '\0'; // Textende festlegen
-    setText(res);         // Test setzen
-    delete[] res;         // Speicher freigeben
+        res[length + i] = t[i];
+    res[length + tl] = '\0';    // Textende festlegen
+    setTextZ(res, length + tl); // Test setzen
 }
 }
 
 
 void Text::appendHex(int num) // hängt die zahl in hex anden Text an
 void Text::appendHex(int num) // hängt die zahl in hex anden Text an
 {
 {
-    int l = getLength();
-    char* res = new char[(__int64)l + 9];
-    for (int i = 0; i < l; ++i)
+    char* res = new char[(__int64)length + 9];
+    for (int i = 0; i < length; ++i)
         res[i] = txt[i];
         res[i] = txt[i];
     std::stringstream stream;
     std::stringstream stream;
     stream << std::setfill('0') << std::setw((int)sizeof(int) * 2) << std::hex
     stream << std::setfill('0') << std::setw((int)sizeof(int) * 2) << std::hex
            << num;
            << num;
     std::string str = stream.str();
     std::string str = stream.str();
-    for (int i = l; i < l + 8; ++i)
-        res[i] = str.c_str()[i - l];
-    res[l + 8] = 0;
-    setText(res);
-    delete[] res;
+    for (int i = length; i < length + 8; ++i)
+        res[i] = str.c_str()[i - length];
+    res[length + 8] = 0;
+    setTextZ(res, length + 8);
 }
 }
 
 
 void Text::appendHex(__int64 num) // hängt die zahl in hex anden Text an
 void Text::appendHex(__int64 num) // hängt die zahl in hex anden Text an
 {
 {
-    int l = getLength();
-    char* res = new char[(__int64)l + 17];
-    for (int i = 0; i < l; ++i)
+    char* res = new char[(__int64)length + 17];
+    for (int i = 0; i < length; ++i)
         res[i] = txt[i];
         res[i] = txt[i];
     std::stringstream stream;
     std::stringstream stream;
     stream << std::setfill('0') << std::setw((int)sizeof(__int64) * 2)
     stream << std::setfill('0') << std::setw((int)sizeof(__int64) * 2)
            << std::hex << num;
            << std::hex << num;
     std::string str = stream.str();
     std::string str = stream.str();
-    for (int i = l; i < l + 16; ++i)
-        res[i] = str.c_str()[i - l];
-    res[l + 16] = 0;
-    setText(res);
-    delete[] res;
+    for (int i = length; i < length + 16; ++i)
+        res[i] = str.c_str()[i - length];
+    res[length + 16] = 0;
+    setTextZ(res, length + 16);
 }
 }
 
 
-void Text::append(const char* t, int l) // hängt an den Text an
-{
-    int txl = getLength();                      // länge des Textes
-    char* res = new char[(__int64)l + txl + 1]; // neuen Text erstellen
-    for (int i = 0; i < txl; ++i)               // mit jetzigem Text füllen
+void Text::append(const char* t, int l)            // hängt an den Text an
+{                                                  // länge des Textes
+    char* res = new char[(__int64)l + length + 1]; // neuen Text erstellen
+    for (int i = 0; i < length; ++i)               // mit jetzigem Text füllen
         res[i] = txt[i];
         res[i] = txt[i];
     for (int i = 0; i < l; ++i) // Übergabe anhängen
     for (int i = 0; i < l; ++i) // Übergabe anhängen
-        res[txl + i] = t[i];
-    res[txl + l] = '\0';   // Textende festlegen
-    setText(res, txl + l); // Test setzen
-    delete[] res;          // Speicher freigeben
+        res[length + i] = t[i];
+    res[length + l] = '\0';    // Textende festlegen
+    setTextZ(res, length + l); // Test setzen
 }
 }
 
 
 void Text::append(Text* t)
 void Text::append(Text* t)
@@ -275,7 +295,20 @@ void Text::append(double num)
     std::stringstream ss;
     std::stringstream ss;
     if (precision >= 0) ss.precision(precision);
     if (precision >= 0) ss.precision(precision);
     ss << std::fixed << num;
     ss << std::fixed << num;
-    append(ss.str().c_str());
+    std::string string = ss.str();
+    const char* str = string.c_str();
+    int len = (int)textLength(str);
+    for (int i = len - 1; i > 0; i--)
+    {
+        if (str[i] == '0')
+            len--;
+        else
+        {
+            if (str[i] == '.') len--;
+            break;
+        }
+    }
+    append(str, len);
 }
 }
 
 
 void Text::append(float num)
 void Text::append(float num)
@@ -283,48 +316,66 @@ void Text::append(float num)
     std::stringstream ss;
     std::stringstream ss;
     if (precision >= 0) ss.precision(precision);
     if (precision >= 0) ss.precision(precision);
     ss << std::fixed << num;
     ss << std::fixed << num;
-    append(ss.str().c_str());
+    std::string string = ss.str();
+    const char* str = string.c_str();
+    int len = (int)textLength(str);
+    for (int i = len - 1; i > 0; i--)
+    {
+        if (str[i] == '0')
+            len--;
+        else
+        {
+            if (str[i] == '.') len--;
+            break;
+        }
+    }
+    append(str, len);
 }
 }
 
 
 //! Gibt einen ostream zurück, der alle ausgaben an diesen Text anhängt
 //! Gibt einen ostream zurück, der alle ausgaben an diesen Text anhängt
 FlushingOStream Text::append()
 FlushingOStream Text::append()
 {
 {
-    return FlushingOStream(&stringWriter);
+    if (!stringWriter)
+    {
+        stringWriter = new DynamicBuffer([this](std::stringbuf& buf) {
+            std::string str = buf.str();
+            this->append(str.c_str());
+            buf.str("");
+            return 0;
+        });
+    }
+    return FlushingOStream(stringWriter);
 }
 }
 
 
 void Text::insert(int p, char c) // Fügt an stelle p ein
 void Text::insert(int p, char c) // Fügt an stelle p ein
 {
 {
-    if (p > getLength() || p < 0) // Auf unsinnige übergabe prüfen
+    if (p > length || p < 0) // Auf unsinnige übergabe prüfen
         return;
         return;
-    int txl = getLength();                  // Länge des Textes
-    char* res = new char[(__int64)txl + 2]; // neuer Text erstellen
-    for (int i = 0; i < p; ++i)             // Text füllen
+    char* res = new char[(__int64)length + 2]; // neuer Text erstellen
+    for (int i = 0; i < p; ++i)                // Text füllen
         res[i] = txt[i];
         res[i] = txt[i];
     res[p] = c;
     res[p] = c;
-    for (int i = p; i < txl; ++i) // Text füllen
+    for (int i = p; i < length; ++i) // Text füllen
         res[i + 1] = txt[i];
         res[i + 1] = txt[i];
-    res[txl + 1] = '\0'; // Text ende festlegen
-    setText(res);        // Text setzen
-    delete[] res;        // Speicher freigeben
+    res[length + 1] = '\0';    // Text ende festlegen
+    setTextZ(res, length + 1); // Text setzen
 }
 }
 
 
 void Text::insert(int p, const char* t) // Fügt an stelle p ein
 void Text::insert(int p, const char* t) // Fügt an stelle p ein
 {
 {
-    if (p > getLength() || p < 0
+    if (p > length || p < 0
         || textLength(t) <= 0) // Auf unsinnige übergabe prüfen
         || textLength(t) <= 0) // Auf unsinnige übergabe prüfen
         return;
         return;
-    int tl = (int)textLength(t);                 // Länge der übergabe
-    int txl = getLength();                       // Länge des Textes
-    char* res = new char[(__int64)tl + txl + 1]; // neuer Text erstellen
-    for (int i = 0; i < p; ++i)                  // Text füllen
+    int tl = (int)textLength(t);                    // Länge der übergabe
+    char* res = new char[(__int64)tl + length + 1]; // neuer Text erstellen
+    for (int i = 0; i < p; ++i)                     // Text füllen
         res[i] = txt[i];
         res[i] = txt[i];
     for (int i = 0; i < tl; ++i) // Text einfügen
     for (int i = 0; i < tl; ++i) // Text einfügen
         res[i + p] = t[i];
         res[i + p] = t[i];
-    for (int i = p; i < txl; ++i) // Text füllen
+    for (int i = p; i < length; ++i) // Text füllen
         res[i + tl] = txt[i];
         res[i + tl] = txt[i];
-    res[tl + txl] = '\0'; // Text ende festlegen
-    setText(res);         // Text setzen
-    delete[] res;         // Speicher freigeben
+    res[tl + length] = '\0';    // Text ende festlegen
+    setTextZ(res, length + tl); // Text setzen
 }
 }
 
 
 void Text::insert(int p, Text* t)
 void Text::insert(int p, Text* t)
@@ -334,6 +385,73 @@ void Text::insert(int p, Text* t)
     t->release();                // Übergabe loslassen
     t->release();                // Übergabe loslassen
 }
 }
 
 
+void Framework::Text::regexReplace(
+    const char* regex, const char* replacement, Regex::RegexConfig* config)
+{
+    regexReplace(
+        regex, [replacement](Regex::Result&) { return replacement; }, config);
+}
+
+void Framework::Text::regexReplace(const char* regex,
+    std::function<Text(Regex::Result&)> replacementFunction,
+    Regex::RegexConfig* config)
+{
+    auto matcher
+        = config == 0 ? Regex::parse(regex) : Regex::parse(regex, *config);
+    if (!matcher) return;
+    auto result = matcher->match(txt, length);
+    if (result->getEintragAnzahl() > 0)
+    {
+        int replacedLength = 0;
+        int replacementLength = 0;
+        Text* replacements = new Text[result->getEintragAnzahl()];
+        int i = 0;
+#ifdef WIN32
+#    pragma warning(push)
+#    pragma warning(disable : 6385)
+#endif
+        for (Regex::Result* match : *result)
+        {
+            replacedLength += match->getEnd() - match->getStart();
+            replacements[i] = replacementFunction(*match);
+            replacementLength += replacements[i].getLength();
+            i++;
+        }
+        int newLength = length - replacedLength + replacementLength;
+        char* newText = new char[(__int64)newLength + 1];
+        int pos = 0;
+        int newPos = 0;
+        int j = 0;
+        for (Regex::Result* match : *result)
+        {
+            for (int i = 0; i < match->getStart() - pos; i++)
+            {
+                newText[newPos + i] = txt[pos + i];
+            }
+            newPos += match->getStart() - pos;
+            pos = match->getEnd();
+            for (int i = 0; i < replacements[j].getLength(); i++)
+            {
+                newText[newPos + i] = replacements[j][i];
+            }
+            newPos += replacements[j].getLength();
+            j++;
+        }
+        for (int i = pos; i < getLength(); i++)
+        {
+            newText[newPos + i - pos] = txt[i];
+        }
+#ifdef WIN32
+#    pragma warning(pop)
+#endif
+        newText[newLength] = '\0';
+        setTextZ(newText, newLength);
+        delete[] replacements;
+    }
+    result->release();
+    matcher->release();
+}
+
 void Text::ersetzen(
 void Text::ersetzen(
     int p1, int p2, const char* t) // Ersetzt den Text von p1 bis p2
     int p1, int p2, const char* t) // Ersetzt den Text von p1 bis p2
 {
 {
@@ -360,9 +478,8 @@ void Text::ersetzen(char c1, char c2) // ersetzt jedes c1 durch c2
         return;
         return;
     if (!hat(c1)) // prüfen ob c1 vorhanden
     if (!hat(c1)) // prüfen ob c1 vorhanden
         return;
         return;
-    int l = getLength(); // Text Länge
     int suchGCount = 0;
     int suchGCount = 0;
-    for (int i = 0; i < l; ++i) // Text durchsuchen
+    for (int i = 0; i < length; ++i) // Text durchsuchen
     {
     {
         bool b = suchGCount != 0;
         bool b = suchGCount != 0;
         if (txt[i] == c1 && !suchGCount) txt[i] = c2; // Text ersetzen
         if (txt[i] == c1 && !suchGCount) txt[i] = c2; // Text ersetzen
@@ -374,23 +491,24 @@ void Text::ersetzen(char c1, char c2) // ersetzt jedes c1 durch c2
 
 
 void Text::ersetzen(const char* t1, const char* t2) // ersetzt jedes t1 durch t2
 void Text::ersetzen(const char* t1, const char* t2) // ersetzt jedes t1 durch t2
 {
 {
-    int txl = getLength();         // Text Länge
     int t1l = (int)textLength(t1); // Länge der Übergaben
     int t1l = (int)textLength(t1); // Länge der Übergaben
     int t2l = (int)textLength(t2);
     int t2l = (int)textLength(t2);
-    if (t1l > txl || t1l <= 0) // Auf unsinnige übergabe prüfen
+    if (t1l > length || t1l <= 0) // Auf unsinnige übergabe prüfen
         return;
         return;
     if (!hat(t1)) // prüfen ob t1 vorhanden
     if (!hat(t1)) // prüfen ob t1 vorhanden
         return;
         return;
     int anz = anzahlVon(t1); // Anzahl von t1 im Text
     int anz = anzahlVon(t1); // Anzahl von t1 im Text
     int* begin = new int[anz];
     int* begin = new int[anz];
     int* end = new int[anz];
     int* end = new int[anz];
+    int searchStart = 0;
     for (int i = 0; i < anz; ++i) // Positionen von t1 speichern
     for (int i = 0; i < anz; ++i) // Positionen von t1 speichern
     {
     {
-        begin[i] = positionVon(t1, i);
+        begin[i] = positionVon(searchStart, t1);
         end[i] = begin[i] + t1l;
         end[i] = begin[i] + t1l;
+        searchStart = end[i];
     }
     }
-    int resl = (txl - (anz * t1l)) + (anz * t2l) + 1; // Länge des Ergebneses
-    char* res = new char[resl];                       // neuer Text erstellen
+    int resl = (length - (anz * t1l)) + (anz * t2l) + 1; // Länge des Ergebneses
+    char* res = new char[resl];                          // neuer Text erstellen
     int rep = 0;              // Speichert bei welchen t1 man sich befindet
     int rep = 0;              // Speichert bei welchen t1 man sich befindet
     int last = 0;             // Füllposition von txt
     int last = 0;             // Füllposition von txt
     int neu = 0;              // Füllporition von res
     int neu = 0;              // Füllporition von res
@@ -416,10 +534,9 @@ void Text::ersetzen(const char* t1, const char* t2) // ersetzt jedes t1 durch t2
         }
         }
     }
     }
     res[resl - 1] = '\0'; // Textende festlegen
     res[resl - 1] = '\0'; // Textende festlegen
-    setText(res);         // Text setzen
+    setTextZ(res, resl);  // Text setzen
     delete[] begin;       // Speicher freigeben
     delete[] begin;       // Speicher freigeben
     delete[] end;
     delete[] end;
-    delete[] res;
 }
 }
 
 
 void Text::ersetzen(Text* t1, const char* t2)
 void Text::ersetzen(Text* t1, const char* t2)
@@ -460,9 +577,8 @@ void Text::ersetzen(int index, char c1, char c2) // ersetzt das i-te c1 durch c2
 void Text::ersetzen(
 void Text::ersetzen(
     int index, const char* t1, const char* t2) // ersetzt das i-te t1 durch t2
     int index, const char* t1, const char* t2) // ersetzt das i-te t1 durch t2
 {
 {
-    int txl = getLength();                   // Text Länge
-    int t1l = (int)textLength(t1);           // Länge der Übergaben
-    if (t1l >= txl || t1l <= 0 || index < 0) // Auf unsinnige übergabe prüfen
+    int t1l = (int)textLength(t1);              // Länge der Übergaben
+    if (t1l >= length || t1l <= 0 || index < 0) // Auf unsinnige übergabe prüfen
         return;
         return;
     if (!hat(t1)) // prüfen ob t1 vorhanden
     if (!hat(t1)) // prüfen ob t1 vorhanden
         return;
         return;
@@ -504,23 +620,20 @@ void Text::fillText(
     for (int i = 0; i < len; ++i)
     for (int i = 0; i < len; ++i)
         res[i] = c;
         res[i] = c;
     res[len] = '\0';
     res[len] = '\0';
-    setText(res);
-    delete[] res;
+    setTextZ(res, len);
 }
 }
 
 
 void Text::remove(int p) // löscht p
 void Text::remove(int p) // löscht p
 {
 {
-    int l = getLength(); // Text Länge
-    if (p < 0 || p >= l) // Auf unsinnige übergabe prüfen
+    if (p < 0 || p >= length) // Auf unsinnige übergabe prüfen
         return;
         return;
-    char* res = new char[l];             // neuen Text anlegen
-    for (int i = 0; i < p && i < l; ++i) // Text befüllen
+    char* res = new char[length];             // neuen Text anlegen
+    for (int i = 0; i < p && i < length; ++i) // Text befüllen
         res[i] = txt[i];
         res[i] = txt[i];
-    for (int i = p + 1; i < l; ++i)
+    for (int i = p + 1; i < length; ++i)
         res[i - 1] = txt[i];
         res[i - 1] = txt[i];
-    res[l - 1] = 0;
-    setText(res); // Text setzen
-    delete[] res; // Speicher freigeben
+    res[length - 1] = 0;
+    setTextZ(res, length - 1); // Text setzen
 }
 }
 
 
 void Text::remove(int p1, int p2) // löscht von p1 zu p2 ( p2 bleibt )
 void Text::remove(int p1, int p2) // löscht von p1 zu p2 ( p2 bleibt )
@@ -532,31 +645,28 @@ void Text::remove(int p1, int p2) // l
         p1 = p2;
         p1 = p2;
         p2 = x;
         p2 = x;
     }
     }
-    int l = getLength(); // Länge des Testes
-    if (p1 < 0)          // Auf unsinnige übergabe prüfen
+    if (p1 < 0) // Auf unsinnige übergabe prüfen
         p1 = 0;
         p1 = 0;
-    if (p2 > l) p2 = l;
-    int resl = l - (p2 - p1);                // Länge vom Ergebnis
+    if (p2 > length) p2 = length;
+    int resl = length - (p2 - p1);           // Länge vom Ergebnis
     char* res = new char[(__int64)resl + 1]; // Neuen Text erstellen
     char* res = new char[(__int64)resl + 1]; // Neuen Text erstellen
     for (int i = 0; i < p1; ++i)             // Text füllen
     for (int i = 0; i < p1; ++i)             // Text füllen
         res[i] = txt[i];
         res[i] = txt[i];
-    for (int i = p2; i < l; ++i)
+    for (int i = p2; i < length; ++i)
         res[i - (p2 - p1)] = txt[i];
         res[i - (p2 - p1)] = txt[i];
-    res[resl] = '\0'; // Testende festlegen
-    setText(res);     // Text setzen
-    delete[] res;     // Speicher freigeben
+    res[resl] = '\0';    // Testende festlegen
+    setTextZ(res, resl); // Text setzen
 }
 }
 
 
 void Text::remove(char c) // löscht jetes c
 void Text::remove(char c) // löscht jetes c
 {
 {
     if (!hat(c)) // prüfen ob c vorhanden
     if (!hat(c)) // prüfen ob c vorhanden
         return;
         return;
-    int l = getLength();                        // Länge des Textes
-    int anz = anzahlVon(c);                     // Anzahl von c
-    char* res = new char[(__int64)l - anz + 1]; // neuen Text erstellen
+    int anz = anzahlVon(c);                          // Anzahl von c
+    char* res = new char[(__int64)length - anz + 1]; // neuen Text erstellen
     int anz2 = 0;
     int anz2 = 0;
     int suchGCount = 0;
     int suchGCount = 0;
-    for (int i = 0; i < l; ++i) // Text befüllen
+    for (int i = 0; i < length; ++i) // Text befüllen
     {
     {
         bool b = suchGCount != 0;
         bool b = suchGCount != 0;
         if (txt[i] == c && !suchGCount)
         if (txt[i] == c && !suchGCount)
@@ -573,16 +683,14 @@ void Text::remove(char c) // l
                 res[i - anz2] = txt[i];
                 res[i - anz2] = txt[i];
         }
         }
     }
     }
-    res[l - anz] = '\0'; // Textende festlegen
-    setText(res);        // Text setzen
-    delete[] res;        // Speicher freigeben
+    res[length - anz] = '\0';    // Textende festlegen
+    setTextZ(res, length - anz); // Text setzen
 }
 }
 
 
 void Text::remove(const char* t) // löscht jetes t
 void Text::remove(const char* t) // löscht jetes t
 {
 {
     int tl = (int)textLength(t); // Länge der Übergabe
     int tl = (int)textLength(t); // Länge der Übergabe
-    int txl = getLength();       // Länge des Textes
-    if (tl <= 0 || tl > txl)     // Auf unsinnige übergabe prüfen
+    if (tl <= 0 || tl > length)  // Auf unsinnige übergabe prüfen
         return;
         return;
     if (!hat(t)) // prüfen ob Text ein t enthält
     if (!hat(t)) // prüfen ob Text ein t enthält
         return;
         return;
@@ -590,10 +698,10 @@ void Text::remove(const char* t) // l
     int* begin = new int[anz];
     int* begin = new int[anz];
     for (int i = 0; i < anz; ++i) // begin aller t-s finden
     for (int i = 0; i < anz; ++i) // begin aller t-s finden
         begin[i] = positionVon(t, i);
         begin[i] = positionVon(t, i);
-    int resl = txl - (anz * tl);             // Länge vom Ergebnes
+    int resl = length - (anz * tl);          // Länge vom Ergebnes
     char* res = new char[(__int64)resl + 1]; // neuen Text erzeugen
     char* res = new char[(__int64)resl + 1]; // neuen Text erzeugen
     int del = 0;
     int del = 0;
-    for (int i = 0; i < txl; ++i) // Text befüllen
+    for (int i = 0; i < length; ++i) // Text befüllen
     {
     {
         if (del < anz && i == begin[del]) // Text auslassen
         if (del < anz && i == begin[del]) // Text auslassen
         {
         {
@@ -603,10 +711,9 @@ void Text::remove(const char* t) // l
         else
         else
             res[i - (del * tl)] = txt[i]; // Text befüllen
             res[i - (del * tl)] = txt[i]; // Text befüllen
     }
     }
-    res[resl] = '\0'; // Text ende festlegen
-    setText(res);     // Text setzen
+    res[resl] = '\0';    // Text ende festlegen
+    setTextZ(res, resl); // Text setzen
     delete[] begin;
     delete[] begin;
-    delete[] res; // Speicher freigeben
 }
 }
 
 
 void Text::remove(Text* t)
 void Text::remove(Text* t)
@@ -625,16 +732,14 @@ void Text::remove(int index, char c)
         return;
         return;
     int pos = positionVon(c, index); // Position vom i-ten c
     int pos = positionVon(c, index); // Position vom i-ten c
     if (pos < 0) return;
     if (pos < 0) return;
-    int l = getLength(); // Länge des Textes
-    if (!l) return;
-    char* res = new char[l];               // neuen Text erzeugen
-    for (int i = 0; i < pos && i < l; ++i) // Text befüllen
+    if (!length) return;
+    char* res = new char[length];               // neuen Text erzeugen
+    for (int i = 0; i < pos && i < length; ++i) // Text befüllen
         res[i] = txt[i];
         res[i] = txt[i];
-    for (int i = pos + 1; i < l; ++i)
+    for (int i = pos + 1; i < length; ++i)
         res[i - 1] = txt[i];
         res[i - 1] = txt[i];
-    res[l - 1] = '\0'; // Text ende festlegen
-    setText(res);      // Text setzen
-    delete[] res;      // Speicher freigeben
+    res[length - 1] = '\0';    // Text ende festlegen
+    setTextZ(res, length - 1); // Text setzen
 }
 }
 
 
 void Text::remove(int index, const char* t) // löscht das i-te t
 void Text::remove(int index, const char* t) // löscht das i-te t
@@ -647,16 +752,14 @@ void Text::remove(int index, const char* t) // l
         return;
         return;
     int pos = positionVon(t, index); // Position vom i-ten c
     int pos = positionVon(t, index); // Position vom i-ten c
     if (pos < 0) return;
     if (pos < 0) return;
-    int l = getLength(); // Länge des Textes
-    if (!l) return;
-    char* res = new char[(__int64)l - tl + 1];      // neuen Text erzeugen
-    for (int i = 0; i < pos && i < l - tl + 1; ++i) // Text befüllen
+    if (!length) return;
+    char* res = new char[(__int64)length - tl + 1];      // neuen Text erzeugen
+    for (int i = 0; i < pos && i < length - tl + 1; ++i) // Text befüllen
         res[i] = txt[i];
         res[i] = txt[i];
-    for (int i = pos + tl; i < l; ++i)
+    for (int i = pos + tl; i < length; ++i)
         res[i - tl] = txt[i];
         res[i - tl] = txt[i];
-    res[l - tl] = '\0'; // Text ende festlegen
-    setText(res);       // Text setzen
-    delete[] res;       // Speicher freigeben
+    res[length - tl] = '\0';    // Text ende festlegen
+    setTextZ(res, length - tl); // Text setzen
 }
 }
 
 
 void Text::remove(int i, Text* t)
 void Text::remove(int i, Text* t)
@@ -706,8 +809,7 @@ void Text::setPrecision(
 // constant
 // constant
 int Text::getLength() const // gibt die Text länge zurück
 int Text::getLength() const // gibt die Text länge zurück
 {
 {
-    if (!txt) return -1;
-    return textLength(txt);
+    return length;
 }
 }
 
 
 int Text::getLKick(int pos) const
 int Text::getLKick(int pos) const
@@ -749,12 +851,11 @@ int Text::getOKick(int pos) const
 
 
 int Text::getRKick(int pos) const
 int Text::getRKick(int pos) const
 {
 {
-    int tl = getLength();
     if (txt[pos] == ' ')
     if (txt[pos] == ' ')
     {
     {
         int ret = 1;
         int ret = 1;
-        for (;
-             ret + pos < tl && txt[pos + ret] == ' ' && txt[pos + ret] != '\n';
+        for (; ret + pos < length && txt[pos + ret] == ' '
+               && txt[pos + ret] != '\n';
              ++ret)
              ++ret)
             ;
             ;
         return pos + ret;
         return pos + ret;
@@ -762,8 +863,8 @@ int Text::getRKick(int pos) const
     else
     else
     {
     {
         int ret = 1;
         int ret = 1;
-        for (;
-             ret + pos < tl && txt[pos + ret] != ' ' && txt[pos + ret] != '\n';
+        for (; ret + pos < length && txt[pos + ret] != ' '
+               && txt[pos + ret] != '\n';
              ++ret)
              ++ret)
             ;
             ;
         return pos + ret;
         return pos + ret;
@@ -772,18 +873,18 @@ int Text::getRKick(int pos) const
 
 
 int Text::getUKick(int pos) const
 int Text::getUKick(int pos) const
 {
 {
-    if (!hat('\n')) return getLength();
+    if (!hat('\n')) return length;
     int lpos = 0;
     int lpos = 0;
     while (pos - lpos > 0 && txt[pos - lpos - 1] != '\n')
     while (pos - lpos > 0 && txt[pos - lpos - 1] != '\n')
         ++lpos;
         ++lpos;
     int llen = 1;
     int llen = 1;
-    while (pos + llen - 1 < getLength() && txt[pos + llen - 1] != '\n')
+    while (pos + llen - 1 < length && txt[pos + llen - 1] != '\n')
         ++llen;
         ++llen;
     int vllen = 1;
     int vllen = 1;
-    while (pos + llen + vllen - 1 < getLength()
-           && txt[pos + llen + vllen - 1] != '\n')
+    while (
+        pos + llen + vllen - 1 < length && txt[pos + llen + vllen - 1] != '\n')
         ++vllen;
         ++vllen;
-    if (vllen == 1) return pos + llen < getLength() ? pos + llen : getLength();
+    if (vllen == 1) return pos + llen < length ? pos + llen : length;
     if (vllen < lpos) return pos + llen + vllen - 1;
     if (vllen < lpos) return pos + llen + vllen - 1;
     return pos + llen + lpos;
     return pos + llen + lpos;
 }
 }
@@ -798,13 +899,18 @@ bool Text::hat(Text* t) const // enth
 }
 }
 
 
 bool Text::hat(const char* t) const
 bool Text::hat(const char* t) const
+{
+    return hat(0, t);
+}
+
+bool Framework::Text::hat(int searchStartIndex, const char* t) const
 {
 {
     int tl = (int)textLength(t); // Länge der Übergabe
     int tl = (int)textLength(t); // Länge der Übergabe
-    int txl = getLength();       // Länge des Textes
-    if (tl <= 0 || tl > txl)     // Auf unsinnige übergabe prüfen
+    if (tl <= 0
+        || tl > length - searchStartIndex) // Auf unsinnige übergabe prüfen
         return 0;
         return 0;
     int suchGCount = 0;
     int suchGCount = 0;
-    for (int i = 0; i + tl <= txl; ++i) // Text durchsuchen
+    for (int i = searchStartIndex; i + tl <= length; ++i) // Text durchsuchen
     {
     {
         if (!suchGCount)
         if (!suchGCount)
         {
         {
@@ -845,9 +951,8 @@ bool Text::hatAt(int pos, Text* t) const
 //  pos: die position an der die zeichenkette im string beginnen soll
 //  pos: die position an der die zeichenkette im string beginnen soll
 bool Text::hatAt(int pos, const char* t) const
 bool Text::hatAt(int pos, const char* t) const
 {
 {
-    int tl = (int)textLength(t);   // Länge der Übergabe
-    int txl = getLength();         // Länge des Textes
-    if (tl <= 0 || tl + pos > txl) // Auf unsinnige übergabe prüfen
+    int tl = (int)textLength(t);      // Länge der Übergabe
+    if (tl <= 0 || tl + pos > length) // Auf unsinnige übergabe prüfen
         return 0;
         return 0;
     bool b = 1;
     bool b = 1;
     for (int i = 0; i < tl; ++i) // Text überprüfen
     for (int i = 0; i < tl; ++i) // Text überprüfen
@@ -857,10 +962,9 @@ bool Text::hatAt(int pos, const char* t) const
 
 
 bool Text::hat(char c) const // enthält c
 bool Text::hat(char c) const // enthält c
 {
 {
-    int l = getLength(); // Text Länge
     bool ret = 0;
     bool ret = 0;
     int suchGCount = 0;
     int suchGCount = 0;
-    for (int i = 0; i < l; ++i) // suchen
+    for (int i = 0; i < length; ++i) // suchen
     {
     {
         bool b = suchGCount != 0;
         bool b = suchGCount != 0;
         if (!suchGCount) // überprüfen
         if (!suchGCount) // überprüfen
@@ -875,11 +979,10 @@ bool Text::hat(char c) const // enth
 
 
 bool Text::istGleich(const char* t) const // prüft ob det Text gleich t ist
 bool Text::istGleich(const char* t) const // prüft ob det Text gleich t ist
 {
 {
-    int txl = getLength();       // Text Länge
     int tl = (int)textLength(t); // Länge der Übergabe
     int tl = (int)textLength(t); // Länge der Übergabe
-    if (txl != tl)               // Auf unsinniege Übergabe prüfen
+    if (length != tl)            // Auf unsinniege Übergabe prüfen
         return 0;
         return 0;
-    if (txl == -1) return 1;
+    if (length == -1) return 1;
     bool ret = true;
     bool ret = true;
     for (int i = 0; i < tl; ++i) // prüfen
     for (int i = 0; i < tl; ++i) // prüfen
         ret &= txt[i] == t[i];
         ret &= txt[i] == t[i];
@@ -901,9 +1004,8 @@ const char* Text::getText() const // gibt Text zur
 int Text::anzahlVon(char c) const // gibt die Anzahl von c im Text zurück
 int Text::anzahlVon(char c) const // gibt die Anzahl von c im Text zurück
 {
 {
     int ret = 0;
     int ret = 0;
-    int l = getLength(); // Text Länge
     int suchGCount = 0;
     int suchGCount = 0;
-    for (int i = 0; i < l; ++i) // suchen
+    for (int i = 0; i < length; ++i) // suchen
     {
     {
         bool b = suchGCount != 0;
         bool b = suchGCount != 0;
         ret += txt[i] == c && !suchGCount; // zählen
         ret += txt[i] == c && !suchGCount; // zählen
@@ -917,12 +1019,11 @@ int Text::anzahlVon(char c) const // gibt die Anzahl von c im Text zur
 int Text::anzahlVon(const char* t) const // gibt die Anzahl von t im Text zurück
 int Text::anzahlVon(const char* t) const // gibt die Anzahl von t im Text zurück
 {
 {
     int tl = (int)textLength(t); // Länge der Übergabe
     int tl = (int)textLength(t); // Länge der Übergabe
-    int txl = getLength();       // Länge des Textes
-    if (tl <= 0 || tl > txl)     // Auf unsinnige übergabe prüfen
+    if (tl <= 0 || tl > length)  // Auf unsinnige übergabe prüfen
         return 0;
         return 0;
     int ret = 0;
     int ret = 0;
     int suchGCount = 0;
     int suchGCount = 0;
-    for (int i = 0; i + tl <= txl; ++i) // suchen
+    for (int i = 0; i + tl <= length; ++i) // suchen
     {
     {
         bool b = suchGCount != 0;
         bool b = suchGCount != 0;
         if (!suchGCount)
         if (!suchGCount)
@@ -956,9 +1057,8 @@ int Text::anzahlVon(Text* t) const
 
 
 int Text::positionVon(char c) const // gibt die Position des ersten c zurück
 int Text::positionVon(char c) const // gibt die Position des ersten c zurück
 {
 {
-    int l = getLength(); // Text Länge
     int suchGCount = 0;
     int suchGCount = 0;
-    for (int i = 0; i < l; ++i) // suchen
+    for (int i = 0; i < length; ++i) // suchen
     {
     {
         bool b = suchGCount != 0;
         bool b = suchGCount != 0;
         if (txt[i] == c && !suchGCount) // überprüfen
         if (txt[i] == c && !suchGCount) // überprüfen
@@ -974,12 +1074,16 @@ int Text::positionVon(char c) const // gibt die Position des ersten c zur
 int Text::positionVon(
 int Text::positionVon(
     const char* t) const // gibt die Position des ersten t zurück
     const char* t) const // gibt die Position des ersten t zurück
 {
 {
-    int tl = (int)textLength(t); // Länge der Übergabe
-    int txl = getLength();       // Länge des Textes
-    if (tl <= 0 || tl > txl)     // Auf unsinnige übergabe prüfen
+    return positionVon(0, t);
+}
+
+int Framework::Text::positionVon(int searchStart, const char* t) const
+{
+    int tl = (int)textLength(t);              // Länge der Übergabe
+    if (tl <= 0 || tl > length - searchStart) // Auf unsinnige übergabe prüfen
         return -1;
         return -1;
     int suchGCount = 0;
     int suchGCount = 0;
-    for (int i = 0; i + tl <= txl; ++i) // suchen
+    for (int i = searchStart; i + tl <= length; ++i) // suchen
     {
     {
         bool b = suchGCount != 0;
         bool b = suchGCount != 0;
         if (!suchGCount)
         if (!suchGCount)
@@ -1014,10 +1118,9 @@ int Text::positionVon(Text* t) const
 int Text::positionVon(
 int Text::positionVon(
     char c, int index) const // gibt die Position des i-ten c zurück
     char c, int index) const // gibt die Position des i-ten c zurück
 {
 {
-    int l = getLength(); // Text Länge
     int ii = 0;
     int ii = 0;
     int suchGCount = 0;
     int suchGCount = 0;
-    for (int i = 0; i < l; ++i) // suchen
+    for (int i = 0; i < length; ++i) // suchen
     {
     {
         bool b = suchGCount != 0;
         bool b = suchGCount != 0;
         if (txt[i] == c && !suchGCount) // überprüfen
         if (txt[i] == c && !suchGCount) // überprüfen
@@ -1044,12 +1147,11 @@ int Text::positionVon(
     const char* t, int index) const // gibt die Position des i-ten t zurück
     const char* t, int index) const // gibt die Position des i-ten t zurück
 {
 {
     int tl = (int)textLength(t); // Länge der Übergabe
     int tl = (int)textLength(t); // Länge der Übergabe
-    int txl = getLength();       // Länge des Textes
-    if (tl <= 0 || tl > txl)     // Auf unsinnige übergabe prüfen
+    if (tl <= 0 || tl > length)  // Auf unsinnige übergabe prüfen
         return 0;
         return 0;
     int i2 = 0;
     int i2 = 0;
     int suchGCount = 0;
     int suchGCount = 0;
-    for (int i = 0; i + tl <= txl; ++i) // suchen
+    for (int i = 0; i + tl <= length; ++i) // suchen
     {
     {
         bool b = suchGCount != 0;
         bool b = suchGCount != 0;
         if (!suchGCount)
         if (!suchGCount)
@@ -1102,8 +1204,7 @@ Text* Text::getTeilText(
         p1 = p2;
         p1 = p2;
         p2 = x;
         p2 = x;
     }
     }
-    int l = getLength();  // Text Länge
-    if (p1 < 0 || p2 > l) // Auf unsinnige übergabe prüfen
+    if (p1 < 0 || p2 > length) // Auf unsinnige übergabe prüfen
         return new Text("");
         return new Text("");
     char* cp = new char[(__int64)p2 - p1 + 1]; // neuen Text erstellen
     char* cp = new char[(__int64)p2 - p1 + 1]; // neuen Text erstellen
     for (int i = p1; i < p2; ++i)              // Text befüllen
     for (int i = p1; i < p2; ++i)              // Text befüllen
@@ -1111,9 +1212,7 @@ Text* Text::getTeilText(
         cp[i - p1] = txt[i];
         cp[i - p1] = txt[i];
     }
     }
     cp[p2 - p1] = '\0';
     cp[p2 - p1] = '\0';
-    Text* t = new Text(cp); // Text zurückgeben
-    delete[] cp;
-    return t;
+    return new Text(cp, p2 - p1); // Text zurückgeben
 }
 }
 
 
 Text* Text::getTeilText(int p) const // gibt den Text von p bis zum Ende zurück
 Text* Text::getTeilText(int p) const // gibt den Text von p bis zum Ende zurück
@@ -1125,9 +1224,8 @@ Text* Text::getTeilText(int p) const // gibt den Text von p bis zum Ende zur
 int Text::hashCode() const
 int Text::hashCode() const
 {
 {
     int result = 0;
     int result = 0;
-    int len = getLength();
-    for (int i = 0; i < len; i++)
-        result += (int)pow(txt[i] * 31, len - 1 - i);
+    for (int i = 0; i < length; i++)
+        result += (int)pow(txt[i] * 31, length - 1 - i);
     return result;
     return result;
 }
 }
 
 
@@ -1209,14 +1307,14 @@ Text::operator const char*() const
 
 
 Text::operator int() const
 Text::operator int() const
 {
 {
-    if (getLength() > 2 && txt[0] == '0' && txt[1] == 'x')
+    if (length > 2 && txt[0] == '0' && txt[1] == 'x')
         return TextZuInt((txt + 2), 16);
         return TextZuInt((txt + 2), 16);
     return TextZuInt(txt, 10);
     return TextZuInt(txt, 10);
 }
 }
 
 
 Text::operator __int64() const
 Text::operator __int64() const
 {
 {
-    if (getLength() > 2 && txt[0] == '0' && txt[1] == 'x')
+    if (length > 2 && txt[0] == '0' && txt[1] == 'x')
         return TextZuInt64((txt + 2), 16);
         return TextZuInt64((txt + 2), 16);
     return TextZuInt64(txt, 10);
     return TextZuInt64(txt, 10);
 }
 }
@@ -1233,29 +1331,27 @@ Text::operator float() const
 
 
 bool Text::operator>(Text& t) const
 bool Text::operator>(Text& t) const
 {
 {
-    int len1 = getLength();
     int len2 = t.getLength();
     int len2 = t.getLength();
     const char* txt2 = t;
     const char* txt2 = t;
-    for (int i = 0; i < len1 && i < len2; ++i)
+    for (int i = 0; i < length && i < len2; ++i)
     {
     {
         if (txt[i] > txt2[i]) return 1;
         if (txt[i] > txt2[i]) return 1;
         if (txt[i] < txt2[i]) return 0;
         if (txt[i] < txt2[i]) return 0;
     }
     }
-    if (len1 > len2) return 1;
+    if (length > len2) return 1;
     return 0;
     return 0;
 }
 }
 
 
 bool Text::operator<(Text& t) const
 bool Text::operator<(Text& t) const
 {
 {
-    int len1 = getLength();
     int len2 = t.getLength();
     int len2 = t.getLength();
     const char* txt2 = t;
     const char* txt2 = t;
-    for (int i = 0; i < len1 && i < len2; ++i)
+    for (int i = 0; i < length && i < len2; ++i)
     {
     {
         if (txt[i] < txt2[i]) return 1;
         if (txt[i] < txt2[i]) return 1;
         if (txt[i] > txt2[i]) return 0;
         if (txt[i] > txt2[i]) return 0;
     }
     }
-    if (len1 < len2) return 1;
+    if (length < len2) return 1;
     return 0;
     return 0;
 }
 }
 
 

+ 41 - 1
Text.h

@@ -11,6 +11,12 @@ namespace Framework
 {
 {
     class Text; //! aus dieser Datei
     class Text; //! aus dieser Datei
 
 
+    namespace Regex
+    {
+        class Result;
+        class RegexConfig;
+    } // namespace Regex
+
     class DynamicBuffer : public std::stringbuf
     class DynamicBuffer : public std::stringbuf
     {
     {
     private:
     private:
@@ -40,10 +46,13 @@ namespace Framework
     {
     {
     private:
     private:
         char* txt;
         char* txt;
+        int length;
         char suchGBeg;
         char suchGBeg;
         char suchGEnd;
         char suchGEnd;
         int precision;
         int precision;
-        DynamicBuffer stringWriter;
+        DynamicBuffer* stringWriter;
+
+        DLLEXPORT Text(char* txt, int l);
 
 
     public:
     public:
         //! Erstellt ein neues Text Objekt mit dem Wert ""
         //! Erstellt ein neues Text Objekt mit dem Wert ""
@@ -65,6 +74,11 @@ namespace Framework
         DLLEXPORT Text(float num);
         DLLEXPORT Text(float num);
         //! Löscht den Text
         //! Löscht den Text
         DLLEXPORT ~Text();
         DLLEXPORT ~Text();
+
+    private:
+        DLLEXPORT void setTextZ(char* t, int l);
+
+    public:
         //! Wandelt alle buchstaben in großbuchstaben um
         //! Wandelt alle buchstaben in großbuchstaben um
         DLLEXPORT void toUpperCase();
         DLLEXPORT void toUpperCase();
         //! Wandelt alle buchstaben in kleinbuchstaben um
         //! Wandelt alle buchstaben in kleinbuchstaben um
@@ -142,6 +156,22 @@ namespace Framework
         //! eingefügt werden soll \param t Der Text, dessen Kopie an der Stelle
         //! eingefügt werden soll \param t Der Text, dessen Kopie an der Stelle
         //! eingefügt werden soll
         //! eingefügt werden soll
         DLLEXPORT void insert(int p, Text* t);
         DLLEXPORT void insert(int p, Text* t);
+        // replaces all regular expression occurences by a static string
+        // \param regex The regular expression to search for
+        // \param replacement The string to replace the occurences with
+        // \param config The configuration for the regular expression
+        DLLEXPORT void regexReplace(const char* regex,
+            const char* replacement,
+            Regex::RegexConfig* config = 0);
+        // replaces all regular expression occurences with a result of a
+        // specified replacement function string \param regex The regular
+        // expression to search for \param replacementFunction a function that
+        // is called with the result of the regular expression and should return
+        // the replacement string \param config The configuration for the
+        // regular expression
+        DLLEXPORT void regexReplace(const char* regex,
+            std::function<Text(Regex::Result&)> replacementFunction,
+            Regex::RegexConfig* config = 0);
         //! Ersetzt einen bestimmten Textabschnitt mit einer anderen
         //! Ersetzt einen bestimmten Textabschnitt mit einer anderen
         //! Zeichenkette
         //! Zeichenkette
         //!  p1: Die Startposition des zu ersetzenden Textabschnittes
         //!  p1: Die Startposition des zu ersetzenden Textabschnittes
@@ -288,6 +318,11 @@ namespace Framework
         //! \param t Die Zeichenkette, nach der gesucht werden soll
         //! \param t Die Zeichenkette, nach der gesucht werden soll
         //! \return (true), wenn die Zeichenkette vorkommt. (false) sonnst
         //! \return (true), wenn die Zeichenkette vorkommt. (false) sonnst
         DLLEXPORT bool hat(const char* t) const;
         DLLEXPORT bool hat(const char* t) const;
+        //! Überprüft, ob im Text eine bestimmte Zeichenkette vorkommt
+        //! \param searchStartIndex Der index ab dem gesucht werden soll
+        //! \param t Die Zeichenkette, nach der gesucht werden soll
+        //! \return (true), wenn die Zeichenkette vorkommt. (false) sonnst
+        DLLEXPORT bool hat(int searchStartIndex, const char* t) const;
         //! Überprüft, ob im Text der Inhalt eines anderen Textes vorkommt
         //! Überprüft, ob im Text der Inhalt eines anderen Textes vorkommt
         //! \param t Der Text, nach dessen Inhalt gesucht werden soll
         //! \param t Der Text, nach dessen Inhalt gesucht werden soll
         //! \return (true), wenn der Inhalt des Textes vorkommt. (false) sonnst
         //! \return (true), wenn der Inhalt des Textes vorkommt. (false) sonnst
@@ -336,6 +371,11 @@ namespace Framework
         //! \param t Die Zeichenkette, die gefunden werden soll
         //! \param t Die Zeichenkette, die gefunden werden soll
         //! \return Die Position des ersten Vorkommens der Zeichenkette
         //! \return Die Position des ersten Vorkommens der Zeichenkette
         DLLEXPORT int positionVon(const char* t) const;
         DLLEXPORT int positionVon(const char* t) const;
+        //! Gibt die erste Position einer bestimmten Zeichenkette im Text zurück
+        //! \param searchStart Index ab dem gesucht werden soll
+        //! \param t Die Zeichenkette, die gefunden werden soll
+        //! \return Die Position des ersten Vorkommens der Zeichenkette
+        DLLEXPORT int positionVon(int searchStart, const char* t) const;
         //! Gibt die erste Position eines Textinhaltes im Text zurück
         //! Gibt die erste Position eines Textinhaltes im Text zurück
         //! \param t Der Text, dessen Inhalt gefunden werden soll
         //! \param t Der Text, dessen Inhalt gefunden werden soll
         //! \return Die Position des ersten Vorkommens des Textinhaltes
         //! \return Die Position des ersten Vorkommens des Textinhaltes