2 次代码提交 14ac2dfc35 ... dcc59f9131

作者 SHA1 备注 提交日期
  Kolja Strohm dcc59f9131 add CriticalLock that unlocks automatically if the current scope is left 11 月之前
  Kolja Strohm 2e9d6d994a improve performance of text operations 11 月之前
共有 4 个文件被更改,包括 354 次插入194 次删除
  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()
 {
-    volatile thread_local static  pthread_t t = GetCurrentThread();
+    volatile thread_local static pthread_t t = GetCurrentThread();
     return (pthread_t)t;
 }
 
@@ -151,4 +151,15 @@ void Synchronizer::notifyAll()
 int Synchronizer::getNumberOfWaitingThreads() const
 {
     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;
     };
 
+    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
     {
     private:

+ 287 - 191
Text.cpp

@@ -7,6 +7,7 @@
 #ifndef WIN32
 #    include <string.h>
 #endif
+#include "Regex.h"
 
 using namespace Framework;
 
@@ -36,38 +37,58 @@ FlushingOStream::~FlushingOStream()
     onDestroy();
 }
 
+Text::Text(char* t, int l)
+    : Text()
+{
+    setTextZ(t, l); // Text setzen
+}
+
 // inhalt der Text Klasse aus Text.h
 // Konstruktor
 Text::Text()
     : ReferenceCounter(),
       txt(0),
+      length(0),
       suchGBeg(0),
       suchGEnd(0),
       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("");
 }
 
 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()
+    : ReferenceCounter(),
+      txt(0),
+      length(0),
+      suchGBeg(0),
+      suchGEnd(0),
+      precision(-1),
+      stringWriter(0)
 {
     setText(t); // Text setzen
 }
 
 Text::Text(int zahl)
-    : Text()
+    : ReferenceCounter(),
+      txt(0),
+      length(0),
+      suchGBeg(0),
+      suchGEnd(0),
+      precision(-1),
+      stringWriter(0)
 {
     *this = zahl;
 }
@@ -91,14 +112,21 @@ Text::Text(float num)
 // Destruktor
 Text::~Text()
 {
+    if (stringWriter) delete stringWriter;
     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()
 {
     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);
         switch (txt[i])
@@ -119,8 +147,7 @@ void Text::toUpperCase()
 void Text::toLowerCase()
 {
     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);
         switch (txt[i])
@@ -149,22 +176,23 @@ void Text::setSuchGrenzen(
 
 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[l] = '\0'; // Textende Festlegen
+    txt[length] = '\0'; // Textende Festlegen
 }
 
 // unconstant
 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[l] = '\0'; // Textende Festlegen
+    txt[length] = '\0'; // Textende Festlegen
 }
 
 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
 {
-    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];
     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
 {
-    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];
     std::stringstream stream;
     stream << std::setfill('0') << std::setw((int)sizeof(int) * 2) << std::hex
            << num;
     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
 {
-    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];
     std::stringstream stream;
     stream << std::setfill('0') << std::setw((int)sizeof(__int64) * 2)
            << std::hex << num;
     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];
     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)
@@ -275,7 +295,20 @@ void Text::append(double num)
     std::stringstream ss;
     if (precision >= 0) ss.precision(precision);
     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)
@@ -283,48 +316,66 @@ void Text::append(float num)
     std::stringstream ss;
     if (precision >= 0) ss.precision(precision);
     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
 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
 {
-    if (p > getLength() || p < 0) // Auf unsinnige übergabe prüfen
+    if (p > length || p < 0) // Auf unsinnige übergabe prüfen
         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[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[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
 {
-    if (p > getLength() || p < 0
+    if (p > length || p < 0
         || textLength(t) <= 0) // Auf unsinnige übergabe prüfen
         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];
     for (int i = 0; i < tl; ++i) // Text einfügen
         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[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)
@@ -334,6 +385,73 @@ void Text::insert(int p, Text* t)
     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(
     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;
     if (!hat(c1)) // prüfen ob c1 vorhanden
         return;
-    int l = getLength(); // Text Länge
     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;
         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
 {
-    int txl = getLength();         // Text Länge
     int t1l = (int)textLength(t1); // Länge der Übergaben
     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;
     if (!hat(t1)) // prüfen ob t1 vorhanden
         return;
     int anz = anzahlVon(t1); // Anzahl von t1 im Text
     int* begin = new int[anz];
     int* end = new int[anz];
+    int searchStart = 0;
     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;
+        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 last = 0;             // Füllposition von txt
     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
-    setText(res);         // Text setzen
+    setTextZ(res, resl);  // Text setzen
     delete[] begin;       // Speicher freigeben
     delete[] end;
-    delete[] res;
 }
 
 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(
     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;
     if (!hat(t1)) // prüfen ob t1 vorhanden
         return;
@@ -504,23 +620,20 @@ void Text::fillText(
     for (int i = 0; i < len; ++i)
         res[i] = c;
     res[len] = '\0';
-    setText(res);
-    delete[] res;
+    setTextZ(res, len);
 }
 
 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;
-    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];
-    for (int i = p + 1; i < l; ++i)
+    for (int i = p + 1; i < length; ++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 )
@@ -532,31 +645,28 @@ void Text::remove(int p1, int p2) // l
         p1 = p2;
         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;
-    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
     for (int i = 0; i < p1; ++i)             // Text füllen
         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[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
 {
     if (!hat(c)) // prüfen ob c vorhanden
         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 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;
         if (txt[i] == c && !suchGCount)
@@ -573,16 +683,14 @@ void Text::remove(char c) // l
                 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
 {
     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;
     if (!hat(t)) // prüfen ob Text ein t enthält
         return;
@@ -590,10 +698,10 @@ void Text::remove(const char* t) // l
     int* begin = new int[anz];
     for (int i = 0; i < anz; ++i) // begin aller t-s finden
         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
     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
         {
@@ -603,10 +711,9 @@ void Text::remove(const char* t) // l
         else
             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[] res; // Speicher freigeben
 }
 
 void Text::remove(Text* t)
@@ -625,16 +732,14 @@ void Text::remove(int index, char c)
         return;
     int pos = positionVon(c, index); // Position vom i-ten c
     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];
-    for (int i = pos + 1; i < l; ++i)
+    for (int i = pos + 1; i < length; ++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
@@ -647,16 +752,14 @@ void Text::remove(int index, const char* t) // l
         return;
     int pos = positionVon(t, index); // Position vom i-ten c
     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];
-    for (int i = pos + tl; i < l; ++i)
+    for (int i = pos + tl; i < length; ++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)
@@ -706,8 +809,7 @@ void Text::setPrecision(
 // constant
 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
@@ -749,12 +851,11 @@ int Text::getOKick(int pos) const
 
 int Text::getRKick(int pos) const
 {
-    int tl = getLength();
     if (txt[pos] == ' ')
     {
         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)
             ;
         return pos + ret;
@@ -762,8 +863,8 @@ int Text::getRKick(int pos) const
     else
     {
         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)
             ;
         return pos + ret;
@@ -772,18 +873,18 @@ int Text::getRKick(int pos) const
 
 int Text::getUKick(int pos) const
 {
-    if (!hat('\n')) return getLength();
+    if (!hat('\n')) return length;
     int lpos = 0;
     while (pos - lpos > 0 && txt[pos - lpos - 1] != '\n')
         ++lpos;
     int llen = 1;
-    while (pos + llen - 1 < getLength() && txt[pos + llen - 1] != '\n')
+    while (pos + llen - 1 < length && txt[pos + llen - 1] != '\n')
         ++llen;
     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;
-    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;
     return pos + llen + lpos;
 }
@@ -798,13 +899,18 @@ bool Text::hat(Text* t) const // enth
 }
 
 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 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;
     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)
         {
@@ -845,9 +951,8 @@ bool Text::hatAt(int pos, Text* t) const
 //  pos: die position an der die zeichenkette im string beginnen soll
 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;
     bool b = 1;
     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
 {
-    int l = getLength(); // Text Länge
     bool ret = 0;
     int suchGCount = 0;
-    for (int i = 0; i < l; ++i) // suchen
+    for (int i = 0; i < length; ++i) // suchen
     {
         bool b = suchGCount != 0;
         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
 {
-    int txl = getLength();       // Text Länge
     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;
-    if (txl == -1) return 1;
+    if (length == -1) return 1;
     bool ret = true;
     for (int i = 0; i < tl; ++i) // prüfen
         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 ret = 0;
-    int l = getLength(); // Text Länge
     int suchGCount = 0;
-    for (int i = 0; i < l; ++i) // suchen
+    for (int i = 0; i < length; ++i) // suchen
     {
         bool b = suchGCount != 0;
         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 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;
     int ret = 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;
         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 l = getLength(); // Text Länge
     int suchGCount = 0;
-    for (int i = 0; i < l; ++i) // suchen
+    for (int i = 0; i < length; ++i) // suchen
     {
         bool b = suchGCount != 0;
         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(
     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;
     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;
         if (!suchGCount)
@@ -1014,10 +1118,9 @@ int Text::positionVon(Text* t) const
 int Text::positionVon(
     char c, int index) const // gibt die Position des i-ten c zurück
 {
-    int l = getLength(); // Text Länge
     int ii = 0;
     int suchGCount = 0;
-    for (int i = 0; i < l; ++i) // suchen
+    for (int i = 0; i < length; ++i) // suchen
     {
         bool b = suchGCount != 0;
         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
 {
     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;
     int i2 = 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;
         if (!suchGCount)
@@ -1102,8 +1204,7 @@ Text* Text::getTeilText(
         p1 = p2;
         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("");
     char* cp = new char[(__int64)p2 - p1 + 1]; // neuen Text erstellen
     for (int i = p1; i < p2; ++i)              // Text befüllen
@@ -1111,9 +1212,7 @@ Text* Text::getTeilText(
         cp[i - p1] = txt[i];
     }
     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
@@ -1125,9 +1224,8 @@ Text* Text::getTeilText(int p) const // gibt den Text von p bis zum Ende zur
 int Text::hashCode() const
 {
     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;
 }
 
@@ -1209,14 +1307,14 @@ Text::operator const char*() 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, 10);
 }
 
 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, 10);
 }
@@ -1233,29 +1331,27 @@ Text::operator float() const
 
 bool Text::operator>(Text& t) const
 {
-    int len1 = getLength();
     int len2 = t.getLength();
     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 0;
     }
-    if (len1 > len2) return 1;
+    if (length > len2) return 1;
     return 0;
 }
 
 bool Text::operator<(Text& t) const
 {
-    int len1 = getLength();
     int len2 = t.getLength();
     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 0;
     }
-    if (len1 < len2) return 1;
+    if (length < len2) return 1;
     return 0;
 }
 

+ 41 - 1
Text.h

@@ -11,6 +11,12 @@ namespace Framework
 {
     class Text; //! aus dieser Datei
 
+    namespace Regex
+    {
+        class Result;
+        class RegexConfig;
+    } // namespace Regex
+
     class DynamicBuffer : public std::stringbuf
     {
     private:
@@ -40,10 +46,13 @@ namespace Framework
     {
     private:
         char* txt;
+        int length;
         char suchGBeg;
         char suchGEnd;
         int precision;
-        DynamicBuffer stringWriter;
+        DynamicBuffer* stringWriter;
+
+        DLLEXPORT Text(char* txt, int l);
 
     public:
         //! Erstellt ein neues Text Objekt mit dem Wert ""
@@ -65,6 +74,11 @@ namespace Framework
         DLLEXPORT Text(float num);
         //! Löscht den Text
         DLLEXPORT ~Text();
+
+    private:
+        DLLEXPORT void setTextZ(char* t, int l);
+
+    public:
         //! Wandelt alle buchstaben in großbuchstaben um
         DLLEXPORT void toUpperCase();
         //! 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
         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
         //! Zeichenkette
         //!  p1: Die Startposition des zu ersetzenden Textabschnittes
@@ -288,6 +318,11 @@ namespace Framework
         //! \param t Die Zeichenkette, nach der gesucht werden soll
         //! \return (true), wenn die Zeichenkette vorkommt. (false) sonnst
         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
         //! \param t Der Text, nach dessen Inhalt gesucht werden soll
         //! \return (true), wenn der Inhalt des Textes vorkommt. (false) sonnst
@@ -336,6 +371,11 @@ namespace Framework
         //! \param t Die Zeichenkette, die gefunden werden soll
         //! \return Die Position des ersten Vorkommens der Zeichenkette
         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
         //! \param t Der Text, dessen Inhalt gefunden werden soll
         //! \return Die Position des ersten Vorkommens des Textinhaltes