// // Lol Engine // // Copyright © 2010—2018 Sam Hocevar // © 2013—2015 Benjamin “Touky” Huet // // Lol Engine is free software. It comes without any warranty, to // the extent permitted by applicable law. You can redistribute it // and/or modify it under the terms of the Do What the Fuck You Want // to Public License, Version 2, as published by the WTFPL Task Force. // See http://www.wtfpl.net/ for more details. // #pragma once // // The string tools // ---------------- // Contains some utilities to work with std::string objects. // #include namespace lol { /* Split a string along a single separator */ array split(std::string const &s, char sep = '\n'); /* Split a string along multiple separators */ array split(std::string const &s, std::string const &seps); /* Check whether a string starts or ends with a given substring */ bool starts_with(std::string const &s, std::string const &prefix); bool ends_with(std::string const &s, std::string const &suffix); /* Convert a string to lowercase or uppercase */ std::string tolower(std::string const &s); std::string toupper(std::string const &s); /* Format a string, printf-style */ std::string format(char const *format, ...) LOL_ATTR_FORMAT(1, 2); std::string vformat(char const *format, va_list ap); } /* namespace lol */ // // The deprecated String class // --------------------------- // A very simple String class, based on Array. The most interesting // thing in there was LOL_ATTR_NODISCARD but apart from that there was // no real point in using our own class. Phase this out. // #include #include #include #include namespace lol { class LOL_ATTR_NODISCARD String : protected array { private: typedef array super; public: inline String() : super() { push('\0'); } inline String(char const *str) : super() { using namespace std; ASSERT(str); resize((int)strlen(str)); memcpy(&(*this)[0], str, count() + 1); } inline String(char const *str, int item_count) : super() { using namespace std; ASSERT(str); resize(item_count); memcpy(&(*this)[0], str, item_count); ((super &)*this)[item_count] = '\0'; } /* Legacy constructor for std::string */ inline String(std::string const &s) : String(s.c_str()) { } inline String(String const &s) : super((super const &)s) { } inline char &operator [](int n) { /* Allow n == count() because we might have reasonable reasons * to access that hidden null character. We cast to unsigned so * as to avoid a harmless message from the GCC optimiser. */ ASSERT(n >= 0); ASSERT((unsigned)n <= (unsigned)count()); return ((super &)*this)[n]; } inline char const &operator [](int n) const { ASSERT(n >= 0); ASSERT((unsigned)n <= (unsigned)count()); return ((super const &)*this)[n]; } inline char &last() { ASSERT(count() > 0); return (*this)[count() - 1]; } inline char const &last() const { ASSERT(count() > 0); return (*this)[count() - 1]; } inline int count() const { return ((super const &)*this).count() - 1; } /* Return a C string */ inline char const *C() const { return &(*this)[0]; } /* Non-const version; make sure to not overflow the internal array */ inline char *C() { return &(*this)[0]; } /* Does not initialise the newly allocated characters */ void resize(int item_count) { ASSERT(item_count >= 0); ((super &)*this).resize(item_count + 1); ((super &)*this).last() = '\0'; } String sub(int start, int item_count = -1) const { ASSERT(start >= 0); if (start >= count()) return String(); if (item_count < 0 || item_count >= count() - start) item_count = count() - start; return String(&(*this)[start], item_count); } int replace(char const old_token, char const new_token, bool all_occurrences = false) { using namespace std; int res = 0; char *tmp = NULL; while ((tmp = strrchr(C(), old_token))) { *tmp = new_token; res++; if (!all_occurrences) break; } return res; } inline String operator +(String const &s) const { String ret(*this); return ret += s; } inline String operator +(char c) const { String ret(*this); return ret += c; } inline String& operator +=(String const &s) { using namespace std; int old_count = count(); resize(count() + s.count()); memcpy(&(*this)[old_count], &s[0], count() - old_count); return *this; } inline String& operator +=(char c) { ((super &)*this).last() = c; ((super &)*this).push('\0'); return *this; } inline bool operator ==(String const &s) const { using namespace std; return count() == s.count() && memcmp(C(), s.C(), count()) == 0; } inline bool operator !=(String const &s) const { return !(*this == s); } inline bool operator ==(char const* sz) const { /* We parse the C string twice because of strlen + memcmp * but it's probably still faster than doing it by hand. */ using namespace std; int sz_len = (int)strlen(sz); return count() == sz_len && memcmp(C(), sz, sz_len) == 0; } inline bool operator !=(char const* sz) const { return !(*this == sz); } inline bool operator <(String const & s) const { using namespace std; int res = memcmp(C(), s.C(), count() < s.count() ? count() : s.count()); if (!res) return count() < s.count(); return res < 0; } }; inline String operator +(char c, String const &s) { return String() + c + s; } inline String operator +(char const *sz, String const &s) { return String(sz) + s; } inline bool operator ==(char const* sz, String const &s) { return s == sz; } inline bool operator !=(char const* sz, String const &s) { return s != sz; } } /* namespace lol */