void TrimLeft(XString& str) { for (XString::iterator i = str.begin();i !=str.end();++i) { if(!isspace(*i)) { str.erase(str.begin(),i); return; } } }
RString::RString(XString x) : owned(nullptr) { const RString *f = x.base(); const char *xb = &*x.begin(); const char *xe = &*x.end(); const char *fb = f ? &*f->begin() : nullptr; const char *fe = f ? &*f->end() : nullptr; if (f && xb == fb && xe == fe) *this = *f; else _assign(x.begin(), x.end()); }
inline void WBUF_STRING(uint8_t *p, size_t pos, XString s, size_t len) { char *const begin = static_cast<char *>(WBUFP(p, pos)); char *const end = begin + len; char *const mid = std::copy(s.begin(), s.end(), begin); std::fill(mid, end, '\0'); }
inline void WFIFO_STRING(int fd, size_t pos, XString s, size_t len) { char *const begin = static_cast<char *>(WFIFOP(fd, pos)); char *const end = begin + len; char *const mid = std::copy(s.begin(), s.end(), begin); std::fill(mid, end, '\0'); }
bool read_constdb(ZString filename) { io::ReadFile in(filename); if (!in.is_open()) { PRINTF("can't read %s\n"_fmt, filename); return false; } bool rv = true; AString line_; while (in.getline(line_)) { // is_comment only works for whole-line comments // that could change once the Z dependency is dropped ... LString comment = "//"_s; XString line = line_.xislice_h(std::search(line_.begin(), line_.end(), comment.begin(), comment.end())).rstrip(); if (!line) continue; // "%m[A-Za-z0-9_] %i %i" // TODO promote either qsplit() or asplit() auto _it = std::find(line.begin(), line.end(), ' '); auto name = line.xislice_h(_it); auto _rest = line.xislice_t(_it); while (_rest.startswith(' ')) _rest = _rest.xslice_t(1); auto _it2 = std::find(_rest.begin(), _rest.end(), ' '); auto val_ = _rest.xislice_h(_it2); auto type_ = _rest.xislice_t(_it2); while (type_.startswith(' ')) type_ = type_.xslice_t(1); // yes, the above actually DTRT even for underlength input int val; int type = 0; // Note for future archeaologists: this code is indented correctly if (std::find_if_not(name.begin(), name.end(), [](char c) { return ('0' <= c && c <= '9') || ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || (c == '_'); }) != name.end() || !extract(val_, &val) || (!extract(type_, &type) && type_)) { PRINTF("Bad const line: %s\n"_fmt, line_); rv = false; continue; } P<str_data_t> n = add_strp(name); n->type = type ? StringCode::PARAM : StringCode::INT; n->val = val; } return rv; }
bool makeSurePath(XString& s) { if(s.empty()) return false; std::replace(s.begin(),s.end(),'\\','/'); Trim(s); TrimLeftChar(s,'/'); if(s.empty()) return false; while('/' != *s.rbegin()) s += '/'; return !s.empty(); }
void TrimRight(XString& str) { if(str.empty()) return; for (XString::iterator i = str.end()-1;i!=str.begin();--i) { if(!isspace(*i)) { str.erase(i+1,str.end()); return; } } }
XIRef<XTimeZone> XSimpleTimeZone::FromXML(XIRef<XDomParserNode> node) { const XString utcOffsetStr = node->GetMetaData("utcOffset"); const XString dstOffsetStr = node->GetMetaData("dstOffset"); if(node->GetTagName() != "XSimpleTimeZone" || utcOffsetStr.empty() || (!verifyDigit(utcOffsetStr[0]) && utcOffsetStr[0] != '-') || count_if(utcOffsetStr.begin() + 1, utcOffsetStr.end(), verifyDigit) != (int)utcOffsetStr.size() - 1 || dstOffsetStr.empty() || (!verifyDigit(dstOffsetStr[0]) && dstOffsetStr[0] != '-') || count_if(dstOffsetStr.begin() + 1, dstOffsetStr.end(), verifyDigit) != (int)dstOffsetStr.size() - 1) { return 0; } const int utcOffset = utcOffsetStr.ToInt(); const int dstOffset = dstOffsetStr.ToInt(); return new XSimpleTimeZone(utcOffset, dstOffset); }
XIRef<XTimeZone> XSimpleTimeZone::FromISOString(const XString& isoString) { if(isoString[0] != '-' && isoString[0] != '+') X_THROW(("Invalid ISO Extended String: %s", isoString.c_str())); const int sign = isoString[0] == '-' ? -1 : 1; const XString str = isoString.substr(1); if(str.empty()) X_THROW(("Invalid ISO Extended String: %s", isoString.c_str())); const size_t colonDex = str.find(':'); XString hoursStr; XString minutesStr; if(colonDex != string::npos) { hoursStr = str.substr(0, colonDex); minutesStr = str.substr(colonDex + 1); if(minutesStr.size() != 2) X_THROW(("Invalid ISO Extended String: %s", isoString.c_str())); } else hoursStr = str; if(count_if(hoursStr.begin(), hoursStr.end(), verifyDigit) != (int)hoursStr.size() || count_if(minutesStr.begin(), minutesStr.end(), verifyDigit) != (int)minutesStr.size()) { X_THROW(("Invalid ISO Extended String: %s", isoString.c_str())); } const int hours = hoursStr.ToInt(); const int minutes = minutesStr.empty() ? 0 : minutesStr.ToInt(); return new XSimpleTimeZone(sign * (int)(convert(HOURS, MINUTES, hours) + minutes)); }
inline bool extract(XString str, HumanTimeDiff *iv) { // str is a sequence of [-+]?[0-9]+([ay]|m|[jd]|h|mn|s) // there are NO spaces here // parse by counting the number starts auto is_num = [](char c) { return c == '-' || c == '+' || ('0' <= c && c <= '9'); }; if (!str || !is_num(str.front())) return false; *iv = HumanTimeDiff{}; while (str) { auto it = std::find_if_not(str.begin(), str.end(), is_num); auto it2 = std::find_if(it, str.end(), is_num); XString number = str.xislice_h(it); XString suffix = str.xislice(it, it2); str = str.xislice_t(it2); short *ptr = nullptr; if (suffix == "y"_s || suffix == "a"_s) ptr = &iv->year; else if (suffix == "m"_s) ptr = &iv->month; else if (suffix == "j"_s || suffix == "d"_s) ptr = &iv->day; else if (suffix == "h"_s) ptr = &iv->hour; else if (suffix == "mn"_s) ptr = &iv->minute; else if (suffix == "s"_s) ptr = &iv->second; else return false; if (number.startswith('+') && !number.startswith("+-"_s)) number = number.xslice_t(1); if (*ptr || !extract(number, ptr)) return false; } return true; }
/// Return a pair of strings, {spellname, parameter} /// Parameter may be empty. static std::pair<XString, XString> magic_tokenise(XString src) { auto seeker = std::find(src.begin(), src.end(), ' '); if (seeker == src.end()) { return {src, XString()}; } else { XString rv1 = src.xislice_h(seeker); ++seeker; while (seeker != src.end() && *seeker == ' ') ++seeker; // Note: this very well could be empty XString rv2 = src.xislice_t(seeker); return {rv1, rv2}; } }
//--------------------------------------------------- // E-mail check: return 0 (not correct) or 1 (valid). //--------------------------------------------------- bool e_mail_check(XString email) { // athena limits if (email.size() < 3 || email.size() > 39) return 0; // part of RFC limits (official reference of e-mail description) XString::iterator at = std::find(email.begin(), email.end(), '@'); if (at == email.end()) return 0; XString username = email.xislice_h(at); XString hostname = email.xislice_t(at + 1); if (!username || !hostname) return 0; if (hostname.contains('@')) return 0; if (hostname.front() == '.' || hostname.back() == '.') return 0; if (hostname.contains_seq("..")) return 0; if (email.contains_any(" ;")) return 0; return email.is_print(); }
void ToUpper(XString& str) { std::transform(str.begin(),str.end(),str.begin(),toupper); }
void ToLower(XString& str) { std::transform(str.begin(),str.end(),str.begin(),tolower); }