//---Include--- #include "Text.h" #include #include #include #ifndef WIN32 # include #endif #include "Regex.h" using namespace Framework; DynamicBuffer::DynamicBuffer(std::function onAppend) : std::stringbuf(), onAppend(onAppend) {} int DynamicBuffer::sync() { return onAppend(*this); } FlushingOStream::FlushingOStream( DynamicBuffer* buffer, std::function onDestroy) : std::ostream(buffer), onDestroy(onDestroy) {} FlushingOStream::FlushingOStream(const Framework::FlushingOStream& stream) : std::ostream(stream.rdbuf()) {} FlushingOStream::~FlushingOStream() { flush(); onDestroy(); } Text::Text(char* t, int l) : ReferenceCounter(), txt(0), length(0), suchGBeg(0), suchGEnd(0), precision(-1), stringWriter(0) { length = l; txt = t; // create new text } // Content of the Text class from Text.h // Constructor Text::Text() : ReferenceCounter(), txt(0), length(0), suchGBeg(0), suchGEnd(0), precision(-1), stringWriter(0) { setText(""); } Text::Text(const Text& txt) : ReferenceCounter(), txt(0), length(0), suchGBeg(0), suchGEnd(0), precision(-1), stringWriter(0) { setText(txt, txt.length); } Text::Text(const char* t) : ReferenceCounter(), txt(0), length(0), suchGBeg(0), suchGEnd(0), precision(-1), stringWriter(0) { setText(t); // set text } Framework::Text::Text(const char* txt, int offset, int length) : ReferenceCounter(), txt(0), length(0), suchGBeg(0), suchGEnd(0), precision(-1), stringWriter(0) { this->length = length; this->txt = new char[length + 1]; memcpy(this->txt, txt + offset, length); this->txt[length] = 0; } Text::Text(int zahl) : ReferenceCounter(), txt(0), length(0), suchGBeg(0), suchGEnd(0), precision(-1), stringWriter(0) { *this = zahl; } // Creates a new Text object with a number as text // num: The number that should be in the text Text::Text(double num) : Text() { *this = num; } // Creates a new Text object with a number as text // num: The number that should be in the text Text::Text(float num) : Text() { *this = num; } // Destructor Text::~Text() { if (stringWriter) delete stringWriter; delete[] txt; } void Framework::Text::setTextZ(char* t, int l) { delete[] txt; // delete old text length = l; txt = t; // create new text } void Text::toUpperCase() { if (!txt) return; for (int i = 0; i < length; i++) { if (txt[i] >= 'a' && txt[i] <= 'z') txt[i] = (char)(txt[i] - 32); switch (txt[i]) { case SpecialCharacters::SMALL_UE: txt[i] = SpecialCharacters::BIG_UE; break; case SpecialCharacters::SMALL_OE: txt[i] = SpecialCharacters::BIG_OE; break; case SpecialCharacters::SMALL_AE: txt[i] = SpecialCharacters::BIG_AE; break; } } } void Text::toLowerCase() { if (!txt) return; for (int i = 0; i < length; i++) { if (txt[i] >= 'A' && txt[i] <= 'Z') txt[i] = (char)(txt[i] + 32); switch (txt[i]) { case SpecialCharacters::BIG_UE: txt[i] = SpecialCharacters::SMALL_UE; break; case SpecialCharacters::BIG_OE: txt[i] = SpecialCharacters::SMALL_OE; break; case SpecialCharacters::BIG_AE: txt[i] = SpecialCharacters::SMALL_AE; break; } } } // non-constant void Text::setSuchGrenzen( char gBeg, char gEnd) // for every search function, does not search between // the characters gBeg and gEnd { suchGBeg = gBeg; suchGEnd = gEnd; } void Text::setText(const char* t) // replaces the text { setText(t, textLength(t)); // set text } // non-constant void Text::setText(const char* t, int l) // replaces the text { delete[] txt; // delete old text length = l; txt = new char[(__int64)length + 1]; // create new text for (int i = 0; i < length; ++i) // fill text txt[i] = t[i]; txt[length] = '\0'; // set text end } void Text::setText(const Text& t) { setText(t, t.getLength()); // set text } void Text::append(char c) // appends to the text { append(&c, 1); } void Text::append(const char* t) // appends to the text { int tl = (int)textLength(t); // length of the argument char* res = new char[(__int64)tl + length + 1]; // create new text for (int i = 0; i < length; ++i) // fill with current text res[i] = txt[i]; for (int i = 0; i < tl; ++i) // append argument res[length + i] = t[i]; res[length + tl] = '\0'; // set text end setTextZ(res, length + tl); // set text } void Text::appendHex(char num) // appends the number in hex to the text { char* res = new char[(__int64)length + sizeof(char) * 2 + 1]; for (int i = 0; i < length; ++i) res[i] = txt[i]; std::stringstream stream; stream << std::setfill('0') << std::setw((int)sizeof(char) * 2) << std::hex << (int)num; std::string str = stream.str(); for (int i = length; i < length + sizeof(char) * 2; ++i) res[i] = str.c_str()[i - length]; res[length + sizeof(char) * 2] = 0; setTextZ(res, length + sizeof(char) * 2); } void Framework::Text::appendHex(short num) { char* res = new char[(__int64)length + sizeof(short) * 2 + 1]; for (int i = 0; i < length; ++i) res[i] = txt[i]; std::stringstream stream; stream << std::setfill('0') << std::setw((int)sizeof(short) * 2) << std::hex << num; std::string str = stream.str(); for (int i = length; i < length + sizeof(short) * 2; ++i) res[i] = str.c_str()[i - length]; res[length + sizeof(short) * 2] = 0; setTextZ(res, length + sizeof(short) * 2); } void Text::appendHex(int num) // appends the number in hex to the text { char* res = new char[(__int64)length + sizeof(int) * 2 + 1]; 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 = length; i < length + sizeof(int) * 2; ++i) res[i] = str.c_str()[i - length]; res[length + sizeof(int) * 2] = 0; setTextZ(res, length + sizeof(int) * 2); } void Text::appendHex(__int64 num) // appends the number in hex to the text { char* res = new char[(__int64)length + sizeof(__int64) * 2 + 1]; 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 = length; i < length + sizeof(__int64) * 2; ++i) res[i] = str.c_str()[i - length]; res[length + sizeof(__int64) * 2] = 0; setTextZ(res, length + sizeof(__int64) * 2); } void Text::append(const char* t, int l) // appends to the text { // length of the text char* res = new char[(__int64)l + length + 1]; // create new text for (int i = 0; i < length; ++i) // fill with current text res[i] = txt[i]; for (int i = 0; i < l; ++i) // append argument res[length + i] = t[i]; res[length + l] = '\0'; // set text end setTextZ(res, length + l); // set text } void Text::append(const Text& t) { if (t.getLength() > 0) // check for invalid argument append(t, t.getLength()); // append text } void Text::append(int num) { std::stringstream ss; ss << num; std::string string = ss.str(); append(string.c_str(), (int)string.length()); } // Appends a number to the end of the text // num: The number to convert to text and append at the end void Text::append(__int64 num) { std::stringstream ss; ss << num; std::string string = ss.str(); append(string.c_str(), (int)string.length()); } void Text::append(unsigned int num) { std::stringstream ss; ss << num; std::string string = ss.str(); append(string.c_str(), (int)string.length()); } void Text::append(double num) { std::stringstream ss; if (precision >= 0) ss.precision(precision); ss << std::fixed << num; std::string string = ss.str(); const char* str = string.c_str(); int len = (int)string.length(); 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) { std::stringstream ss; if (precision >= 0) ss.precision(precision); ss << std::fixed << num; std::string string = ss.str(); const char* str = string.c_str(); int len = (int)string.length(); for (int i = len - 1; i > 0; i--) { if (str[i] == '0') len--; else { if (str[i] == '.') len--; break; } } append(str, len); } //! Returns an ostream that appends all output to this text FlushingOStream Text::append() { if (!stringWriter) { stringWriter = new DynamicBuffer([this](std::stringbuf& buf) { std::string str = buf.str(); this->append(str.c_str(), (int)str.length()); buf.str(""); return 0; }); } return FlushingOStream(stringWriter); } void Text::insert(int p, char c) // inserts at position p { if (p > length || p < 0) // check for invalid argument return; char* res = new char[(__int64)length + 2]; // create new text for (int i = 0; i < p; ++i) // fill text res[i] = txt[i]; res[p] = c; for (int i = p; i < length; ++i) // fill text res[i + 1] = txt[i]; res[length + 1] = '\0'; // set text end setTextZ(res, length + 1); // set text } void Text::insert(int p, const char* t) // inserts at position p { insert(p, t, textLength(t)); // insert text } void Framework::Text::insert(int p, const char* t, int len) { if (p > length || p < 0 || len <= 0) // check for invalid argument return; // length of argument char* res = new char[(__int64)len + length + 1]; // create new text for (int i = 0; i < p; ++i) // fill text res[i] = txt[i]; for (int i = 0; i < len; ++i) // insert text res[i + p] = t[i]; for (int i = p; i < length; ++i) // fill text res[i + len] = txt[i]; res[len + length] = '\0'; // set text end setTextZ(res, length + len); // set text } void Text::insert(int p, const Text& t) { insert(p, t, t.getLength()); // insert text } 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 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) // replaces text from p1 to p2 { ersetzen(p1, p2, t, textLength(t)); // replace text } void Framework::Text::ersetzen(int p1, int p2, const char* t, int len) { if (p1 > p2) { int x = p1; // swap p1 and p2 p1 = p2; p2 = x; } remove(p1, p2); // delete text section from p1 to p2 if (len > 0) { insert(p1, t, len); // insert argument at p1 } } void Text::ersetzen(int p1, int p2, const Text& t) { ersetzen(p1, p2, t, t.getLength()); // replace text } void Text::ersetzen(char c1, char c2) // replaces every c1 with c2 { if (c1 == '\0' || c2 == '\0') // check for invalid argument return; if (!hat(c1)) // check if c1 exists return; int suchGCount = 0; if (suchGBeg && suchGEnd) { for (int i = 0; i < length; ++i) // search text { bool b = suchGCount != 0; if (txt[i] == c1 && !suchGCount) txt[i] = c2; // replace text if (txt[i] == suchGBeg) ++suchGCount; if (txt[i] == suchGEnd) --suchGCount; if (txt[i] == c1 && !suchGCount && b) txt[i] = c2; // replace text } } else { for (int i = 0; i < length; ++i) // search text { if (txt[i] == c1) txt[i] = c2; // replace text } } } void Text::ersetzen(const char* t1, const char* t2) // replaces every t1 with t2 { ersetzen(t1, textLength(t1), t2, textLength(t2)); // replace text } void Framework::Text::ersetzen( const char* t1, int len1, const char* t2, int len2) { if (len1 > length || len1 <= 0) // check for invalid argument return; if (!hat(t1, len1)) // check if t1 exists return; int anz = anzahlVon(t1, len1); // count of t1 in text int* begin = new int[anz]; int* end = new int[anz]; int searchStart = 0; for (int i = 0; i < anz; ++i) // save positions of t1 { begin[i] = positionVon(searchStart, t1, len1); end[i] = begin[i] + len1; searchStart = end[i]; } int resl = (length - (anz * len1)) + (anz * len2) + 1; // length of result char* res = new char[resl]; // create new text int rep = 0; // stores which t1 we are at int last = 0; // fill position in txt int neu = 0; // fill position in res for (; neu < resl; ++neu) // fill text { if (rep < anz && last == begin[rep]) // replace text { last = end[rep]; ++rep; for (int ii = 0; ii < len2; ++ii) { if (neu >= resl) break; res[neu] = t2[ii]; ++neu; } if (neu >= resl) break; --neu; } else // copy text { res[neu] = txt[last]; ++last; } } res[resl - 1] = '\0'; // set text end setTextZ(res, resl); // set text delete[] begin; // free memory delete[] end; } void Text::ersetzen(const Text& t1, const char* t2) { ersetzen(t1, t1.getLength(), t2, textLength(t2)); // replace text } void Text::ersetzen(const char* t1, const Text& t2) { ersetzen(t1, textLength(t1), t2, t2.getLength()); // replace text } void Text::ersetzen(const Text& t1, const Text& t2) { ersetzen(t1, t1.getLength(), t2, t2.getLength()); // replace text } void Text::ersetzen(int index, char c1, char c2) // replaces the i-th c1 with c2 { if (c1 == '\0' || c2 == '\0' || index < 0) // check for invalid argument return; if (!hat(c1)) // check if c1 exists return; int anz = anzahlVon(c1); if (index >= anz) // check if an i-th c1 exists return; txt[positionVon(c1, index)] = c2; } void Text::ersetzen(int index, const char* t1, const char* t2) // replaces the i-th t1 with t2 { ersetzen(index, t1, textLength(t1), t2, textLength(t2)); // replace text } void Framework::Text::ersetzen( int index, const char* t1, int len1, const char* t2, int len2) { if (len1 >= length || len1 <= 0 || index < 0) // check for invalid argument return; if (!hat(t1)) // check if t1 exists return; int anz = anzahlVon(t1, len1); // count of t1 in text if (index >= anz) // check if an i-th t1 exists return; int begin = positionVon(index, len1, t1); int end = begin + len1; ersetzen(begin, end, t2, len2); // replace } void Text::ersetzen(int i, const Text& t1, const char* t2) { ersetzen(i, t1, t1.getLength(), t2, textLength(t2)); // replace } void Text::ersetzen(int i, const char* t1, const Text& t2) { ersetzen(i, t1, textLength(t1), t2, t2.getLength()); // replace } void Text::ersetzen(int i, const Text& t1, const Text& t2) { ersetzen(i, t1, t1.getLength(), t2, t2.getLength()); // replace } void Text::fillText( char c, int len) // sets the text to as many c as len is large { char* res = new char[(__int64)len + 1]; for (int i = 0; i < len; ++i) res[i] = c; res[len] = '\0'; setTextZ(res, len); } void Text::remove(int p) // deletes p { if (p < 0 || p >= length) // check for invalid argument return; char* res = new char[length]; // create new text for (int i = 0; i < p && i < length; ++i) // fill text res[i] = txt[i]; for (int i = p + 1; i < length; ++i) res[i - 1] = txt[i]; res[length - 1] = 0; setTextZ(res, length - 1); // set text } void Text::remove(int p1, int p2) // deletes from p1 to p2 (p2 is kept) { if (p1 == p2) return; if (p1 > p2) // swap p1 and p2 { int x = p1; p1 = p2; p2 = x; } if (p1 < 0) // check for invalid argument p1 = 0; if (p2 > length) p2 = length; int resl = length - (p2 - p1); // length of result char* res = new char[(__int64)resl + 1]; // create new text memcpy(res, txt, p1); memcpy(res + p1, txt + p2, length - p2); res[resl] = '\0'; // set text end setTextZ(res, resl); // set text } void Text::remove(char c) // deletes every c { if (!hat(c)) // check if c exists return; int anz = anzahlVon(c); // count of c char* res = new char[(__int64)length - anz + 1]; // create new text int anz2 = 0; int suchGCount = 0; for (int i = 0; i < length; ++i) // fill text { bool b = suchGCount != 0; if (txt[i] == c && !suchGCount) ++anz2; else res[i - anz2] = txt[i]; if (txt[i] == suchGBeg) ++suchGCount; if (txt[i] == suchGEnd) --suchGCount; if (b) { if (txt[i] == c && !suchGCount) ++anz2; else res[i - anz2] = txt[i]; } } res[length - anz] = '\0'; // set text end setTextZ(res, length - anz); // set text } void Text::remove(const char* t) // deletes every t { remove(t, textLength(t)); // delete text } void Framework::Text::remove(const char* t, int len) { if (len <= 0 || len > length) // check for invalid argument return; if (!hat(t, len)) // check if text contains t return; int anz = anzahlVon(t, len); // count of t int* begin = new int[anz]; for (int i = 0; i < anz; ++i) // find start of all t's begin[i] = positionVon(i, len, t); int resl = length - (anz * len); // length of result char* res = new char[(__int64)resl + 1]; // create new text int del = 0; for (int i = 0; i < length; ++i) // fill text { if (del < anz && i == begin[del]) // skip text { i += len - 1; ++del; } else res[i - (del * len)] = txt[i]; // fill text } res[resl] = '\0'; // set text end setTextZ(res, resl); // set text delete[] begin; } void Text::remove(const Text& t) { remove(t, t.getLength()); // delete text } void Text::remove(int index, char c) { if (index < 0 || !hat(c)) // check for invalid argument return; int anz = anzahlVon(c); // count of c's if (index >= anz) // check if an i-th c exists return; int pos = positionVon(c, index); // position of the i-th c if (pos < 0) return; if (!length) return; char* res = new char[length]; // create new text for (int i = 0; i < pos && i < length; ++i) // fill text res[i] = txt[i]; for (int i = pos + 1; i < length; ++i) res[i - 1] = txt[i]; res[length - 1] = '\0'; // set text end setTextZ(res, length - 1); // set text } void Text::remove(int index, const char* t) // deletes the i-th t { remove(index, t, textLength(t)); // delete text } void Framework::Text::remove(int index, const char* t, int len) { if (index < 0 || !hat(t, len) || len <= 0) // check for invalid argument return; int anz = anzahlVon(t, len); // count of t's if (index >= anz) // check if an i-th t exists return; int pos = positionVon(index, len, t); // position of the i-th t if (pos < 0) return; if (!length) return; char* res = new char[(__int64)length - len + 1]; // create new text for (int i = 0; i < pos && i < length - len + 1; ++i) // fill text res[i] = txt[i]; for (int i = pos + len; i < length; ++i) res[i - len] = txt[i]; res[length - len] = '\0'; // set text end setTextZ(res, length - len); // set text } void Text::remove(int i, const Text& t) { remove(i, t, t.getLength()); // delete text } // Deletes all ' ', '\n', '\r', '\t' until a different character // pos: The position of the first character int Text::removeWhitespaceAfter(int pos) { int removedLength = 0; for (int i = pos; i < length; i++) { if (txt[i] == ' ' || txt[i] == '\n' || txt[i] == '\r' || txt[i] == '\t') removedLength++; else break; } remove(pos, pos + removedLength); return length; } // Deletes all ' ', '\n', '\r', '\t' until a different character // pos: The position of the first character (starts at pos-1) int Text::removeWhitespaceBefore(int pos) { int length = 0; for (int i = pos - 1; i >= 0; i--) { if (txt[i] == ' ' || txt[i] == '\n' || txt[i] == '\r' || txt[i] == '\t') length++; else break; } remove(pos - length, pos); return length; } void Text::setPrecision( int p) // sets the number of decimal places for doubles { precision = p; } // constant int Text::getLength() const // returns the text length { return length; } int Text::getLKick(int pos) const { if (txt[pos - 1] == ' ') { int ret = 1; for (; ret < pos && txt[pos - ret - 1] == ' ' && txt[pos - ret - 1] != '\n'; ++ret) ; return pos - ret; } else { int ret = 1; for (; ret < pos && txt[pos - ret - 1] != ' ' && txt[pos - ret - 1] != '\n'; ++ret) ; return pos - ret; } } int Text::getOKick(int pos) const { if (!hat('\n')) return 0; int lpos = 0; while (pos - lpos - 1 > 0 && txt[pos - lpos - 1] != '\n') ++lpos; int vllen = 1; while (pos - lpos - vllen - 1 >= 0 && txt[pos - lpos - vllen - 1] != '\n') ++vllen; if (vllen > lpos) return pos - vllen; else return pos - lpos - 1; } int Text::getRKick(int pos) const { if (txt[pos] == ' ') { int ret = 1; for (; ret + pos < length && txt[pos + ret] == ' ' && txt[pos + ret] != '\n'; ++ret) ; return pos + ret; } else { int ret = 1; for (; ret + pos < length && txt[pos + ret] != ' ' && txt[pos + ret] != '\n'; ++ret) ; return pos + ret; } } int Text::getUKick(int pos) const { 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 < length && txt[pos + llen - 1] != '\n') ++llen; int vllen = 1; while ( pos + llen + vllen - 1 < length && txt[pos + llen + vllen - 1] != '\n') ++vllen; if (vllen == 1) return pos + llen < length ? pos + llen : length; if (vllen < lpos) return pos + llen + vllen - 1; return pos + llen + lpos; } bool Text::hat(const Text& t) const // does the text contain t { return hat(t, t.getLength()); // check text } bool Text::hat(const char* t) const { return hat(t, textLength(t)); // check text } bool Framework::Text::hat(const char* t, int len) const { return hat(0, t, len); } bool Framework::Text::hat(int searchStartIndex, const char* t) const { return hat(searchStartIndex, t, textLength(t)); // check text } bool Framework::Text::hat(int searchStartIndex, const char* t, int len) const { if (len <= 0 || len > length - searchStartIndex) // check for invalid argument return 0; int suchGCount = 0; for (int i = searchStartIndex; i + len <= length; ++i) // search text { bool searched = 0; if (!suchGCount) { bool b = 1; for (int ii = 0; ii < len; ++ii) // check text b &= txt[i + ii] == t[ii]; if (b) return 1; searched = 1; } if (txt[i] == suchGBeg) ++suchGCount; if (txt[i] == suchGEnd) --suchGCount; if (!suchGCount && !searched) { bool b = 1; for (int ii = 0; ii < len; ++ii) // check text b &= txt[i + ii] == t[ii]; if (b) return 1; } } return 0; } // Checks whether the text contains the content of another text // t: The text whose content to search for // return: (true) if the content is found. (false) otherwise // pos: the position where the string should begin bool Text::hatAt(int pos, const Text& t) const { return hatAt(pos, t, t.getLength()); // check text } // Checks whether the text contains a specific string // t: The string to search for // return: (true) if the string is found. (false) otherwise // pos: the position where the string should begin bool Text::hatAt(int pos, const char* t) const { return hatAt(pos, t, textLength(t)); // check text } bool Framework::Text::hatAt(int pos, const char* t, int len) const { if (len <= 0 || len + pos > length) // check for invalid argument return 0; bool b = 1; for (int i = 0; i < len; ++i) // check text b &= txt[pos + i] == t[i]; return b; } bool Text::hat(char c) const // contains c { bool ret = 0; int suchGCount = 0; for (int i = 0; i < length; ++i) // search { bool b = suchGCount != 0; if (!suchGCount) // check ret |= txt[i] == c; if (txt[i] == suchGBeg) ++suchGCount; if (txt[i] == suchGEnd) --suchGCount; if (!suchGCount && b) // check ret |= txt[i] == c; } return ret; } bool Text::beginnsWith(const char* t) const { return hatAt(0, t); } bool Text::endsWith(const char* t) const { int len = textLength(t); return hatAt(length - len, t, len); } bool Text::istGleich(const char* t) const // checks if the text equals t { return istGleich(t, textLength(t)); // check text } bool Text::istGleich( const char* t, int len) const // checks if the text equals t { if (length != len) // check for invalid argument return 0; if (length == -1) return 1; bool ret = true; for (int i = 0; i < len; ++i) // check ret &= txt[i] == t[i]; return ret; } bool Text::istGleich(const Text& t) const { return istGleich(t, t.getLength()); // check text } const char* Text::getText() const // returns the text { return txt; } int Text::anzahlVon(char c) const // returns the count of c in the text { int ret = 0; int suchGCount = 0; if (suchGBeg && suchGEnd) { for (int i = 0; i < length; ++i) // search { bool b = suchGCount != 0; ret += txt[i] == c && !suchGCount; // count if (txt[i] == suchGBeg) ++suchGCount; if (txt[i] == suchGEnd) --suchGCount; ret += txt[i] == c && !suchGCount && b; // count } } else { for (int i = 0; i < length; ++i) // search { ret += txt[i] == c; // count } } return ret; } int Text::anzahlVon( const char* t) const // returns the count of t in the text { return anzahlVon(t, textLength(t)); // check text } int Framework::Text::anzahlVon(const char* t, int len) const { if (len <= 0 || len > length) // check for invalid argument return 0; int ret = 0; int suchGCount = 0; for (int i = 0; i + len <= length; ++i) // search { bool b = suchGCount != 0; if (!suchGCount) { bool b = 1; for (int ii = 0; ii < len; ++ii) // check b &= txt[i + ii] == t[ii]; if (b) ++ret; // count } if (txt[i] == suchGBeg) ++suchGCount; if (txt[i] == suchGEnd) --suchGCount; if (!suchGCount && b) { bool b = 1; for (int ii = 0; ii < len; ++ii) // check b &= txt[i + ii] == t[ii]; if (b) ++ret; // count } } return ret; } int Text::anzahlVon(const Text& t) const { return anzahlVon(t, t.getLength()); // check text } int Text::positionVon(char c) const // returns the position of the first c { int suchGCount = 0; for (int i = 0; i < length; ++i) // search { bool b = suchGCount != 0; if (txt[i] == c && !suchGCount) // check return i; if (txt[i] == suchGBeg) ++suchGCount; if (txt[i] == suchGEnd) --suchGCount; if (txt[i] == c && !suchGCount && b) // check return i; } return -1; } int Text::positionVon( const char* t) const // returns the position of the first t { return positionVon(textLength(t), t); } int Framework::Text::positionVon(int len, const char* t) const { return positionVon(0, t, len); } int Text::positionVon(int searchStart, const char* t, int len) const { if (len <= 0 || len > length - searchStart) // check for invalid argument return -1; int suchGCount = 0; for (int i = searchStart; i + len <= length; ++i) // search { bool b = suchGCount != 0; if (!suchGCount) { bool b = 1; for (int ii = 0; ii < len; ++ii) // check b &= txt[i + ii] == t[ii]; if (b) return i; } if (txt[i] == suchGBeg) ++suchGCount; if (txt[i] == suchGEnd) --suchGCount; if (!suchGCount && b) { bool b = 1; for (int ii = 0; ii < len; ++ii) // check b &= txt[i + ii] == t[ii]; if (b) return i; } } return -1; } int Text::positionVon(const Text& t) const { return positionVon(t.getLength(), t); // check text } int Text::positionVon( char c, int index) const // returns the position of the i-th c { int ii = 0; int suchGCount = 0; for (int i = 0; i < length; ++i) // search { bool b = suchGCount != 0; if (txt[i] == c && !suchGCount) // check { if (ii == index) return i; else ++ii; } if (txt[i] == suchGBeg) ++suchGCount; if (txt[i] == suchGEnd) --suchGCount; if (txt[i] == c && !suchGCount && b) // check { if (ii == index) return i; else ++ii; } } return -1; } int Text::positionVon( const char* t, int index) const // returns the position of the i-th t { return positionVon(index, textLength(t), t); // check text } int Framework::Text::positionVon(int index, int len, const char* t) const { if (len <= 0 || len > length) // check for invalid argument return 0; int i2 = 0; int suchGCount = 0; for (int i = 0; i + len <= length; ++i) // search { bool b = suchGCount != 0; if (!suchGCount) { bool b = 1; for (int ii = 0; ii < len; ++ii) // check b &= txt[i + ii] == t[ii]; if (b) { if (i2 == index) return i; else ++i2; } } if (txt[i] == suchGBeg) ++suchGCount; if (txt[i] == suchGEnd) --suchGCount; if (!suchGCount && b) { bool b = 1; for (int ii = 0; ii < len; ++ii) // check b &= txt[i + ii] == t[ii]; if (b) { if (i2 == index) return i; else ++i2; } } } return -1; } int Text::positionVon(const Text& t, int i) const { return positionVon(i, t.getLength(), t); // check text } Text* Text::getTeilText( int p1, int p2) const // returns the text from p1 to p2 { if (p1 > p2) // swap p1 and p2 { int x = p1; p1 = p2; p2 = x; } if (p1 < 0 || p2 > length) // check for invalid argument return new Text(""); char* cp = new char[(__int64)p2 - p1 + 1]; // create new text for (int i = p1; i < p2; ++i) // fill text { cp[i - p1] = txt[i]; } cp[p2 - p1] = '\0'; return new Text(cp, p2 - p1); // return text } Text* Text::getTeilText(int p) const // returns the text from p to the end { return getTeilText(p, getLength()); // return text } // calculates the hash code of the text int Text::hashCode() const { int result = 0; for (int i = 0; i < length; i++) result += (int)pow(txt[i] * 31, length - 1 - i); return result; } // Operators Text& Text::operator+=(const int num) { append(num); return *this; } // Appends a number to the end of the text Text& Text::operator+=(const __int64 num) { append(num); return *this; } Text& Text::operator+=(const double num) { append(num); return *this; } Text& Text::operator+=(const float num) { append(num); return *this; } Text& Text::operator+=(const char* txt) { append(txt); return *this; } Text& Text::operator+=(const Text& txt) { append(txt, txt.getLength()); return *this; } Text& Text::operator=(const int num) { setText("", 0); append(num); return *this; } Text& Text::operator=(const double num) { setText("", 0); append(num); return *this; } Text& Text::operator=(const float num) { setText("", 0); append(num); return *this; } Text& Text::operator=(const char* txt) { setText(txt); return *this; } Text& Text::operator=(const Text& txt) { setText(txt, txt.getLength()); return *this; } Text::operator const char*() const { return txt; } Text::operator int() const { if (length > 2 && txt[0] == '0' && txt[1] == 'x') return TextZuInt((txt + 2), 16); return TextZuInt(txt, 10); } Text::operator __int64() const { if (length > 2 && txt[0] == '0' && txt[1] == 'x') return TextZuInt64((txt + 2), 16); return TextZuInt64(txt, 10); } Text::operator double() const { return TextZuDouble(txt); } Text::operator float() const { return TextZuFloat(txt); } bool Text::operator>(Text& t) const { int len2 = t.getLength(); const char* txt2 = t; for (int i = 0; i < length && i < len2; ++i) { if (txt[i] > txt2[i]) return 1; if (txt[i] < txt2[i]) return 0; } if (length > len2) return 1; return 0; } bool Text::operator<(Text& t) const { int len2 = t.getLength(); const char* txt2 = t; for (int i = 0; i < length && i < len2; ++i) { if (txt[i] < txt2[i]) return 1; if (txt[i] > txt2[i]) return 0; } if (length < len2) return 1; return 0; } // Creates a new text consisting of this and t2 Text Text::operator+(const Text& t2) const { return Text(*this) += t2; } // Creates a new text consisting of this and t2 Text Text::operator+(const char* t2) const { return Text(*this) += t2; } // Creates a new text consisting of this and num Text Text::operator+(const int num) const { return Text(*this) += num; } // Creates a new text consisting of this and num Text Text::operator+(const __int64 num) const { return Text(*this) += num; } // Creates a new text consisting of this and num Text Text::operator+(const double num) const { return Text(*this) += num; } // Creates a new text consisting of this and num Text Text::operator+(const float num) const { return Text(*this) += num; } bool Text::operator==(const Text& right) const { return istGleich(right, right.getLength()); } Text Text::fromArray(char* arr, int len) { return Text(arr, len); } const Text Text::EMPTY = ""; // Content of the TextReader class // Constructor // txt: The text to be read. It is not copied but read directly. TextReader::TextReader(Text* txt) : ReferenceCounter() { this->txt = txt; lPos = 0; } // Destructor TextReader::~TextReader() { txt->release(); } // Sets the position of the byte to be read next // pos: The index of the byte // ende: 1 if the index counts from the end of the text. 0 if from the beginning void TextReader::setLPosition(__int64 pos, bool ende) { int l = txt->getLength(); lPos = ende ? l - pos : pos; if (lPos < 0) lPos = 0; if (lPos > l) lPos = l; } // Reads from the text // bytes: An array to be filled with bytes from the text // len: How many bytes to read from the text void TextReader::lese(char* bytes, int len) { int l = txt->getLength(); len = (int)MIN(l - lPos, len); for (__int64 i = lPos; i < lPos + len; i++) bytes[i - lPos] = txt->getText()[i]; lPos += len; } // Reads the next line of the text // return: The read line as text with line break Text* TextReader::leseZeile() { if (istEnde()) return 0; Text* ret = new Text(""); __int64 len = txt->getLength(); for (char c = 0; c != '\n' && lPos < len;) { lese(&c, 1); if (c) ret->append(&c, 1); } return ret; } // Checks whether the resource has been fully read // return 1 if the resource has been fully read. 0 otherwise bool TextReader::istEnde() const { return lPos >= txt->getLength(); } // Returns the index of the byte from the text that would be read next // return -1 if an error occurred. Otherwise the position of the read pointer __int64 TextReader::getLPosition() const { return lPos; } //! Returns the number of bytes to read __int64 TextReader::getSize() const { return txt->getLength(); } // char* operationen int Framework::stringPositionVonChar(const char* string, char c, int num) // finds the position of the num-th c // in string, -1 if not found { int gef = 0; int p = 0; for (char cc = *string; *string; ++string) { if (cc == c) { if (gef == num) return p; else ++gef; } ++p; } return -1; } int Framework::stringPositionVonString(const char* string, char* suche, int sBegPos) // finds the position of 'suche' in 'string' starting at // position 'sBegPos', -1 if not found { for (int i = 0; i < sBegPos; ++i) { if (!*string) return -1; ++string; } int tl = textLength(suche); // length of the argument int txl = textLength(string); // length of the text if (tl <= 0 || tl > txl) // check for invalid argument return -1; for (int i = 0; i + tl <= txl; ++i) // search { bool b = 1; for (int ii = 0; ii < tl; ++ii) // check if (b) b = string[i + ii] == suche[ii]; if (b) return i + sBegPos; } return -1; } //---Other Functions--- void Framework::TextKopieren( const char* txt) // copies the text to the clipboard { #ifdef WIN32 int laen = textLength(txt) + 1; if (laen == 1) return; HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, laen); if (!hMem) return; memcpy(GlobalLock(hMem), txt, laen); GlobalUnlock(hMem); OpenClipboard(0); EmptyClipboard(); SetClipboardData(CF_TEXT, hMem); CloseClipboard(); #endif } const char* Framework::TextInsert() // returns the text from the clipboard { #ifdef WIN32 if (!OpenClipboard(0)) return ""; HANDLE hClipData = GetClipboardData(CF_TEXT); char* cBuffer = (char*)GlobalLock(hClipData); GlobalUnlock(hClipData); CloseClipboard(); return cBuffer; #else return 0; #endif } char Framework::smallOrBig(char c, bool gr) { int ret = c; if (gr) { if (c >= 'a' && c <= 'z') ret -= 32; else { switch (c) { case SpecialCharacters::CARET: return SpecialCharacters::DEGREE_SIGN; case '1': return '!'; case '<': return '>'; case '2': return '\"'; case '3': return SpecialCharacters::SECTION_SIGN; case '4': return '$'; case '5': return '%'; case '6': return '&'; case '7': return '/'; case '8': return '('; case '9': return ')'; case '0': return '='; case ',': return ';'; case '.': return ':'; case 'ß': return '?'; case '-': return '_'; case SpecialCharacters::ACUTE_ACCENT: return '`'; case '+': return '*'; case '#': return '\''; case SpecialCharacters::SMALL_UE: return SpecialCharacters::BIG_UE; case SpecialCharacters::SMALL_OE: return SpecialCharacters::BIG_OE; case SpecialCharacters::SMALL_AE: return SpecialCharacters::BIG_AE; } } } else { if (c >= 'A' && c <= 'Z') ret += 32; else { switch (c) { case SpecialCharacters::DEGREE_SIGN: return SpecialCharacters::CARET; case '!': return '1'; case '>': return '<'; case '\"': return '2'; case SpecialCharacters::SECTION_SIGN: return '3'; case '$': return '4'; case '%': return '5'; case '&': return '6'; case '/': return '7'; case '(': return '8'; case ')': return '9'; case '=': return '0'; case ';': return ','; case ':': return '.'; case '?': return SpecialCharacters::SZ; case '_': return '-'; case '`': return SpecialCharacters::ACUTE_ACCENT; case '*': return '+'; case '\'': return '#'; case SpecialCharacters::BIG_UE: return SpecialCharacters::SMALL_UE; case SpecialCharacters::BIG_OE: return SpecialCharacters::SMALL_OE; case SpecialCharacters::BIG_AE: return SpecialCharacters::SMALL_AE; } } } return (char)ret; } bool Framework::istSchreibbar( unsigned char zeichen) // checks if zeichen is a printable character { if (zeichen > 32 && zeichen < 127) return 1; if (zeichen == 128 || zeichen == 181 || zeichen == 178 || zeichen == 179) return 1; if (zeichen > 191 && zeichen < 198) return 1; if (zeichen > 199 && zeichen < 208) return 1; if (zeichen > 209 && zeichen < 215) return 1; if (zeichen > 216 && zeichen < 221) return 1; if (zeichen > 222 && zeichen < 230) return 1; if (zeichen > 231 && zeichen < 240) return 1; if (zeichen > 241 && zeichen < 247) return 1; if (zeichen > 248 && zeichen < 253) return 1; if (zeichen == ' ' || zeichen == '\t') return 1; return 0; } unsigned int Framework::TextZuInt( const char* c, int system) // converts c to int { if (system == 16) return (unsigned int)strtoul(c, 0, system); return (unsigned int)strtol(c, 0, system); } unsigned int Framework::TextZuInt(const char* c, char** c_ende, int system) { if (system == 16) return (unsigned int)strtoul(c, c_ende, system); return (unsigned int)strtol(c, c_ende, system); } unsigned __int64 Framework::TextZuInt64(const char* c, int system) { if (system == 16) return strtoull(c, 0, system); return (unsigned __int64)strtoll(c, 0, system); } unsigned __int64 Framework::TextZuInt64( const char* c, char** c_ende, int system) { if (system == 16) return strtoull(c, c_ende, system); return (unsigned __int64)strtoll(c, c_ende, system); } double Framework::TextZuDouble(const char* c) // converts c to double { return strtod(c, 0); } float Framework::TextZuFloat(const char* c) // converts c to float { return strtof(c, 0); } double Framework::TextZuDouble(const char* c, char** c_ende) { return strtod(c, c_ende); } float Framework::TextZuFloat(const char* c, char** c_ende) { return strtof(c, c_ende); } int Framework::textLength(const char* txt) // returns the length of txt { if (!txt) return 0; int ret = 0; for (; txt[ret]; ++ret) ; return ret; }