Add some helper methods and rewrite some of the string manipulation code

This commit is contained in:
mniip 2018-05-02 01:32:04 +03:00
parent 833383b121
commit a121c62c3b
28 changed files with 314 additions and 214 deletions

View File

@ -1166,26 +1166,22 @@ int main(int argc, char * argv[])
ByteString ptsaveArg = arguments["ptsave"]; ByteString ptsaveArg = arguments["ptsave"];
try try
{ {
if (ptsaveArg.find("ptsave:")) ByteString saveIdPart;
throw std::runtime_error("Invalid save link"); if (ByteString::Split split = arguments["ptsave"].SplitBy(':'))
ByteString saveIdPart = "";
int saveId;
size_t hashPos = ptsaveArg.find('#');
if (hashPos != ByteString::npos)
{ {
saveIdPart = ptsaveArg.substr(7, hashPos-7); if (split.Before() != "ptsave")
throw std::runtime_error("Not a ptsave link");
saveIdPart = split.After().SplitBy('#').Before();
} }
else else
{ throw std::runtime_error("Invalid save link");
saveIdPart = ptsaveArg.substr(7);
} if (!saveIdPart.size())
if (!saveIdPart.length())
throw std::runtime_error("No Save ID"); throw std::runtime_error("No Save ID");
#ifdef DEBUG #ifdef DEBUG
std::cout << "Got Ptsave: id: " << saveIdPart << std::endl; std::cout << "Got Ptsave: id: " << saveIdPart << std::endl;
#endif #endif
saveId = format::ByteStringToNumber<int>(saveIdPart); int saveId = format::ByteStringToNumber<int>(saveIdPart);
if (!saveId) if (!saveId)
throw std::runtime_error("Invalid Save ID"); throw std::runtime_error("Invalid Save ID");
@ -1227,7 +1223,7 @@ int main(int argc, char * argv[])
} }
catch(exception& e) catch(exception& e)
{ {
BlueScreen(e.what()); BlueScreen(ByteString(e.what()).FromUtf8());
} }
#endif #endif

View File

@ -349,17 +349,9 @@ bool Client::DoInstallation()
#include "icondoc.h" #include "icondoc.h"
int success = 1; int success = 1;
ByteString filename = Platform::ExecutableName(), pathname = filename.substr(0, filename.rfind('/')); ByteString filename = Platform::ExecutableName(), pathname = filename.SplitFromEndBy('/').Before();
for (size_t i = 0; i < filename.size(); i++) filename.Substitute('\'', "'\\''");
{ filename = '\'' + filename + '\'';
if (filename[i] == '\'')
{
filename.insert(i, "'\\'");
i += 3;
}
}
filename.insert(filename.size(), "'");
filename.insert(0, "'");
FILE *f; FILE *f;
const char *mimedata = const char *mimedata =
@ -539,18 +531,17 @@ std::vector<ByteString> Client::DirectorySearch(ByteString directory, ByteString
bool extensionMatch = !extensions.size(); bool extensionMatch = !extensions.size();
for(std::vector<ByteString>::iterator extIter = extensions.begin(), extEnd = extensions.end(); extIter != extEnd; ++extIter) for(std::vector<ByteString>::iterator extIter = extensions.begin(), extEnd = extensions.end(); extIter != extEnd; ++extIter)
{ {
size_t filenameLength = filename.length()-(*extIter).length(); if(filename.EndsWith(*extIter))
if(filename.find(*extIter, filenameLength) == filenameLength)
{ {
extensionMatch = true; extensionMatch = true;
tempfilename = filename.substr(0, filenameLength); tempfilename = filename.SubstrFromEnd(0, (*extIter).size());
break; break;
} }
} }
for (ByteString::iterator iter = tempfilename.begin(); iter != tempfilename.end(); ++iter) for (ByteString::iterator iter = tempfilename.begin(); iter != tempfilename.end(); ++iter)
*iter = toupper(*iter); *iter = toupper(*iter);
bool searchMatch = !search.size(); bool searchMatch = !search.size();
if(search.size() && tempfilename.find(search)!=ByteString::npos) if(search.size() && tempfilename.Contains(search))
searchMatch = true; searchMatch = true;
if(searchMatch && extensionMatch) if(searchMatch && extensionMatch)
@ -1202,10 +1193,9 @@ void Client::RescanStamps()
stampIDs.clear(); stampIDs.clear();
while ((entry = readdir(directory))) while ((entry = readdir(directory)))
{ {
if(strncmp(entry->d_name, "..", 3) && strncmp(entry->d_name, ".", 2) && strstr(entry->d_name, ".stm") && strlen(entry->d_name) == 14) ByteString name = entry->d_name;
{ if(name != ".." && name != "." && name.EndsWith(".stm") && name.size() == 14)
stampIDs.push_front(ByteString(entry->d_name).substr(0, 10)); stampIDs.push_front(name.Substr(0, 10));
}
} }
closedir(directory); closedir(directory);
updateStamps(); updateStamps();
@ -2084,11 +2074,10 @@ Json::Value Client::GetPref(Json::Value root, ByteString prop, Json::Value defau
{ {
try try
{ {
size_t dot = prop.find('.'); if(ByteString::Split split = prop.SplitBy('.'))
if (dot == prop.npos) return GetPref(root[split.Before()], split.After(), defaultValue);
return root.get(prop, defaultValue);
else else
return GetPref(root[prop.substr(0, dot)], prop.substr(dot+1), defaultValue); return root.get(prop, defaultValue);
} }
catch (std::exception & e) catch (std::exception & e)
{ {
@ -2277,15 +2266,14 @@ std::vector<bool> Client::GetPrefBoolArray(ByteString prop)
// and return it to SetPref to do the actual setting // and return it to SetPref to do the actual setting
Json::Value Client::SetPrefHelper(Json::Value root, ByteString prop, Json::Value value) Json::Value Client::SetPrefHelper(Json::Value root, ByteString prop, Json::Value value)
{ {
size_t dot = prop.find("."); if(ByteString::Split split = prop.SplitBy('.'))
if (dot == prop.npos)
root[prop] = value;
else
{ {
Json::Value toSet = GetPref(root, prop.substr(0, dot)); Json::Value toSet = GetPref(root, split.Before());
toSet = SetPrefHelper(toSet, prop.substr(dot+1), value); toSet = SetPrefHelper(toSet, split.After(), value);
root[prop.substr(0, dot)] = toSet; root[split.Before()] = toSet;
} }
else
root[prop] = value;
return root; return root;
} }
@ -2293,13 +2281,10 @@ void Client::SetPref(ByteString prop, Json::Value value)
{ {
try try
{ {
size_t dot = prop.find("."); if(ByteString::Split split = prop.SplitBy('.'))
if (dot == prop.npos) preferences[split.Before()] = SetPrefHelper(preferences[split.Before()], split.After(), value);
preferences[prop] = value;
else else
{ preferences[prop] = value;
preferences[prop.substr(0, dot)] = SetPrefHelper(preferences[prop.substr(0, dot)], prop.substr(dot+1), value);
}
} }
catch (std::exception & e) catch (std::exception & e)
{ {

View File

@ -678,7 +678,7 @@ void GameSave::readOPS(char * data, int dataLength)
{ {
if (!strcmp(bson_iterator_key(&signiter), "text") && bson_iterator_type(&signiter) == BSON_STRING) if (!strcmp(bson_iterator_key(&signiter), "text") && bson_iterator_type(&signiter) == BSON_STRING)
{ {
tempSign.text = format::CleanString(ByteString(bson_iterator_string(&signiter)).FromUtf8(), true, true, true).substr(0, 45); tempSign.text = format::CleanString(ByteString(bson_iterator_string(&signiter)).FromUtf8(), true, true, true).Substr(0, 45);
} }
else if (!strcmp(bson_iterator_key(&signiter), "justification") && bson_iterator_type(&signiter) == BSON_INT) else if (!strcmp(bson_iterator_key(&signiter), "justification") && bson_iterator_type(&signiter) == BSON_INT)
{ {
@ -1407,11 +1407,7 @@ void GameSave::readPSv(char * saveDataChar, int dataLength)
int bzStatus = 0; int bzStatus = 0;
if ((bzStatus = BZ2_bzBuffToBuffDecompress((char *)data, (unsigned *)&size, (char *)(saveData+12), dataLength-12, 0, 0))) if ((bzStatus = BZ2_bzBuffToBuffDecompress((char *)data, (unsigned *)&size, (char *)(saveData+12), dataLength-12, 0, 0)))
{ throw ParseException(ParseException::Corrupt, "Cannot decompress: " + format::NumberToString(bzStatus));
String::Stream bzStatusStr;
bzStatusStr << bzStatus;
throw ParseException(ParseException::Corrupt, "Cannot decompress: " + bzStatusStr.str());
}
dataLength = size; dataLength = size;
#ifdef DEBUG #ifdef DEBUG
@ -1952,7 +1948,7 @@ void GameSave::readPSv(char * saveDataChar, int dataLength)
x = 254; x = 254;
memcpy(tempSignText, data+p, x); memcpy(tempSignText, data+p, x);
tempSignText[x] = 0; tempSignText[x] = 0;
tempSign.text = format::CleanString(tempSignText, true, true, true).substr(0, 45); tempSign.text = format::CleanString(tempSignText, true, true, true).Substr(0, 45);
tempSigns.push_back(tempSign); tempSigns.push_back(tempSign);
p += x; p += x;
} }

View File

@ -947,7 +947,7 @@ ByteString FindBoundary(std::map<ByteString, ByteString> parts, ByteString bound
{ {
// loop through every character in each part and search for the substring, adding 1 to map for every character found (character after the substring) // loop through every character in each part and search for the substring, adding 1 to map for every character found (character after the substring)
for (ssize_t j = 0; j < (ssize_t)((*iter).second.length()-blen); j++) for (ssize_t j = 0; j < (ssize_t)((*iter).second.length()-blen); j++)
if (!blen || (*iter).second.substr(j, blen) == boundary) if (!blen || (*iter).second.Substr(j, blen) == boundary)
{ {
unsigned char ch = (*iter).second[j+blen]; unsigned char ch = (*iter).second[j+blen];
if (ch >= '0' && ch <= '9') if (ch >= '0' && ch <= '9')
@ -999,12 +999,11 @@ ByteString GetMultipartMessage(std::map<ByteString, ByteString> parts, ByteStrin
data << "Content-transfer-encoding: binary" << "\r\n"; data << "Content-transfer-encoding: binary" << "\r\n";
// colon p // colon p
size_t colonP = name.find(':'); if (ByteString::Split split = name.SplitBy(':'))
if (colonP != name.npos)
{ {
// used to upload files (save data) // used to upload files (save data)
data << "content-disposition: form-data; name=\"" << name.substr(0, colonP) << "\""; data << "content-disposition: form-data; name=\"" << split.Before() << "\"";
data << "filename=\"" << name.substr(colonP+1) << "\""; data << "filename=\"" << split.After() << "\"";
} }
else else
{ {

View File

@ -7,26 +7,97 @@
class String; class String;
template<typename T> class SplitBase
{
T const &parent;
size_t posBefore;
size_t posAfter;
bool reverse;
inline SplitBase(T const &_parent, size_t _posBefore, size_t offset, bool _reverse):
parent(_parent),
posBefore(_posBefore),
posAfter(_posBefore == T::npos ? T::npos : _posBefore + offset),
reverse(_reverse)
{}
public:
inline T Before(bool includeSeparator = false) const
{
if(posBefore == T::npos)
return reverse ? T() : parent;
return parent.Substr(0, includeSeparator ? posAfter : posBefore);
}
inline T After(bool includeSeparator = false) const
{
if(posBefore == T::npos)
return reverse ? parent : T();
return parent.Substr(includeSeparator ? posBefore : posAfter);
}
inline size_t PositionBefore() const { return posBefore; }
inline size_t PositionAfter() const { return posAfter; }
inline operator bool() const { return posBefore != T::npos; }
friend T;
};
class ByteString : public std::basic_string<char> class ByteString : public std::basic_string<char>
{ {
using super = std::basic_string<char>;
public:
inline ByteString(): super() {}
inline ByteString(value_type ch): super(1, ch) {}
inline ByteString(size_type count, value_type ch): super(count, ch) {}
inline ByteString(value_type const *ch, size_type count): super(ch, count) {}
inline ByteString(value_type const *ch): super(ch) {}
template<class It> inline ByteString(It first, It last): super(first, last) {}
inline ByteString(super const &other): super(other) {}
inline ByteString(super &&other): super(std::move(other)) {}
inline ByteString(ByteString const &other): super(other) {}
inline ByteString(ByteString &&other): super(std::move(other)) {}
inline ByteString &operator=(ByteString const &other) { super::operator=(other); return *this; }
inline ByteString &operator=(ByteString &&other) { super::operator=(other); return *this; }
inline ByteString &operator+=(ByteString const &other) { super::operator+=(other); return *this; }
inline ByteString &operator+=(ByteString &&other) { super::operator+=(std::move(other)); return *this; }
inline ByteString Substr(size_t pos = 0, size_t count = npos) const { return super::substr(pos, count); }
inline ByteString SubstrFromEnd(size_t rpos = 0, size_t rcount = npos) const { return super::substr(rcount == npos || rcount > rpos ? 0 : rpos - rcount, size() - rpos); }
inline ByteString Between(size_t from, size_t to) const { return from >= to ? ByteString() : super::substr(from, to - from); }
inline bool Contains(value_type ch) const { return super::find(ch) != npos; }
inline bool Contains(ByteString const &other) { return super::find(other) != npos; }
inline bool BeginsWith(ByteString const &other) const { return super::compare(0, other.size(), other); }
inline bool EndsWith(ByteString const &other) const { return super::compare(size() - other.size(), other.size(), other); }
using Split = SplitBase<ByteString>;
inline Split SplitBy(value_type ch, size_t pos = 0) const { return Split(*this, super::find(ch, pos), 1, false); }
inline Split SplitBy(ByteString const &str, size_t pos = 0) const { return Split(*this, super::find(str, pos), str.size(), false); }
inline Split SplitByAny(ByteString const &str, size_t pos = 0) const { return Split(*this, super::find_first_of(str, pos), 1, false); }
inline Split SplitByNot(ByteString const &str, size_t pos = 0) const { return Split(*this, super::find_first_not_of(str, pos), 1, false); }
inline Split SplitFromEndBy(value_type ch, size_t pos = npos) const { return Split(*this, super::rfind(ch, pos), 1, true); }
inline Split SplitFromEndBy(ByteString const &str, size_t pos = npos) const { return Split(*this, super::find(str, pos), str.size(), true); }
inline Split SplitFromEndByAny(ByteString const &str, size_t pos = npos) const { return Split(*this, super::find_last_of(str, pos), 1, true); }
inline Split SplitFromEndByNot(ByteString const &str, size_t pos = npos) const { return Split(*this, super::find_last_not_of(str, pos), 1, true); }
inline ByteString &Substitute(ByteString const &needle, ByteString const &replacement)
{
size_t needleSize = needle.size();
size_t replacementSize = replacement.size();
size_t at = super::find(needle);
while(at != npos)
{
super::replace(at, needleSize, replacement);
at += replacementSize + !needleSize;
at = super::find(needle, at);
}
return *this;
}
public: public:
inline ByteString(): std::basic_string<char>() {}
inline ByteString(size_type count, value_type ch): std::basic_string<char>(count, ch) {}
inline ByteString(value_type const *ch, size_type count): std::basic_string<char>(ch, count) {}
inline ByteString(value_type const *ch): std::basic_string<char>(ch) {}
template<class It> inline ByteString(It first, It last): std::basic_string<char>(first, last) {}
inline ByteString(std::basic_string<char> const &other): std::basic_string<char>(other) {}
inline ByteString(std::basic_string<char> &&other): std::basic_string<char>(std::move(other)) {}
inline ByteString(ByteString const &other): std::basic_string<char>(other) {}
inline ByteString(ByteString &&other): std::basic_string<char>(std::move(other)) {}
inline ByteString &operator=(ByteString const &other) { std::basic_string<char>::operator=(other); return *this; }
inline ByteString &operator=(ByteString &&other) { std::basic_string<char>::operator=(std::move(other)); return *this; }
template<typename T> ByteString &operator+=(T &&other) { std::basic_string<char>::operator+=(std::forward<T>(other)); return *this; }
template<typename T> inline ByteString operator+(T &&other) const { ByteString tmp = *this; tmp += std::forward<T>(other); return tmp; }
template<typename... Ts> ByteString substr(Ts&&... args) const { return std::basic_string<char>::substr(std::forward<Ts>(args)...); }
template<typename... Ts> ByteString &insert(Ts&&... args) { std::basic_string<char>::insert(std::forward<Ts>(args)...); return *this; }
class ConversionError : public std::runtime_error class ConversionError : public std::runtime_error
{ {
@ -42,38 +113,89 @@ public:
using Stream = std::basic_stringstream<value_type>; using Stream = std::basic_stringstream<value_type>;
}; };
inline ByteString operator+(ByteString::value_type const *ch, ByteString const &str) { return ByteString(ch) + str; } inline ByteString operator+(ByteString const &lhs, ByteString const &rhs) { return static_cast<std::basic_string<char> const &>(lhs) + static_cast<std::basic_string<char> const &>(rhs); }
inline ByteString operator+(std::basic_string<char> const &other, ByteString const &str) { return ByteString(other) + str; } inline ByteString operator+(ByteString const &lhs, ByteString &&rhs) { return static_cast<std::basic_string<char> const &>(lhs) + static_cast<std::basic_string<char> &&>(rhs); }
inline ByteString operator+(std::basic_string<char> &&other, ByteString const &str) { return ByteString(std::move(other)) + str; } inline ByteString operator+(ByteString &&lhs, ByteString const &rhs) { return static_cast<std::basic_string<char> &&>(lhs) + static_cast<std::basic_string<char> const &>(rhs); }
inline ByteString operator+(ByteString &&lhs, ByteString &&rhs) { return static_cast<std::basic_string<char> &&>(lhs) + static_cast<std::basic_string<char> &&>(rhs); }
inline ByteString operator+(ByteString const &lhs, std::basic_string<char> const &rhs) { return static_cast<std::basic_string<char> const &>(lhs) + rhs; }
inline ByteString operator+(ByteString const &lhs, std::basic_string<char> &&rhs) { return static_cast<std::basic_string<char> const &>(lhs) + std::move(rhs); }
inline ByteString operator+(ByteString &&lhs, std::basic_string<char> const &rhs) { return static_cast<std::basic_string<char> &&>(lhs) + rhs; }
inline ByteString operator+(ByteString &&lhs, std::basic_string<char> &&rhs) { return static_cast<std::basic_string<char> &&>(lhs) + std::move(rhs); }
inline ByteString operator+(ByteString const &lhs, ByteString::value_type rhs) { return static_cast<std::basic_string<char> const &>(lhs) + rhs; }
inline ByteString operator+(ByteString &&lhs, ByteString::value_type rhs) { return static_cast<std::basic_string<char> &&>(lhs) + rhs; }
inline ByteString operator+(ByteString const &lhs, ByteString::value_type const *rhs) { return static_cast<std::basic_string<char> const &>(lhs) + rhs; }
inline ByteString operator+(ByteString &&lhs, ByteString::value_type const *rhs) { return static_cast<std::basic_string<char> &&>(lhs) + rhs; }
inline ByteString operator+(std::basic_string<char> const &lhs, ByteString const &rhs) { return lhs + static_cast<std::basic_string<char> const &>(rhs); }
inline ByteString operator+(std::basic_string<char> const &lhs, ByteString &&rhs) { return lhs + static_cast<std::basic_string<char> &&>(rhs); }
inline ByteString operator+(std::basic_string<char> &&lhs, ByteString const &rhs) { return std::move(lhs) + static_cast<std::basic_string<char> const &>(rhs); }
inline ByteString operator+(std::basic_string<char> &&lhs, ByteString &&rhs) { return std::move(lhs) + static_cast<std::basic_string<char> &&>(rhs); }
inline ByteString operator+(ByteString::value_type lhs, ByteString const &rhs) { return lhs + static_cast<std::basic_string<char> const &>(rhs); }
inline ByteString operator+(ByteString::value_type lhs, ByteString &&rhs) { return lhs + static_cast<std::basic_string<char> &&>(rhs); }
inline ByteString operator+(ByteString::value_type const *lhs, ByteString const &rhs) { return lhs + static_cast<std::basic_string<char> const &>(rhs); }
inline ByteString operator+(ByteString::value_type const *lhs, ByteString &&rhs) { return lhs + static_cast<std::basic_string<char> &&>(rhs); }
class String : public std::basic_string<char32_t> class String : public std::basic_string<char32_t>
{ {
using super = std::basic_string<char32_t>;
public: public:
inline String(): std::basic_string<char32_t>() {} inline String(): super() {}
inline String(size_type count, value_type ch): std::basic_string<char32_t>(count, ch) {} inline String(value_type ch): super(1, ch) {}
inline String(value_type const *ch, size_type count): std::basic_string<char32_t>(ch, count) {} inline String(size_type count, value_type ch): super(count, ch) {}
inline String(value_type const *ch): std::basic_string<char32_t>(ch) {} inline String(value_type const *ch, size_type count): super(ch, count) {}
template<class It> inline String(It first, It last): std::basic_string<char32_t>(first, last) {} inline String(value_type const *ch): super(ch) {}
inline String(std::basic_string<char32_t> const &other): std::basic_string<char32_t>(other) {} template<class It> inline String(It first, It last): super(first, last) {}
inline String(std::basic_string<char32_t> &&other): std::basic_string<char32_t>(std::move(other)) {} inline String(super const &other): super(other) {}
inline String(String const &other): std::basic_string<char32_t>(other) {} inline String(super &&other): super(std::move(other)) {}
inline String(String &&other): std::basic_string<char32_t>(std::move(other)) {} inline String(String const &other): super(other) {}
template<unsigned N> inline String(ByteString::value_type const (&ch)[N]): std::basic_string<char32_t>(ByteString(ch, N - 1).FromAscii()) {} inline String(String &&other): super(std::move(other)) {}
template<size_t N> inline String(ByteString::value_type const (&ch)[N]): super(ByteString(ch, N - 1).FromAscii()) {}
inline String &operator=(String const &other) { std::basic_string<char32_t>::operator=(other); return *this; } inline String &operator=(String const &other) { super::operator=(other); return *this; }
inline String &operator=(String &&other) { std::basic_string<char32_t>::operator=(other); return *this; } inline String &operator=(String &&other) { super::operator=(other); return *this; }
inline String &operator+=(String const &other) { super::operator+=(other); return *this; }
inline String &operator+=(String &&other) { super::operator+=(std::move(other)); return *this; }
inline String Substr(size_t pos = 0, size_t count = npos) const { return super::substr(pos, count); }
inline String SubstrFromEnd(size_t rpos = 0, size_t rcount = npos) const { return super::substr(rcount == npos || rcount > rpos ? 0 : rpos - rcount, size() - rpos); }
inline String Between(size_t from, size_t to) const { return from >= to ? String() : super::substr(from, to - from); }
inline bool Contains(value_type ch) const { return super::find(ch) != npos; }
inline bool Contains(String const &other) const { return super::find(other) != npos; }
inline bool BeginsWith(String const &other) const { return super::compare(0, other.size(), other); }
inline bool EndsWith(String const &other) const { return super::compare(size() - other.size(), other.size(), other); }
using Split = SplitBase<String>;
inline Split SplitBy(value_type ch, size_t pos = 0) const { return Split(*this, super::find(ch, pos), 1, false); }
inline Split SplitBy(String const &str, size_t pos = 0) const { return Split(*this, super::find(str, pos), str.size(), false); }
inline Split SplitByAny(String const &str, size_t pos = 0) const { return Split(*this, super::find_first_of(str, pos), 1, false); }
inline Split SplitByNot(String const &str, size_t pos = 0) const { return Split(*this, super::find_first_not_of(str, pos), 1, false); }
inline Split SplitFromEndBy(value_type ch, size_t pos = npos) const { return Split(*this, super::rfind(ch, pos), 1, true); }
inline Split SplitFromEndBy(String const &str, size_t pos = npos) const { return Split(*this, super::find(str, pos), str.size(), true); }
inline Split SplitFromEndByAny(String const &str, size_t pos = npos) const { return Split(*this, super::find_last_of(str, pos), 1, true); }
inline Split SplitFromEndByNot(String const &str, size_t pos = npos) const { return Split(*this, super::find_last_not_of(str, pos), 1, true); }
inline String &Substitute(String const &needle, String const &replacement)
{
size_t needleSize = needle.size();
size_t replacementSize = replacement.size();
size_t at = super::find(needle);
while(at != npos)
{
super::replace(at, needleSize, replacement);
at += replacementSize + !needleSize;
at = super::find(needle, at);
}
return *this;
}
template<typename T> inline String &operator+=(T &&other) { std::basic_string<char32_t>::operator+=(std::forward<T>(other)); return *this; } inline String &Insert(size_t pos, String const &str) { super::insert(pos, str); return *this; }
template<unsigned N> inline String &operator+=(ByteString::value_type const (&ch)[N]) { std::basic_string<char32_t>::operator+=(ByteString(ch, N - 1).FromAscii()); return *this; } inline String &Erase(size_t pos, size_t count) { super::erase(pos, count); return *this; }
template<typename T> inline String operator+(T &&other) const { String tmp = *this; tmp += std::forward<T>(other); return tmp; } inline String &EraseBetween(size_t from, size_t to) { if(from < to) super::erase(from, to - from); return *this; }
template<typename... Ts> inline String substr(Ts&&... args) const { return std::basic_string<char32_t>::substr(std::forward<Ts>(args)...); }
inline String &insert(size_t pos, String &str) { std::basic_string<char32_t>::insert(pos, str); return *this; }
inline String &insert(size_t pos, size_t n, value_type ch) { std::basic_string<char32_t>::insert(pos, n, ch); return *this; }
template<unsigned N> inline String &insert(size_t pos, ByteString::value_type const (&ch)[N]) { std::basic_string<char32_t>::insert(pos, ByteString(ch, N - 1).FromAscii()); return *this; }
inline size_t find(String const &str, size_t pos = 0) { return std::basic_string<char32_t>::find(str, pos); }
inline size_t find(value_type ch, size_t pos = 0) { return std::basic_string<char32_t>::find(ch, pos); }
inline bool operator==(String const &other) { return std::basic_string<char32_t>(*this) == other; } inline bool operator==(String const &other) { return std::basic_string<char32_t>(*this) == other; }
inline bool operator!=(String const &other) { return std::basic_string<char32_t>(*this) != other; }
ByteString ToUtf8() const; ByteString ToUtf8() const;
ByteString ToAscii() const; ByteString ToAscii() const;
@ -81,11 +203,30 @@ public:
using Stream = std::basic_stringstream<value_type>; using Stream = std::basic_stringstream<value_type>;
}; };
inline String operator+(String::value_type const *ch, String const &str) { return String(ch) + str; } inline String operator+(String const &lhs, String const &rhs) { return static_cast<std::basic_string<char32_t> const &>(lhs) + static_cast<std::basic_string<char32_t> const &>(rhs); }
inline String operator+(std::basic_string<char32_t> const &other, String const &str) { return String(other) + str; } inline String operator+(String const &lhs, String &&rhs) { return static_cast<std::basic_string<char32_t> const &>(lhs) + static_cast<std::basic_string<char32_t> &&>(rhs); }
inline String operator+(std::basic_string<char32_t> &&other, String const &str) { return String(std::move(other)) + str; } inline String operator+(String &&lhs, String const &rhs) { return static_cast<std::basic_string<char32_t> &&>(lhs) + static_cast<std::basic_string<char32_t> const &>(rhs); }
template<unsigned N> inline String operator+(ByteString::value_type const (&ch)[N], String const &str) { return String(ch) + str; } inline String operator+(String &&lhs, String &&rhs) { return static_cast<std::basic_string<char32_t> &&>(lhs) + static_cast<std::basic_string<char32_t> &&>(rhs); }
inline String operator+(String const &lhs, std::basic_string<char32_t> const &rhs) { return static_cast<std::basic_string<char32_t> const &>(lhs) + rhs; }
inline String operator+(String const &lhs, std::basic_string<char32_t> &&rhs) { return static_cast<std::basic_string<char32_t> const &>(lhs) + std::move(rhs); }
inline String operator+(String &&lhs, std::basic_string<char32_t> const &rhs) { return static_cast<std::basic_string<char32_t> &&>(lhs) + rhs; }
inline String operator+(String &&lhs, std::basic_string<char32_t> &&rhs) { return static_cast<std::basic_string<char32_t> &&>(lhs) + std::move(rhs); }
inline String operator+(String const &lhs, String::value_type rhs) { return static_cast<std::basic_string<char32_t> const &>(lhs) + rhs; }
inline String operator+(String &&lhs, String::value_type rhs) { return static_cast<std::basic_string<char32_t> &&>(lhs) + rhs; }
inline String operator+(String const &lhs, String::value_type const *rhs) { return static_cast<std::basic_string<char32_t> const &>(lhs) + rhs; }
inline String operator+(String &&lhs, String::value_type const *rhs) { return static_cast<std::basic_string<char32_t> &&>(lhs) + rhs; }
template<size_t N> inline String operator+(String const &lhs, ByteString::value_type const (&rhs)[N]) { return static_cast<std::basic_string<char32_t> const &>(lhs) + std::move(ByteString(rhs).FromAscii()); }
template<size_t N> inline String operator+(String &&lhs, ByteString::value_type const (&rhs)[N]) { return static_cast<std::basic_string<char32_t> &&>(lhs) + std::move(ByteString(rhs).FromAscii()); }
inline String operator+(std::basic_string<char32_t> const &lhs, String const &rhs) { return lhs + static_cast<std::basic_string<char32_t> const &>(rhs); }
inline String operator+(std::basic_string<char32_t> const &lhs, String &&rhs) { return lhs + static_cast<std::basic_string<char32_t> &&>(rhs); }
inline String operator+(std::basic_string<char32_t> &&lhs, String const &rhs) { return std::move(lhs) + static_cast<std::basic_string<char32_t> const &>(rhs); }
inline String operator+(std::basic_string<char32_t> &&lhs, String &&rhs) { return std::move(lhs) + static_cast<std::basic_string<char32_t> &&>(rhs); }
inline String operator+(String::value_type lhs, String const &rhs) { return lhs + static_cast<std::basic_string<char32_t> const &>(rhs); }
inline String operator+(String::value_type lhs, String &&rhs) { return lhs + static_cast<std::basic_string<char32_t> &&>(rhs); }
inline String operator+(String::value_type const *lhs, String const &rhs) { return lhs + static_cast<std::basic_string<char32_t> const &>(rhs); }
inline String operator+(String::value_type const *lhs, String &&rhs) { return lhs + static_cast<std::basic_string<char32_t> &&>(rhs); }
template<size_t N> inline String operator+(ByteString::value_type const (&lhs)[N], String const &rhs) { return std::move(ByteString(lhs).FromAscii()) + static_cast<std::basic_string<char32_t> const &>(rhs); }
template<size_t N> inline String operator+(ByteString::value_type const (&lhs)[N], String &&rhs) { return std::move(ByteString(lhs).FromAscii()) + static_cast<std::basic_string<char32_t> &&>(rhs); }
inline String ByteString::FromAscii() const inline String ByteString::FromAscii() const
{ {

View File

@ -591,7 +591,7 @@ void Graphics::textnpos(String str, int n, int w, int *cx, int *cy)
while (*s&&n) while (*s&&n)
{ {
wordlen = 0; wordlen = 0;
while(*s && String(" .,!?\n").find(*s) != String::npos) while(*s && String(" .,!?\n").Contains(*s))
s++; s++;
charspace = textwidthx(s, w-x); charspace = textwidthx(s, w-x);
if (charspace<wordlen && wordlen && w-x<w/3) if (charspace<wordlen && wordlen && w-x<w/3)
@ -717,7 +717,7 @@ int Graphics::textwrapheight(String str, int width)
while (*s) while (*s)
{ {
wordlen = 0; wordlen = 0;
while(*s && String(" .,!?\n").find(*s) != String::npos) while(*s && String(" .,!?\n").Contains(*s))
s++; s++;
charspace = textwidthx(s, width-x); charspace = textwidthx(s, width-x);
if (charspace<wordlen && wordlen && width-x<width/3) if (charspace<wordlen && wordlen && width-x<width/3)

View File

@ -805,7 +805,7 @@ void Renderer::DrawWalls()
// there is no velocity here, draw a streamline and continue // there is no velocity here, draw a streamline and continue
if (!xVel && !yVel) if (!xVel && !yVel)
{ {
drawtext(x*CELL, y*CELL-2, String(1, 0xE00D), 255, 255, 255, 128); drawtext(x*CELL, y*CELL-2, 0xE00D, 255, 255, 255, 128);
addpixel(oldX, oldY, 255, 255, 255, 255); addpixel(oldX, oldY, 255, 255, 255, 255);
continue; continue;
} }
@ -836,7 +836,7 @@ void Renderer::DrawWalls()
xf += xVel; xf += xVel;
yf += yVel; yf += yVel;
} }
drawtext(x*CELL, y*CELL-2, String(1, 0xE00D), 255, 255, 255, 128); drawtext(x*CELL, y*CELL-2, 0xE00D, 255, 255, 255, 128);
} }
break; break;
case 1: case 1:

View File

@ -17,7 +17,7 @@ void ConsoleController::EvaluateCommand(String command)
{ {
if(command.length()) if(command.length())
{ {
if (command.substr(0, 6) == "!load ") if (command.BeginsWith("!load "))
CloseConsole(); CloseConsole();
int returnCode = commandInterface->Command(command); int returnCode = commandInterface->Command(command);
consoleModel->AddLastCommand(ConsoleCommand(command, returnCode, commandInterface->GetLastError())); consoleModel->AddLastCommand(ConsoleCommand(command, returnCode, commandInterface->GetLastError()));

View File

@ -117,9 +117,9 @@ void ElementSearchActivity::searchTools(String query)
std::transform(nameLower.begin(), nameLower.end(), nameLower.begin(), ::tolower); std::transform(nameLower.begin(), nameLower.end(), nameLower.begin(), ::tolower);
if(nameLower == queryLower) if(nameLower == queryLower)
exactmatches.push_back(*iter); exactmatches.push_back(*iter);
else if(!nameLower.compare(0, queryLower.length(), queryLower)) else if(!nameLower.BeginsWith(queryLower))
frontmatches.push_back(*iter); frontmatches.push_back(*iter);
else if(nameLower.find(queryLower) != String::npos) else if(nameLower.Contains(queryLower))
matches.push_back(*iter); matches.push_back(*iter);
} }
@ -181,7 +181,7 @@ void ElementSearchActivity::SetActiveTool(int selectionState, Tool * tool)
gameController->RebuildFavoritesMenu(); gameController->RebuildFavoritesMenu();
} }
else if (ctrlPressed && altPressed && !shiftPressed && else if (ctrlPressed && altPressed && !shiftPressed &&
tool->GetIdentifier().find("DEFAULT_PT_") != tool->GetIdentifier().npos) tool->GetIdentifier().Contains("DEFAULT_PT_"))
{ {
gameController->SetActiveTool(3, tool); gameController->SetActiveTool(3, tool);
} }

View File

@ -75,17 +75,8 @@ class LoadFilesTask: public Task
saveFile->SetGameSave(tempSave); saveFile->SetGameSave(tempSave);
saveFiles.push_back(saveFile); saveFiles.push_back(saveFile);
ByteString filename = *iter; ByteString filename = (*iter).SplitFromEndBy(PATH_SEP).After();
size_t folderPos = filename.rfind(PATH_SEP); filename = filename.SplitBy('.').Before();
if(folderPos!=ByteString::npos && folderPos+1 < filename.size())
{
filename = filename.substr(folderPos+1);
}
size_t extPos = filename.rfind(".");
if(extPos!=ByteString::npos)
{
filename = filename.substr(0, extPos);
}
saveFile->SetDisplayName(filename.FromUtf8()); saveFile->SetDisplayName(filename.FromUtf8());
} }
catch(std::exception & e) catch(std::exception & e)

View File

@ -281,7 +281,7 @@ FontEditor::FontEditor(ByteString _header):
v->PrevChar(); v->PrevChar();
} }
}; };
ui::Button *prev = new ui::Button(ui::Point(currentX, baseline), ui::Point(17, 17), String(1, 0xE016)); ui::Button *prev = new ui::Button(ui::Point(currentX, baseline), ui::Point(17, 17), 0xE016);
currentX += 18; currentX += 18;
prev->SetActionCallback(new PrevCharAction(this)); prev->SetActionCallback(new PrevCharAction(this));
AddComponent(prev); AddComponent(prev);
@ -316,7 +316,7 @@ FontEditor::FontEditor(ByteString _header):
v->NextChar(); v->NextChar();
} }
}; };
ui::Button *next = new ui::Button(ui::Point(currentX, baseline), ui::Point(17, 17), String(1, 0xE015)); ui::Button *next = new ui::Button(ui::Point(currentX, baseline), ui::Point(17, 17), 0xE015);
currentX += 18; currentX += 18;
next->SetActionCallback(new NextCharAction(this)); next->SetActionCallback(new NextCharAction(this));
AddComponent(next); AddComponent(next);

View File

@ -674,7 +674,7 @@ bool GameController::MouseUp(int x, int y, unsigned button, char type)
ret = false; ret = false;
if (type == 'c' || type == 't' || type == 's') if (type == 'c' || type == 't' || type == 's')
{ {
String link = str.substr(3, pos-3); String link = str.Substr(3, pos-3);
switch (type) switch (type)
{ {
case 'c': case 'c':
@ -983,7 +983,7 @@ void GameController::Update()
{ {
int rightSelected = PT_DUST; int rightSelected = PT_DUST;
Tool * activeTool = gameModel->GetActiveTool(1); Tool * activeTool = gameModel->GetActiveTool(1);
if (activeTool->GetIdentifier().find("DEFAULT_PT_") != activeTool->GetIdentifier().npos) if (activeTool->GetIdentifier().BeginsWith("DEFAULT_PT_"))
{ {
int sr = activeTool->GetToolID(); int sr = activeTool->GetToolID();
if (sr && sim->IsValidElement(sr)) if (sr && sim->IsValidElement(sr))

View File

@ -433,7 +433,7 @@ GameView::GameView():
v->c->OpenElementSearch(); v->c->OpenElementSearch();
} }
}; };
ui::Button * tempButton = new ui::Button(ui::Point(WINDOWW-16, WINDOWH-32), ui::Point(15, 15), String(1, 0xE065), "Search for elements"); ui::Button * tempButton = new ui::Button(ui::Point(WINDOWW-16, WINDOWH-32), ui::Point(15, 15), 0xE065, "Search for elements");
tempButton->Appearance.Margin = ui::Border(0, 2, 3, 2); tempButton->Appearance.Margin = ui::Border(0, 2, 3, 2);
tempButton->SetActionCallback(new ElementSearchAction(this)); tempButton->SetActionCallback(new ElementSearchAction(this));
AddComponent(tempButton); AddComponent(tempButton);
@ -555,7 +555,7 @@ public:
else else
{ {
if (v->CtrlBehaviour() && v->AltBehaviour() && !v->ShiftBehaviour()) if (v->CtrlBehaviour() && v->AltBehaviour() && !v->ShiftBehaviour())
if (tool->GetIdentifier().find("DEFAULT_PT_") != tool->GetIdentifier().npos) if (tool->GetIdentifier().BeginsWith("DEFAULT_PT_"))
sender->SetSelectionState(3); sender->SetSelectionState(3);
if (sender->GetSelectionState() >= 0 && sender->GetSelectionState() <= 3) if (sender->GetSelectionState() >= 0 && sender->GetSelectionState() <= 3)
@ -676,18 +676,15 @@ void GameView::NotifyActiveToolsChanged(GameModel * sender)
if(sender->GetActiveTool(0) == tool) if(sender->GetActiveTool(0) == tool)
{ {
toolButtons[i]->SetSelectionState(0); //Primary toolButtons[i]->SetSelectionState(0); //Primary
if (tool->GetIdentifier().find("DEFAULT_UI_WIND") != tool->GetIdentifier().npos) windTool = tool->GetIdentifier() == "DEFAULT_UI_WIND";
windTool = true;
else
windTool = false;
if (sender->GetActiveTool(0)->GetIdentifier().find("DEFAULT_DECOR_") != sender->GetActiveTool(0)->GetIdentifier().npos) if (sender->GetActiveTool(0)->GetIdentifier().BeginsWith("DEFAULT_DECOR_"))
decoBrush = true; decoBrush = true;
} }
else if(sender->GetActiveTool(1) == tool) else if(sender->GetActiveTool(1) == tool)
{ {
toolButtons[i]->SetSelectionState(1); //Secondary toolButtons[i]->SetSelectionState(1); //Secondary
if (sender->GetActiveTool(1)->GetIdentifier().find("DEFAULT_DECOR_") != sender->GetActiveTool(1)->GetIdentifier().npos) if (sender->GetActiveTool(1)->GetIdentifier().BeginsWith("DEFAULT_DECOR_"))
decoBrush = true; decoBrush = true;
} }
else if(sender->GetActiveTool(2) == tool) else if(sender->GetActiveTool(2) == tool)
@ -708,7 +705,7 @@ void GameView::NotifyActiveToolsChanged(GameModel * sender)
if (sender->GetRenderer()->findingElement) if (sender->GetRenderer()->findingElement)
{ {
Tool *active = sender->GetActiveTool(0); Tool *active = sender->GetActiveTool(0);
if (active->GetIdentifier().find("_PT_") == active->GetIdentifier().npos) if (active->GetIdentifier().Contains("_PT_"))
ren->findingElement = 0; ren->findingElement = 0;
else else
ren->findingElement = sender->GetActiveTool(0)->GetToolID()%256; ren->findingElement = sender->GetActiveTool(0)->GetToolID()%256;
@ -723,10 +720,7 @@ void GameView::NotifyLastToolChanged(GameModel * sender)
if (sender->GetLastTool()) if (sender->GetLastTool())
{ {
wallBrush = sender->GetLastTool()->GetBlocky(); wallBrush = sender->GetLastTool()->GetBlocky();
if (sender->GetLastTool()->GetIdentifier().find("DEFAULT_TOOL_") != sender->GetLastTool()->GetIdentifier().npos) toolBrush = sender->GetLastTool()->GetIdentifier().BeginsWith("DEFAULT_TOOL_");
toolBrush = true;
else
toolBrush = false;
} }
} }
@ -1504,7 +1498,7 @@ void GameView::OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool
if (ctrl) if (ctrl)
{ {
Tool *active = c->GetActiveTool(0); Tool *active = c->GetActiveTool(0);
if (active->GetIdentifier().find("_PT_") == active->GetIdentifier().npos || ren->findingElement == active->GetToolID()%256) if (!active->GetIdentifier().Contains("_PT_") || ren->findingElement == active->GetToolID()%256)
ren->findingElement = 0; ren->findingElement = 0;
else else
ren->findingElement = active->GetToolID()%256; ren->findingElement = active->GetToolID()%256;
@ -1739,7 +1733,7 @@ void GameView::OnTick(float dt)
int pos = sign::splitsign(str, &type); int pos = sign::splitsign(str, &type);
if (type == 'c' || type == 't' || type == 's') if (type == 'c' || type == 't' || type == 's')
{ {
String linkSign = str.substr(3, pos-3); String linkSign = str.Substr(3, pos-3);
String::Stream tooltip; String::Stream tooltip;
switch (type) switch (type)
{ {
@ -1912,7 +1906,7 @@ void GameView::NotifyNotificationsChanged(GameModel * sender)
AddComponent(tempButton); AddComponent(tempButton);
notificationComponents.push_back(tempButton); notificationComponents.push_back(tempButton);
tempButton = new ui::Button(ui::Point(XRES-20, currentY), ui::Point(15, 15), String(1, 0xE02A)); tempButton = new ui::Button(ui::Point(XRES-20, currentY), ui::Point(15, 15), 0xE02A);
//tempButton->SetIcon(IconClose); //tempButton->SetIcon(IconClose);
tempButton->SetActionCallback(new CloseNotificationButtonAction(this, *iter)); tempButton->SetActionCallback(new CloseNotificationButtonAction(this, *iter));
tempButton->Appearance.Margin.Left -= 1; tempButton->Appearance.Margin.Left -= 1;
@ -2266,7 +2260,7 @@ void GameView::OnDraw()
{ {
String::Stream sampleInfo; String::Stream sampleInfo;
sampleInfo << recordingIndex; sampleInfo << recordingIndex;
sampleInfo << ". " + String(1, 0xE00E) + " REC"; sampleInfo << ". " + String(0xE00E) + " REC";
int textWidth = Graphics::textwidth(sampleInfo.str()); int textWidth = Graphics::textwidth(sampleInfo.str());
g->fillrect(XRES-20-textWidth, 12, textWidth+8, 15, 0, 0, 0, 255*0.5); g->fillrect(XRES-20-textWidth, 12, textWidth+8, 15, 0, 0, 0, 255*0.5);

View File

@ -104,20 +104,20 @@ void PropertyWindow::SetProperty()
case StructProperty::ParticleType: case StructProperty::ParticleType:
{ {
int v; int v;
if(value.length() > 2 && value.substr(0, 2) == "0x") if(value.length() > 2 && value.BeginsWith("0x"))
{ {
//0xC0FFEE //0xC0FFEE
String::Stream buffer; String::Stream buffer;
buffer.exceptions(String::Stream::failbit | String::Stream::badbit); buffer.exceptions(String::Stream::failbit | String::Stream::badbit);
buffer << std::hex << value.substr(2); buffer << std::hex << value.Substr(2);
buffer >> v; buffer >> v;
} }
else if(value.length() > 1 && value[0] == '#') else if(value.length() > 1 && value.BeginsWith("0"))
{ {
//#C0FFEE //#C0FFEE
String::Stream buffer; String::Stream buffer;
buffer.exceptions(String::Stream::failbit | String::Stream::badbit); buffer.exceptions(String::Stream::failbit | String::Stream::badbit);
buffer << std::hex << value.substr(1); buffer << std::hex << value.Substr(1);
buffer >> v; buffer >> v;
} }
else else
@ -155,20 +155,20 @@ void PropertyWindow::SetProperty()
case StructProperty::UInteger: case StructProperty::UInteger:
{ {
unsigned int v; unsigned int v;
if(value.length() > 2 && value.substr(0, 2) == "0x") if(value.length() > 2 && value.BeginsWith("0x"))
{ {
//0xC0FFEE //0xC0FFEE
String::Stream buffer; String::Stream buffer;
buffer.exceptions(String::Stream::failbit | String::Stream::badbit); buffer.exceptions(String::Stream::failbit | String::Stream::badbit);
buffer << std::hex << value.substr(2); buffer << std::hex << value.Substr(2);
buffer >> v; buffer >> v;
} }
else if(value.length() > 1 && value[0] == '#') else if(value.length() > 1 && value.BeginsWith("#"))
{ {
//#C0FFEE //#C0FFEE
String::Stream buffer; String::Stream buffer;
buffer.exceptions(String::Stream::failbit | String::Stream::badbit); buffer.exceptions(String::Stream::failbit | String::Stream::badbit);
buffer << std::hex << value.substr(1); buffer << std::hex << value.Substr(1);
buffer >> v; buffer >> v;
} }
else else
@ -190,9 +190,9 @@ void PropertyWindow::SetProperty()
buffer >> tool->propValue.Float; buffer >> tool->propValue.Float;
if (properties[property->GetOption().second].Name == "temp" && value.length()) if (properties[property->GetOption().second].Name == "temp" && value.length())
{ {
if (value.substr(value.length()-1) == "C") if (value.EndsWith("C"))
tool->propValue.Float += 273.15; tool->propValue.Float += 273.15;
else if (value.substr(value.length()-1) == "F") else if (value.EndsWith("F"))
tool->propValue.Float = (tool->propValue.Float-32.0f)*5/9+273.15f; tool->propValue.Float = (tool->propValue.Float-32.0f)*5/9+273.15f;
} }
#ifdef DEBUG #ifdef DEBUG

View File

@ -128,10 +128,10 @@ SignWindow::SignWindow(SignTool * tool_, Simulation * sim_, int signID_, ui::Poi
justification = new ui::DropDown(ui::Point(52, 48), ui::Point(50, 16)); justification = new ui::DropDown(ui::Point(52, 48), ui::Point(50, 16));
AddComponent(justification); AddComponent(justification);
justification->AddOption(std::pair<String, int>(String(1, 0xE020) + " Left", (int)sign::Left)); justification->AddOption(std::pair<String, int>(0xE020 + String(" Left"), (int)sign::Left));
justification->AddOption(std::pair<String, int>(String(1, 0xE01E) + " Middle", (int)sign::Middle)); justification->AddOption(std::pair<String, int>(0xE01E + String(" Middle"), (int)sign::Middle));
justification->AddOption(std::pair<String, int>(String(1, 0xE01F) + " Right", (int)sign::Right)); justification->AddOption(std::pair<String, int>(0xE01F + String(" Right"), (int)sign::Right));
justification->AddOption(std::pair<String, int>(String(1, 0xE01D) + " None", (int)sign::None)); justification->AddOption(std::pair<String, int>(0xE01D + String(" None"), (int)sign::None));
justification->SetOption(1); justification->SetOption(1);
justification->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; justification->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;

View File

@ -13,7 +13,7 @@ ToolButton::ToolButton(ui::Point position, ui::Point size, ByteString text_, Byt
Appearance.BorderFavorite = ui::Colour(255, 255, 0); Appearance.BorderFavorite = ui::Colour(255, 255, 0);
//don't use "..." on elements that have long names //don't use "..." on elements that have long names
buttonDisplayText = ButtonText.substr(0, 7); buttonDisplayText = ButtonText.Substr(0, 7);
Component::TextPosition(buttonDisplayText); Component::TextPosition(buttonDisplayText);
} }
@ -67,7 +67,7 @@ void ToolButton::Draw(const ui::Point& screenPos)
} }
if (Favorite::Ref().IsFavorite(toolIdentifier)) if (Favorite::Ref().IsFavorite(toolIdentifier))
{ {
g->drawtext(screenPos.X, screenPos.Y, String(1, 0xE068), Appearance.BorderFavorite.Red, Appearance.BorderFavorite.Green, Appearance.BorderFavorite.Blue, Appearance.BorderFavorite.Alpha); g->drawtext(screenPos.X, screenPos.Y, 0xE068, Appearance.BorderFavorite.Red, Appearance.BorderFavorite.Green, Appearance.BorderFavorite.Blue, Appearance.BorderFavorite.Alpha);
} }
if (totalColour<544) if (totalColour<544)

View File

@ -214,9 +214,9 @@ void Label::copySelection()
String copyText; String copyText;
if (selectionIndex1 > selectionIndex0) if (selectionIndex1 > selectionIndex0)
copyText = currentText.substr(selectionIndex0, selectionIndex1-selectionIndex0).c_str(); copyText = currentText.Between(selectionIndex0, selectionIndex1).c_str();
else if(selectionIndex0 > selectionIndex1) else if(selectionIndex0 > selectionIndex1)
copyText = currentText.substr(selectionIndex1, selectionIndex0-selectionIndex1).c_str(); copyText = currentText.Between(selectionIndex1, selectionIndex0).c_str();
else if (!currentText.length()) else if (!currentText.length())
return; return;
else else
@ -324,8 +324,8 @@ void Label::updateSelection()
textFragments = currentText; textFragments = currentText;
//textFragments.insert(selectionIndex1, "\x0E"); //textFragments.insert(selectionIndex1, "\x0E");
//textFragments.insert(selectionIndex0, "\x0F\x01\x01\x01"); //textFragments.insert(selectionIndex0, "\x0F\x01\x01\x01");
textFragments.insert(selectionIndex1, "\x01"); textFragments.Insert(selectionIndex1, "\x01");
textFragments.insert(selectionIndex0, "\x01"); textFragments.Insert(selectionIndex0, "\x01");
} else if(selectionIndex0 > selectionIndex1) { } else if(selectionIndex0 > selectionIndex1) {
selectionLineH = Graphics::PositionAtCharIndex(currentText, selectionIndex0, selectionXH, selectionYH); selectionLineH = Graphics::PositionAtCharIndex(currentText, selectionIndex0, selectionXH, selectionYH);
selectionLineL = Graphics::PositionAtCharIndex(currentText, selectionIndex1, selectionXL, selectionYL); selectionLineL = Graphics::PositionAtCharIndex(currentText, selectionIndex1, selectionXL, selectionYL);
@ -333,8 +333,8 @@ void Label::updateSelection()
textFragments = currentText; textFragments = currentText;
//textFragments.insert(selectionIndex0, "\x0E"); //textFragments.insert(selectionIndex0, "\x0E");
//textFragments.insert(selectionIndex1, "\x0F\x01\x01\x01"); //textFragments.insert(selectionIndex1, "\x0F\x01\x01\x01");
textFragments.insert(selectionIndex0, "\x01"); textFragments.Insert(selectionIndex0, "\x01");
textFragments.insert(selectionIndex1, "\x01"); textFragments.Insert(selectionIndex1, "\x01");
} else { } else {
selectionXH = -1; selectionXH = -1;
selectionXL = -1; selectionXL = -1;
@ -349,14 +349,14 @@ void Label::updateSelection()
int tSelectionIndex1 = Graphics::CharIndexAtPosition(displayText, selectionXH, selectionYH); int tSelectionIndex1 = Graphics::CharIndexAtPosition(displayText, selectionXH, selectionYH);
int tSelectionIndex0 = Graphics::CharIndexAtPosition(displayText, selectionXL, selectionYL); int tSelectionIndex0 = Graphics::CharIndexAtPosition(displayText, selectionXL, selectionYL);
displayText.insert(tSelectionIndex1, "\x01"); displayText.Insert(tSelectionIndex1, "\x01");
displayText.insert(tSelectionIndex0, "\x01"); displayText.Insert(tSelectionIndex0, "\x01");
} else if(selectionIndex0 > selectionIndex1) { } else if(selectionIndex0 > selectionIndex1) {
int tSelectionIndex0 = Graphics::CharIndexAtPosition(displayText, selectionXH, selectionYH); int tSelectionIndex0 = Graphics::CharIndexAtPosition(displayText, selectionXH, selectionYH);
int tSelectionIndex1 = Graphics::CharIndexAtPosition(displayText, selectionXL, selectionYL); int tSelectionIndex1 = Graphics::CharIndexAtPosition(displayText, selectionXL, selectionYL);
displayText.insert(tSelectionIndex0, "\x01"); displayText.Insert(tSelectionIndex0, "\x01");
displayText.insert(tSelectionIndex1, "\x01"); displayText.Insert(tSelectionIndex1, "\x01");
} }
} }
} }

View File

@ -239,15 +239,15 @@ void SaveButton::Draw(const Point& screenPos)
int y = screenPos.Y-15+(Size.Y-thumbBoxSize.Y)/2+thumbBoxSize.Y; int y = screenPos.Y-15+(Size.Y-thumbBoxSize.Y)/2+thumbBoxSize.Y;
g->fillrect(x+1, y+1, 7, 8, 255, 255, 255, 255); g->fillrect(x+1, y+1, 7, 8, 255, 255, 255, 255);
if (isMouseInsideHistory) { if (isMouseInsideHistory) {
g->drawtext(x, y, String(1, 0xE026), 200, 100, 80, 255); g->drawtext(x, y, 0xE026, 200, 100, 80, 255);
} else { } else {
g->drawtext(x, y, String(1, 0xE026), 160, 70, 50, 255); g->drawtext(x, y, 0xE026, 160, 70, 50, 255);
} }
} }
if (!save->GetPublished()) if (!save->GetPublished())
{ {
g->drawtext(screenPos.X, screenPos.Y-2, String(1, 0xE04D), 255, 255, 255, 255); g->drawtext(screenPos.X, screenPos.Y-2, 0xE04D, 255, 255, 255, 255);
g->drawtext(screenPos.X, screenPos.Y-2, String(1, 0xE04E), 212, 151, 81, 255); g->drawtext(screenPos.X, screenPos.Y-2, 0xE04E, 212, 151, 81, 255);
} }
} }
else if (file) else if (file)

View File

@ -141,7 +141,7 @@ void Textbox::cutSelection()
{ {
if (getLowerSelectionBound() < 0 || getHigherSelectionBound() > (int)backingText.length()) if (getLowerSelectionBound() < 0 || getHigherSelectionBound() > (int)backingText.length())
return; return;
String toCopy = backingText.substr(getLowerSelectionBound(), getHigherSelectionBound()-getLowerSelectionBound()); String toCopy = backingText.Between(getLowerSelectionBound(), getHigherSelectionBound());
ClipboardPush(format::CleanString(toCopy, false, true, false).ToUtf8()); ClipboardPush(format::CleanString(toCopy, false, true, false).ToUtf8());
backingText.erase(backingText.begin()+getLowerSelectionBound(), backingText.begin()+getHigherSelectionBound()); backingText.erase(backingText.begin()+getLowerSelectionBound(), backingText.begin()+getHigherSelectionBound());
cursor = getLowerSelectionBound(); cursor = getLowerSelectionBound();
@ -191,7 +191,7 @@ void Textbox::pasteIntoSelection()
{ {
if (getLowerSelectionBound() < 0 || getHigherSelectionBound() > (int)backingText.length()) if (getLowerSelectionBound() < 0 || getHigherSelectionBound() > (int)backingText.length())
return; return;
backingText.erase(backingText.begin()+getLowerSelectionBound(), backingText.begin()+getHigherSelectionBound()); backingText.EraseBetween(getLowerSelectionBound(), getHigherSelectionBound());
cursor = getLowerSelectionBound(); cursor = getLowerSelectionBound();
} }
@ -203,7 +203,7 @@ void Textbox::pasteIntoSelection()
if (limit != String::npos) if (limit != String::npos)
{ {
newText = newText.substr(0, limit-backingText.length()); newText = newText.Substr(0, limit-backingText.length());
} }
if (!multiline && Graphics::textwidth(backingText + newText) > regionWidth) if (!multiline && Graphics::textwidth(backingText + newText) > regionWidth)
{ {
@ -211,12 +211,12 @@ void Textbox::pasteIntoSelection()
int cIndex = Graphics::CharIndexAtPosition(newText, pLimit, 0); int cIndex = Graphics::CharIndexAtPosition(newText, pLimit, 0);
if (cIndex > 0) if (cIndex > 0)
newText = newText.substr(0, cIndex); newText = newText.Substr(0, cIndex);
else else
newText = ""; newText = "";
} }
backingText.insert(cursor, newText); backingText.Insert(cursor, newText);
cursor = cursor+newText.length(); cursor = cursor+newText.length();
ClearSelection(); ClearSelection();
@ -353,7 +353,7 @@ void Textbox::OnVKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool
{ {
if (getLowerSelectionBound() < 0 || getHigherSelectionBound() > (int)backingText.length()) if (getLowerSelectionBound() < 0 || getHigherSelectionBound() > (int)backingText.length())
return; return;
backingText.erase(backingText.begin()+getLowerSelectionBound(), backingText.begin()+getHigherSelectionBound()); backingText.Erase(getLowerSelectionBound(), getHigherSelectionBound());
cursor = getLowerSelectionBound(); cursor = getLowerSelectionBound();
changed = true; changed = true;
} }
@ -362,9 +362,9 @@ void Textbox::OnVKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool
if (ctrl) if (ctrl)
{ {
size_t stopChar; size_t stopChar;
stopChar = backingText.find_first_not_of(String(" .,!?\n"), cursor); stopChar = backingText.SplitByNot(" .,!?\n", cursor).PositionBefore();
stopChar = backingText.find_first_of(String(" .,!?\n"), stopChar); stopChar = backingText.SplitByAny(" .,!?\n", stopChar).PositionBefore();
backingText.erase(cursor, stopChar-cursor); backingText.EraseBetween(cursor, stopChar);
} }
else else
backingText.erase(cursor, 1); backingText.erase(cursor, 1);
@ -388,12 +388,12 @@ void Textbox::OnVKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool
if (ctrl) if (ctrl)
{ {
size_t stopChar; size_t stopChar;
stopChar = backingText.substr(0, cursor).find_last_not_of(String(" .,!?\n")); stopChar = backingText.SplitFromEndByNot(" .,!?\n", cursor).PositionBefore();
if (stopChar == backingText.npos) if (stopChar == backingText.npos)
stopChar = -1; stopChar = -1;
else else
stopChar = backingText.substr(0, stopChar).find_last_of(String(" .,!?\n")); stopChar = backingText.SplitFromEndByAny(" .,!?\n", stopChar).PositionBefore();
backingText.erase(stopChar+1, cursor-(stopChar+1)); backingText.EraseBetween(stopChar+1, cursor);
cursor = stopChar+1; cursor = stopChar+1;
} }
else else
@ -431,7 +431,7 @@ void Textbox::OnVKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool
} }
else else
{ {
backingText.insert(cursor, 1, String::value_type(character)); backingText.Insert(cursor, character);
} }
cursor++; cursor++;
} }

View File

@ -21,8 +21,8 @@ LocalBrowserView::LocalBrowserView():
lastChanged(0), lastChanged(0),
pageCount(0) pageCount(0)
{ {
nextButton = new ui::Button(ui::Point(WINDOWW-52, WINDOWH-18), ui::Point(50, 16), "Next " + String(1, 0xE015)); nextButton = new ui::Button(ui::Point(WINDOWW-52, WINDOWH-18), ui::Point(50, 16), String("Next ") + 0xE015);
previousButton = new ui::Button(ui::Point(2, WINDOWH-18), ui::Point(50, 16), String(1, 0xE016) + " Prev"); previousButton = new ui::Button(ui::Point(2, WINDOWH-18), ui::Point(50, 16), 0xE016 + String(" Prev"));
undeleteButton = new ui::Button(ui::Point(WINDOWW-122, WINDOWH-18), ui::Point(60, 16), "Rescan"); undeleteButton = new ui::Button(ui::Point(WINDOWW-122, WINDOWH-18), ui::Point(60, 16), "Rescan");
AddComponent(nextButton); AddComponent(nextButton);
AddComponent(previousButton); AddComponent(previousButton);

View File

@ -8,7 +8,7 @@ LoginModel::LoginModel():
void LoginModel::Login(ByteString username, ByteString password) void LoginModel::Login(ByteString username, ByteString password)
{ {
if (username.find('@') != username.npos) if (username.Contains("@"))
{ {
statusText = "Use your Powder Toy account to log in, not your email. If you don't have a Powder Toy account, you can create one at https://powdertoy.co.uk/Register.html"; statusText = "Use your Powder Toy account to log in, not your email. If you don't have a Powder Toy account, you can create one at https://powdertoy.co.uk/Register.html";
loginStatus = false; loginStatus = false;

View File

@ -280,10 +280,8 @@ void PreviewView::commentBoxAutoHeight()
bool PreviewView::CheckSwearing(String text) bool PreviewView::CheckSwearing(String text)
{ {
for (std::set<String>::iterator iter = swearWords.begin(), end = swearWords.end(); iter != end; iter++) for (std::set<String>::iterator iter = swearWords.begin(), end = swearWords.end(); iter != end; iter++)
{ if (text.Contains(*iter))
if (text.find(*iter) != text.npos)
return true; return true;
}
return false; return false;
} }
@ -293,7 +291,7 @@ void PreviewView::CheckComment()
return; return;
String text = addCommentBox->GetText(); String text = addCommentBox->GetText();
std::transform(text.begin(), text.end(), text.begin(), ::tolower); std::transform(text.begin(), text.end(), text.begin(), ::tolower);
if (!userIsAuthor && (text.find("stolen") != String::npos || text.find("copied") != String::npos)) if (!userIsAuthor && (text.Contains("stolen") || text.Contains("copied")))
{ {
if (!commentHelpText) if (!commentHelpText)
{ {
@ -304,7 +302,7 @@ void PreviewView::CheckComment()
commentHelpText = true; commentHelpText = true;
} }
} }
else if (userIsAuthor && text.find("vote") != text.npos) else if (userIsAuthor && text.Contains("vote"))
{ {
commentWarningLabel->SetText("Do not ask for votes"); commentWarningLabel->SetText("Do not ask for votes");
commentHelpText = true; commentHelpText = true;

View File

@ -24,8 +24,8 @@ SearchView::SearchView():
Client::Ref().AddListener(this); Client::Ref().AddListener(this);
nextButton = new ui::Button(ui::Point(WINDOWW-52, WINDOWH-18), ui::Point(50, 16), "Next " + String(1, 0xE015)); nextButton = new ui::Button(ui::Point(WINDOWW-52, WINDOWH-18), ui::Point(50, 16), String("Next ") + 0xE015);
previousButton = new ui::Button(ui::Point(2, WINDOWH-18), ui::Point(50, 16), String(1, 0xE016) + " Prev"); previousButton = new ui::Button(ui::Point(2, WINDOWH-18), ui::Point(50, 16), 0xE016 + String(" Prev"));
tagsLabel = new ui::Label(ui::Point(270, WINDOWH-18), ui::Point(WINDOWW-540, 16), "\boPopular Tags:"); tagsLabel = new ui::Label(ui::Point(270, WINDOWH-18), ui::Point(WINDOWW-540, 16), "\boPopular Tags:");
motdLabel = new ui::RichLabel(ui::Point(51, WINDOWH-18), ui::Point(WINDOWW-102, 16), Client::Ref().GetMessageOfTheDay()); motdLabel = new ui::RichLabel(ui::Point(51, WINDOWH-18), ui::Point(WINDOWW-102, 16), Client::Ref().GetMessageOfTheDay());

View File

@ -43,7 +43,7 @@ private:
{ {
free(data); free(data);
errorStream << "Server responded with Status " << status; errorStream << "Server responded with Status " << status;
notifyError("Could not download update: " + errorStream.str()); notifyError("Could not download update: " + String(errorStream.str()));
return false; return false;
} }
if (!data) if (!data)
@ -109,7 +109,7 @@ private:
return true; return true;
corrupt: corrupt:
notifyError("Downloaded update is corrupted\n" + errorStream.str()); notifyError("Downloaded update is corrupted\n" + String(errorStream.str()));
free(data); free(data);
return false; return false;
} }

View File

@ -623,7 +623,7 @@ int LuaScriptInterface::simulation_signNewIndex(lua_State *l)
if (!key.compare("text")) if (!key.compare("text"))
{ {
const char *temp = luaL_checkstring(l, 3); const char *temp = luaL_checkstring(l, 3);
String cleaned = format::CleanString(ByteString(temp).FromUtf8(), false, true, true).substr(0, 45); String cleaned = format::CleanString(ByteString(temp).FromUtf8(), false, true, true).Substr(0, 45);
if (!cleaned.empty()) if (!cleaned.empty())
luacon_sim->signs[id].text = cleaned; luacon_sim->signs[id].text = cleaned;
else else
@ -670,7 +670,7 @@ int LuaScriptInterface::simulation_newsign(lua_State *l)
if (luacon_sim->signs.size() >= MAXSIGNS) if (luacon_sim->signs.size() >= MAXSIGNS)
return lua_pushnil(l), 1; return lua_pushnil(l), 1;
String text = format::CleanString(ByteString(luaL_checkstring(l, 1)).FromUtf8(), false, true, true).substr(0, 45); String text = format::CleanString(ByteString(luaL_checkstring(l, 1)).FromUtf8(), false, true, true).Substr(0, 45);
int x = luaL_checkinteger(l, 2); int x = luaL_checkinteger(l, 2);
int y = luaL_checkinteger(l, 3); int y = luaL_checkinteger(l, 3);
int ju = luaL_optinteger(l, 4, 1); int ju = luaL_optinteger(l, 4, 1);
@ -2894,7 +2894,7 @@ int LuaScriptInterface::elements_free(lua_State * l)
return luaL_error(l, "Invalid element"); return luaL_error(l, "Invalid element");
ByteString identifier = luacon_sim->elements[id].Identifier; ByteString identifier = luacon_sim->elements[id].Identifier;
if(identifier.length()>7 && identifier.substr(0, 7) == "DEFAULT") if(identifier.BeginsWith("DEFAULT"))
return luaL_error(l, "Cannot free default elements"); return luaL_error(l, "Cannot free default elements");
luacon_sim->elements[id].Enabled = false; luacon_sim->elements[id].Enabled = false;
@ -3524,7 +3524,7 @@ int LuaScriptInterface::Command(String command)
if (command[0] == '!') if (command[0] == '!')
{ {
lastError = ""; lastError = "";
int ret = legacy->Command(command.substr(1)); int ret = legacy->Command(command.Substr(1));
lastError = legacy->GetLastError(); lastError = legacy->GetLastError();
return ret; return ret;
} }
@ -3549,7 +3549,7 @@ int LuaScriptInterface::Command(String command)
{ {
lastError = luacon_geterror(); lastError = luacon_geterror();
String err = lastError; String err = lastError;
if (err.find("near '<eof>'") != err.npos) //the idea stolen from lua-5.1.5/lua.c if (err.Contains("near '<eof>'")) //the idea stolen from lua-5.1.5/lua.c
lastError = "..."; lastError = "...";
else else
lastCode = ""; lastCode = "";
@ -3808,7 +3808,7 @@ String LuaScriptInterface::FormatCommand(String command)
{ {
if(command.size() && command[0] == '!') if(command.size() && command[0] == '!')
{ {
return "!"+legacy->FormatCommand(command.substr(1)); return "!"+legacy->FormatCommand(command.Substr(1));
} }
else else
return highlight(command); return highlight(command);

View File

@ -274,9 +274,9 @@ AnyType TPTScriptInterface::tptS_set(std::deque<String> * words)
{ {
String newString = ((StringType)value).Value(); String newString = ((StringType)value).Value();
if (newString.at(newString.length()-1) == 'C') if (newString.at(newString.length()-1) == 'C')
newValuef = atof(newString.substr(0, newString.length()-1).ToUtf8().c_str())+273.15; newValuef = atof(newString.SubstrFromEnd(1).ToUtf8().c_str())+273.15;
else if (newString.at(newString.length()-1) == 'F') else if (newString.at(newString.length()-1) == 'F')
newValuef = (atof(newString.substr(0, newString.length()-1).ToUtf8().c_str())-32.0f)*5/9+273.15f; newValuef = (atof(newString.SubstrFromEnd(1).ToUtf8().c_str())-32.0f)*5/9+273.15f;
else else
throw GeneralException("Invalid value for assignment"); throw GeneralException("Invalid value for assignment");
} }

View File

@ -41,7 +41,7 @@ String sign::getText(Simulation *sim)
{ {
int pos = splitsign(text); int pos = splitsign(text);
if (pos) if (pos)
signTextNew << text.substr(pos+1, text.length()-pos-2); signTextNew << text.Between(pos + 1, text.size() - 1);
else else
signTextNew << text; signTextNew << text;
} }

View File

@ -76,7 +76,7 @@ int Simulation::Load(int fullX, int fullY, GameSave * save, bool includePressure
// if this is a custom element, set the ID to the ID we found when comparing identifiers in the palette map // if this is a custom element, set the ID to the ID we found when comparing identifiers in the palette map
// set type to 0 if we couldn't find an element with that identifier present when loading, // set type to 0 if we couldn't find an element with that identifier present when loading,
// unless this is a default element, in which case keep the current ID, because otherwise when an element is renamed it wouldn't show up anymore in older saves // unless this is a default element, in which case keep the current ID, because otherwise when an element is renamed it wouldn't show up anymore in older saves
if (myId != 0 || pi.first.find("DEFAULT_PT_") != 0) if (myId != 0 || pi.first.BeginsWith("DEFAULT_PT_"))
partMap[pi.second] = myId; partMap[pi.second] = myId;
} }
} }