This allow compile check event for CONNECT and use EVENT as CONNECT target, also raise event now is simple execute EVENT function.
499 lines
12 KiB
C++
499 lines
12 KiB
C++
/*
|
||
PIP - Platform Independent Primitives
|
||
String
|
||
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
|
||
|
||
This program is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
#include "pistring.h"
|
||
|
||
|
||
const char PIString::toBaseN[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
|
||
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
|
||
'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^'};
|
||
const int PIString::fromBaseN[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
|
||
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
|
||
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1,
|
||
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
|
||
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
|
||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
|
||
|
||
|
||
void PIString::appendFromChars(const char * c, int s) {
|
||
int sz;
|
||
wchar_t wc;
|
||
for (int i = 0; i < s; ++i) {
|
||
if (/*isascii(c[i])*/c[i] >= 0) {
|
||
push_back(PIChar(c[i]));
|
||
continue;
|
||
}
|
||
sz = mbtowc(&wc, &c[i], 4);
|
||
//cout << sz << endl;
|
||
switch (sz) {
|
||
case 4:
|
||
push_back(PIChar(*(int*)&(c[i])));
|
||
i += 3;
|
||
continue;
|
||
case 3:
|
||
push_back(PIChar(*(int*)&(c[i])));
|
||
back().ch &= 0xFFFFFF;
|
||
i += 2;
|
||
continue;
|
||
case 2:
|
||
push_back(PIChar(*(short * )&(c[i])));
|
||
++i;
|
||
continue;
|
||
default:
|
||
push_back(PIChar(c[i]));
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
PIString & PIString::operator +=(const char * str) {
|
||
int l = 0;
|
||
while (str[l] != '\0') ++l;
|
||
appendFromChars(str, l);
|
||
return *this;
|
||
}
|
||
|
||
|
||
PIString & PIString::operator +=(const wchar_t * str) {
|
||
//cout << "wc" << endl;
|
||
int l = 0, sz;
|
||
char * c = new char[MB_CUR_MAX];
|
||
while (str[l] != 0) ++l;
|
||
for (int i = 0; i < l; ++i) {
|
||
sz = wctomb(c, str[i]);
|
||
switch (sz) {
|
||
case 4:
|
||
push_back(PIChar(*(int*)c));
|
||
continue;
|
||
case 3:
|
||
push_back(PIChar(*(int*)c));
|
||
back().ch &= 0xFFFFFF;
|
||
continue;
|
||
case 2:
|
||
push_back(PIChar(*(short * )c));
|
||
continue;
|
||
default:
|
||
push_back(PIChar(c[0]));
|
||
break;
|
||
}
|
||
}
|
||
delete[] c;
|
||
return *this;
|
||
}
|
||
|
||
|
||
#ifdef HAS_LOCALE
|
||
PIString & PIString::operator +=(const wstring & str) {
|
||
uint l = str.size();
|
||
for (uint i = 0; i < l; ++i) push_back(str[i]);
|
||
return *this;
|
||
}
|
||
#endif
|
||
|
||
|
||
PIString & PIString::operator +=(const PIString & str) {
|
||
uint l = str.size();
|
||
for (uint i = 0; i < l; ++i) push_back(str[i]);
|
||
return *this;
|
||
}
|
||
|
||
|
||
bool PIString::operator ==(const PIString & str) const {
|
||
uint l = str.size();
|
||
if (size() != l) return false;
|
||
for (uint i = 0; i < l; ++i)
|
||
if (str[i] != at(i))
|
||
return false;
|
||
return true;
|
||
}
|
||
|
||
|
||
bool PIString::operator !=(const PIString & str) const {
|
||
uint l = str.size();
|
||
if (size() != l) return true;
|
||
for (uint i = 0; i < l; ++i)
|
||
if (str[i] != at(i))
|
||
return true;
|
||
return false;
|
||
}
|
||
|
||
|
||
bool PIString::operator <(const PIString & str) const {
|
||
uint l = str.size();
|
||
if (size() < l) return true;
|
||
if (size() > l) return false;
|
||
for (uint i = 0; i < l; ++i) {
|
||
if (str[i] == at(i)) continue;
|
||
if (str[i] < at(i)) return true;
|
||
else return false;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
bool PIString::operator >(const PIString & str) const {
|
||
uint l = str.size();
|
||
if (size() < l) return false;
|
||
if (size() > l) return true;
|
||
for (uint i = 0; i < l; ++i) {
|
||
if (str[i] == at(i)) continue;
|
||
if (str[i] < at(i)) return false;
|
||
else return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
PIString PIString::mid(const int start, const int len) const {
|
||
PIString str;
|
||
int s = start, l = len;
|
||
if (l == 0) return str;
|
||
if (s < 0) {
|
||
l += s;
|
||
s = 0;
|
||
}
|
||
if (l < 0) {
|
||
for (uint i = s; i < size(); ++i)
|
||
str += at(i);
|
||
} else {
|
||
if (l > length() - s)
|
||
l = length() - s;
|
||
for (int i = s; i < s + l; ++i)
|
||
str += at(i);
|
||
}
|
||
return str;
|
||
}
|
||
|
||
|
||
PIString & PIString::cutMid(const int start, const int len) {
|
||
int s = start, l = len;
|
||
if (l == 0) return *this;
|
||
if (s < 0) {
|
||
l += s;
|
||
s = 0;
|
||
}
|
||
if (l < 0)
|
||
remove(s, size() - s);
|
||
else {
|
||
if (l > length() - s)
|
||
l = length() - s;
|
||
remove(s, l);
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
|
||
PIString & PIString::trim() {
|
||
int st = 0, fn = 0;
|
||
for (int i = 0; i < length(); ++i)
|
||
if (at(i) != ' ' && at(i) != '\t')
|
||
{st = i; break;}
|
||
for (int i = length() - 1; i >= 0; --i)
|
||
if (at(i) != ' ' && at(i) != '\t')
|
||
{fn = i; break;}
|
||
*this = mid(st, fn - st + 1);
|
||
return *this;
|
||
}
|
||
|
||
|
||
PIString PIString::trimmed() const {
|
||
int st = 0, fn = 0;
|
||
for (int i = 0; i < length(); ++i)
|
||
if (at(i) != ' ' && at(i) != '\t')
|
||
{st = i; break;}
|
||
for (int i = length() - 1; i >= 0; --i)
|
||
if (at(i) != ' ' && at(i) != '\t')
|
||
{fn = i; break;}
|
||
return mid(st, fn - st + 1);
|
||
}
|
||
|
||
|
||
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]);
|
||
return *this;
|
||
}
|
||
|
||
|
||
PIString & PIString::replace(const PIString & what, const PIString & with, bool * ok) {
|
||
if (what.isEmpty()) {
|
||
if (ok != 0) *ok = false;
|
||
return *this;
|
||
}
|
||
int s = find(what);
|
||
if (s >= 0) replace(s, what.length(), with);
|
||
if (ok != 0) *ok = (s >= 0);
|
||
return *this;
|
||
}
|
||
|
||
|
||
PIString & PIString::replaceAll(const PIString & what, const PIString & with) {
|
||
if (what.isEmpty()) return *this;
|
||
bool ok = true;
|
||
while (ok) replace(what, with, &ok);
|
||
return *this;
|
||
}
|
||
|
||
|
||
PIString & PIString::insert(int index, const PIString & str) {
|
||
uint c = str.length();
|
||
for (uint i = 0; i < c; ++i) insert(index + i, str[i]);
|
||
return *this;
|
||
}
|
||
|
||
|
||
PIStringList PIString::split(const PIString & delim) const {
|
||
PIStringList sl;
|
||
if (isEmpty() || delim.isEmpty()) return sl;
|
||
PIString ts(*this);
|
||
int ci = ts.find(delim);
|
||
while (ci >= 0) {
|
||
sl << ts.left(ci);
|
||
ts.cutLeft(ci + delim.length());
|
||
ci = ts.find(delim);
|
||
}
|
||
if (ts.length() > 0) sl << ts;
|
||
return sl;
|
||
}
|
||
|
||
|
||
int PIString::find(const char str, const int start) const {
|
||
for (int i = start; i < length(); ++i)
|
||
if (at(i) == str)
|
||
return i;
|
||
return -1;
|
||
}
|
||
|
||
|
||
int PIString::find(const PIString str, const int start) const {
|
||
int l = str.length();
|
||
for (int i = start; i < length() - l + 1; ++i)
|
||
if (mid(i, l) == str)
|
||
return i;
|
||
return -1;
|
||
}
|
||
|
||
|
||
int PIString::findLast(const char str, const int start) const {
|
||
for (int i = length() - 1; i >= start; --i)
|
||
if (at(i) == str)
|
||
return i;
|
||
return -1;
|
||
}
|
||
|
||
|
||
int PIString::findLast(const PIString str, const int start) const {
|
||
int l = str.length();
|
||
for (int i = length() - l; i >= start; --i)
|
||
if (mid(i, l) == str)
|
||
return i;
|
||
return -1;
|
||
}
|
||
|
||
|
||
PIString PIString::toUpperCase() const {
|
||
PIString str(*this);
|
||
int l = str.size();
|
||
for (int i = 0; i < l; ++i) str[i] = str[i].toUpper();
|
||
return str;
|
||
}
|
||
|
||
|
||
PIString PIString::toLowerCase() const {
|
||
PIString str(*this);
|
||
int l = str.size();
|
||
for (int i = 0; i < l; ++i) str[i] = str[i].toLower();
|
||
return str;
|
||
}
|
||
|
||
|
||
int PIString::lengthAscii() const {
|
||
int j = 0;
|
||
for (int i = 0; i < size_s(); ++i, ++j)
|
||
if (!at(i).isAscii()) ++j;
|
||
return j;
|
||
}
|
||
|
||
|
||
const char * PIString::data() const {
|
||
PIByteArray & d_(*(const_cast<PIByteArray * >(&data_)));
|
||
d_.clear();
|
||
int wc;
|
||
uchar tc;
|
||
for (int i = 0, j = 0; i < size_s(); ++i) {
|
||
wc = at(i).toInt();
|
||
while (tc = wc & 0xFF, tc) {
|
||
d_.push_back(uchar(tc)); ++j;
|
||
wc >>= 8;
|
||
}
|
||
/*if (at(i).isAscii())
|
||
d_.push_back(uchar(at(i).toAscii()));
|
||
else {
|
||
d_.push_back((at(i).toCharPtr()[0])); ++j;
|
||
d_.push_back((at(i).toCharPtr()[1]));
|
||
}*/
|
||
}
|
||
d_.push_back(uchar('\0'));
|
||
return (const char * )d_.data();
|
||
}
|
||
|
||
|
||
string PIString::convertToStd() const {
|
||
string s;
|
||
int wc;
|
||
uchar tc;
|
||
if (size() > 0) {
|
||
for (int i = 0; i < length(); ++i) {
|
||
wc = at(i).toInt();
|
||
while (tc = wc & 0xFF, tc) {
|
||
s.push_back(char(tc));
|
||
wc >>= 8;
|
||
}
|
||
/*if (at(i).isAscii())
|
||
s.push_back(at(i).toAscii());
|
||
else {
|
||
s.push_back(at(i).toCharPtr()[0]);
|
||
s.push_back(at(i).toCharPtr()[1]);
|
||
}*/
|
||
}
|
||
}
|
||
return s;
|
||
}
|
||
|
||
|
||
char PIString::toChar() const {
|
||
PIString s(toNativeDecimalPoints());
|
||
char v;
|
||
sscanf(s.data(), "%c", &v);
|
||
return v;
|
||
}
|
||
|
||
/*
|
||
short PIString::toShort() const {
|
||
PIString s(trimmed().toLowerCase().toNativeDecimalPoints());
|
||
short v;
|
||
if (s.left(2) == "0x") {sscanf(s.data(), "%hx", &v); return v;}
|
||
if (s.left(1) == "0") {sscanf(s.data(), "%ho", &v); return v;}
|
||
sscanf(s.data(), "%hd", &v);
|
||
return v;
|
||
}
|
||
|
||
|
||
int PIString::toInt() const {
|
||
PIString s(trimmed().toLowerCase().toNativeDecimalPoints());
|
||
int v;
|
||
if (s.left(2) == "0x") {sscanf(s.data(), "%x", &v); return v;}
|
||
if (s.left(1) == "0") {sscanf(s.data(), "%o", &v); return v;}
|
||
sscanf(s.data(), "%d", &v);
|
||
return v;
|
||
}
|
||
|
||
|
||
long PIString::toLong() const {
|
||
PIString s(trimmed().toLowerCase().toNativeDecimalPoints());
|
||
long v;
|
||
if (s.left(2) == "0x") {sscanf(s.data(), "%lx", &v); return v;}
|
||
if (s.left(1) == "0") {sscanf(s.data(), "%lo", &v); return v;}
|
||
sscanf(s.data(), "%ld", &v);
|
||
return v;
|
||
}
|
||
|
||
|
||
llong PIString::toLLong() const {
|
||
PIString s(trimmed().toLowerCase().toNativeDecimalPoints());
|
||
llong v;
|
||
if (s.left(2) == "0x") {sscanf(s.data(), "%llx", &v); return v;}
|
||
if (s.left(1) == "0") {sscanf(s.data(), "%llo", &v); return v;}
|
||
sscanf(s.data(), "%lld", &v);
|
||
return v;
|
||
}
|
||
*/
|
||
|
||
PIString & PIString::setReadableSize(long bytes) {
|
||
clear();
|
||
if (bytes < 1024) {*this += (PIString::fromNumber(bytes) + " B"); return *this;}
|
||
double fres = bytes / 1024.;
|
||
long res = bytes / 1024;
|
||
fres -= res;
|
||
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(int(fres * 10)).left(1) + " kB"); return *this;}
|
||
fres = res / 1024.;
|
||
res /= 1024;
|
||
fres -= res;
|
||
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(int(fres * 10)).left(1) + " MB"); return *this;}
|
||
fres = res / 1024.;
|
||
res /= 1024;
|
||
fres -= res;
|
||
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(int(fres * 10)).left(1) + " GB"); return *this;}
|
||
fres = res / 1024.;
|
||
res /= 1024;
|
||
fres -= res;
|
||
*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(int(fres * 10)).left(1) + " PB");
|
||
return *this;
|
||
}
|
||
|
||
|
||
inline char chrUpr(char c) {
|
||
if (c >= 'a' && c <= 'z') return c + 'A' - 'a';
|
||
//if (c >= 'а' && c <= 'я') return c + 'А' - 'а';
|
||
return c;
|
||
}
|
||
|
||
|
||
inline char chrLwr(char c) {
|
||
if (c >= 'A' && c <= 'Z') return c + 'a' - 'A';
|
||
//if (c >= 'А' && c <= 'Я') return c + 'а' - 'А';
|
||
return c;
|
||
}
|
||
|
||
|
||
PIStringList& PIStringList::removeDuplicates() {
|
||
PIStringList l;
|
||
PIString s;
|
||
bool ae;
|
||
for (uint i = 0; i < size(); ++i) {
|
||
ae = false;
|
||
s = at(i);
|
||
for (uint j = 0; j < l.size(); ++j) {
|
||
if (s != l[j]) continue;
|
||
ae = true; break;
|
||
}
|
||
if (!ae) {
|
||
l << s;
|
||
continue;
|
||
}
|
||
remove(i);
|
||
--i;
|
||
}
|
||
return *this;
|
||
}
|