PIString hard optimization

This commit is contained in:
2020-07-31 14:12:47 +03:00
parent 1d5c979607
commit e728b30e5e
7 changed files with 318 additions and 258 deletions

View File

@@ -173,7 +173,7 @@ PIString PIString::dtos(const double num, char format, int precision) {
PIString PIString::fromNumberBaseS(const llong value, int base, bool * ok) {
if (value == 0LL) return PIString("0");
if (value == 0LL) return PIString('0');
if (base < 2 || base > 40) {if (ok != 0) *ok = false; return PIString();}
if (ok != 0) *ok = true;
if (base == 10) return lltos(value);
@@ -192,7 +192,7 @@ PIString PIString::fromNumberBaseS(const llong value, int base, bool * ok) {
}
PIString PIString::fromNumberBaseU(const ullong value, int base, bool * ok) {
if (value == 0ULL) return PIString("0");
if (value == 0ULL) return PIString('0');
if (base < 2 || base > 40) {if (ok != 0) *ok = false; return PIString();}
if (ok != 0) *ok = true;
if (base == 10) return ulltos(value);
@@ -211,9 +211,10 @@ PIString PIString::fromNumberBaseU(const ullong value, int base, bool * ok) {
llong PIString::toNumberBase(const PIString & value, int base, bool * ok) {
static const PIString s_0x = PIStringAscii("0x");
PIString v = value.trimmed();
if (base < 0) {
int ind = v.find("0x");
int ind = v.find(s_0x);
if (ind == 0 || ind == 1) {v.remove(ind, 2); base = 16;}
else base = 10;
} else
@@ -254,6 +255,7 @@ void PIString::appendFromChars(const char * c, int s, const char * codepage) {
int sz = ucnv_toUChars(cc, ucs, s, c, s, &e);
//printf("appendFromChars %d -> %d\n", s, sz);
//printf("PIString %d -> %d\n", c[0], ucs[0]);
reserve(size_s() + sz);
for (int i = 0; i < sz; ++i)
push_back(PIChar(ucs[i]));
delete[] ucs;
@@ -264,11 +266,9 @@ void PIString::appendFromChars(const char * c, int s, const char * codepage) {
# ifdef WINDOWS
sz = MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, 0, 0);
if (sz <= 0) return;
wchar_t * buffer = new wchar_t[sz];
MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, buffer, sz);
for (int i = 0; i < sz; ++i)
push_back(PIChar((ushort)buffer[i]));
delete[] buffer;
int old_sz = size_s();
enlarge(sz);
MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, (LPWSTR)PIDeque<PIChar>::data(old_sz), sz);
return;
//printf("request %d\n", sz);
# else
@@ -330,9 +330,14 @@ PIString PIString::fromAscii(const char * s) {
PIString ret;
int l = 0;
while (s[l] != '\0') {
ret.push_back(PIChar(short(s[l])));
ret.push_back(PIChar(s[l]));
++l;
}
/*while (s[l] != '\0') ++l;
PIString ret;
ret.resize(l);
for (int i = 0; i < l; ++i)
ret[i] = s[i];*/
return ret;
}
@@ -369,6 +374,7 @@ void PIString::buildData(const char * cp) const {
UConverter * cc = ucnv_open(cp, &e);
if (cc) {
char uc[8];
data_.reserve(size_s());
for (int i = 0; i < size_s(); ++i) {
if (at(i).isAscii())
data_.push_back(uchar(at(i).unicode16Code()));
@@ -605,16 +611,18 @@ PIString PIString::trimmed() const {
PIString & PIString::replace(int from, int count, const PIString & with) {
if (count < length() - from) remove(from, count);
else remove(from, length() - from);
uint c = with.length();
for (uint i = 0; i < c; ++i) insert(from + i, with[i]);
count = piMini(count, length() - from);
if (count == with.size_s())
memcpy(&(at(from)), &(with.at(0)), count * sizeof(PIChar));
else {
remove(from, count);
PIDeque<PIChar>::insert(from, with);
}
return *this;
}
PIString & PIString::replace(const PIString & what, const PIString & with, bool * ok) {
//piCout << "replace" << what << with;
if (what.isEmpty()) {
if (ok != 0) *ok = false;
return *this;
@@ -628,8 +636,53 @@ PIString & PIString::replace(const PIString & what, const PIString & with, bool
PIString & PIString::replaceAll(const PIString & what, const PIString & with) {
if (what.isEmpty() || what == with) return *this;
bool ok = true;
while (ok) replace(what, with, &ok);
if (with.isEmpty()) removeAll(what);
else {
int l = what.length(), dl = with.length() - what.length();
for (int i = 0; i < length() - l + 1; ++i) {
bool match = true;
for (int j = 0; j < l; ++j) {
if (at(j + i) != what[j]) {
match = false;
break;
}
}
if (!match) continue;
if (dl > 0) PIDeque<PIChar>::insert(i, PIDeque<PIChar>((size_t)dl));
if (dl < 0) PIDeque<PIChar>::remove(i, -dl);
memcpy(PIDeque<PIChar>::data(i), &(with.at(0)), with.length() * sizeof(PIChar));
//i -= l;
}
}
return *this;
}
PIString & PIString::replaceAll(const char what, const char with) {
int l = length();
for (int i = 0; i < l; ++i) {
if (at(i) == what)
at(i) = with;
}
return *this;
}
PIString & PIString::removeAll(const PIString & str) {
if (str.isEmpty()) return *this;
int l = str.length();
for (int i = 0; i < length() - l + 1; ++i) {
bool match = true;
for (int j = 0; j < l; ++j) {
if (at(j + i) != str[j]) {
match = false;
break;
}
}
if (!match) continue;
PIDeque<PIChar>::remove(i, l);
i -= l;
}
return *this;
}
@@ -641,16 +694,17 @@ PIString & PIString::insert(int index, const PIString & str) {
PIString & PIString::elide(int size, float pos) {
static const PIString s_dotdot = PIStringAscii("..");
if (length() <= size) return *this;
if (length() <= 2) {
fill(".");
fill('.');
return *this;
}
pos = piClampf(pos, 0.f, 1.f);
int ns = size - 2;
int ls = piRoundf(ns * pos);
remove(ls, length() - ns);
insert(ls, "..");
insert(ls, s_dotdot);
return *this;
}
@@ -670,9 +724,9 @@ PIStringList PIString::split(const PIString & delim) const {
}
int PIString::find(const char str, const int start) const {
int PIString::find(const char c, const int start) const {
for (int i = start; i < length(); ++i)
if (at(i) == str)
if (at(i) == c)
return i;
return -1;
}
@@ -687,9 +741,9 @@ int PIString::find(const PIString & str, const int start) const {
}
int PIString::findLast(const char str, const int start) const {
int PIString::findLast(const char c, const int start) const {
for (int i = length() - 1; i >= start; --i)
if (at(i) == str)
if (at(i) == c)
return i;
return -1;
}
@@ -730,7 +784,7 @@ int PIString::findCWord(const PIString & word, const int start) const {
}
int PIString::findRange(const PIChar & start, const PIChar & end, const PIChar & shield, const int start_index, int * len) const {
int PIString::findRange(const PIChar start, const PIChar end, const PIChar shield, const int start_index, int * len) const {
if (len) *len = 0;
bool trim_ = (start != ' ' && start != '\t' && start != '\n' && start != '\r'), eq = (start == end);
int sz = size_s(), ls = -1, le = -1, cnt = 0;
@@ -783,7 +837,7 @@ int PIString::findAnyLast(const PIString & str, const int start) const {
}
int PIString::entries(const PIChar & c) const {
int PIString::entries(const PIChar c) const {
int sz = size_s(), ret = 0;
for (int i = 0; i < sz; ++i)
if (at(i) == c) ++ret;
@@ -804,9 +858,14 @@ bool PIString::endsWith(const PIString & str) const {
bool PIString::toBool() const {
static const PIString s_true = PIStringAscii("true");
static const PIString s_yes = PIStringAscii("yes" );
static const PIString s_on = PIStringAscii("on" );
static const PIString s_ok = PIStringAscii("ok" );
PIString s(*this);
s = s.trimmed().toLowerCase();
if ( atof(s.toNativeDecimalPoints().data()) > 0. || s == "true" || s == "yes" || s == "on" || s == "ok") return true;
if (s == s_true || s == s_yes || s == s_on || s == s_ok) return true;
if (atof(s.toNativeDecimalPoints().data()) > 0.) return true;
return false;
}
@@ -953,7 +1012,7 @@ PIString PIString::takeNumber() {
}
PIString PIString::takeRange(const PIChar & start, const PIChar & end, const PIChar & shield) {
PIString PIString::takeRange(const PIChar start, const PIChar end, const PIChar shield) {
PIString ret;
bool trim_ = (start != ' ' && start != '\t' && start != '\n' && start != '\r'), eq = (start == end);
int sz = size_s(), ls = -1, le = -1, cnt = 0;
@@ -991,7 +1050,7 @@ PIString PIString::takeRange(const PIChar & start, const PIChar & end, const PIC
}
PIString PIString::inBrackets(const PIChar &start, const PIChar &end) const {
PIString PIString::inBrackets(const PIChar start, const PIChar end) const {
int slen = length();
int st = -1, bcnt = 0;
PIChar cc;
@@ -1030,9 +1089,9 @@ PIString PIString::toNativeDecimalPoints() const {
#ifdef HAS_LOCALE
PIString s(*this);
if (currentLocale == 0) return s;
return s.replaceAll(".", currentLocale->decimal_point).replaceAll(",", currentLocale->decimal_point);
return s.replaceAll('.', currentLocale->decimal_point).replaceAll(',', currentLocale->decimal_point);
#else
return PIString(*this).replaceAll(",", ".");
return PIString(*this).replaceAll(',', '.');
#endif
}
@@ -1062,27 +1121,27 @@ ldouble PIString::toLDouble() const {
PIString & PIString::setReadableSize(llong bytes) {
clear();
if (bytes < 1024) {*this += (PIString::fromNumber(bytes) + " B"); return *this;}
if (bytes < 1024) {*this += (PIString::fromNumber(bytes) + PIStringAscii(" B")); return *this;}
double fres = bytes / 1024.;
llong res = bytes / 1024;
fres -= res;
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " kB"); return *this;}
if (res < 1024) {*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" kB")); return *this;}
fres = res / 1024.;
res /= 1024;
fres -= res;
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " MB"); return *this;}
if (res < 1024) {*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" MB")); return *this;}
fres = res / 1024.;
res /= 1024;
fres -= res;
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " GB"); return *this;}
if (res < 1024) {*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" GB")); return *this;}
fres = res / 1024.;
res /= 1024;
fres -= res;
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " TB"); return *this;}
if (res < 1024) {*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" TB")); return *this;}
fres = res / 1024.;
res /= 1024;
fres -= res;
*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " PB");
*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" PB"));
return *this;
}
@@ -1110,14 +1169,14 @@ void parseVersion(PIString s, PIVector<int> & codes, PIStringList & strs) {
}
int mccnt = 2 - s.entries('.');
if (mccnt > 0) {
int ind = s.findLast(".") + 1;
int ind = s.findLast('.') + 1;
while (!_versionDelims_.contains(s[ind])) {
++ind;
if (ind > s.size_s() - 1)
break;
}
for (int i = 0; i < mccnt; ++i)
s.insert(ind, ".0");
s.insert(ind, PIStringAscii(".0"));
}
PIStringList comps;
while (!s.isEmpty()) {
@@ -1132,7 +1191,7 @@ void parseVersion(PIString s, PIVector<int> & codes, PIStringList & strs) {
}
for (int i = 0; i < comps.size_s(); ++i) {
if (comps[i].isEmpty())
comps[i] = "0";
comps[i] = '0';
bool ok = false;
int val = comps[i].toInt(-1, &ok);
if (ok) {
@@ -1148,20 +1207,20 @@ void parseVersion(PIString s, PIVector<int> & codes, PIStringList & strs) {
int versionLabelValue(PIString s) {
int ret = -10000;
if (s.isEmpty()) return 0;
if (s.startsWith("pre")) {
if (s.startsWith(PIStringAscii("pre"))) {
s.cutLeft(3);
ret -= 1;
}
if (s.startsWith("rc")) {
if (s.startsWith(PIStringAscii("rc"))) {
s.cutLeft(2);
ret += s.toInt();
}
if (s.startsWith("r")) {
if (s.startsWith(PIStringAscii("r"))) {
s.cutLeft(1);
ret += 10000 + s.toInt();
}
if (s == "alpha") ret -= 4;
if (s == "beta" ) ret -= 2;
if (s == PIStringAscii("alpha")) ret -= 4;
if (s == PIStringAscii("beta" )) ret -= 2;
return ret;
}
@@ -1200,13 +1259,13 @@ PIString versionNormalize(const PIString & v) {
PIString ret;
for (int i = 0; i < codes.size_s(); ++i) {
if (i > 0) {
if (i < 3) ret += ".";
else ret += "-";
if (i < 3) ret += '.';
else ret += '-';
}
ret += PIString::fromNumber(codes[i]);
}
for (int i = 0; i < strs.size_s(); ++i) {
ret += "_";
ret += '_';
ret += strs[i];
}
return ret;