void String::CommandLineSplit(StackArray<String> &astrResult) const { MUTEX_LOCK(str_mutex); char* sz = str_szBuffer; bool bInString = false; String strBuffer; s_char c; do { #ifdef SCRATCH_NO_UTF8 c = *sz; s_char cn = *(sz + 1); #else s_char cn; sz = (char*)utf8codepoint(sz, &c); utf8codepoint(sz, &cn); #endif if (c == '\\') { strBuffer += cn; #ifdef SCRATCH_NO_UTF8 sz++; #else sz = (char*)utf8codepoint(sz, nullptr); #endif continue; } if (bInString) { if (c == '"' && (cn == ' ' || cn == '\0')) { bInString = false; continue; } } else { if (c == '"' && strBuffer.Length() == 0) { bInString = true; continue; } if (c == ' ' && strBuffer.Length() != 0) { astrResult.Push() = strBuffer; strBuffer = ""; continue; } } strBuffer += c; } #ifdef SCRATCH_NO_UTF8 while (*(++sz) != '\0'); #else //while (*(sz = (char*)utf8codepoint(sz, nullptr)) != '\0'); while (c != 0); #endif if (strBuffer.Length() != 0) { astrResult.Push() = strBuffer; } }
int utf8len(const char *str) { int retval = 0; while (utf8codepoint(&str)) retval++; return retval; } // utf8len
int String::IndexOfLast(s_char c) const { MUTEX_LOCK(str_mutex); #ifdef SCRATCH_NO_UTF8 const char* sz = strrchr(this->str_szBuffer, c); if (sz != nullptr) { return sz - this->str_szBuffer; } return -1; #else int ct = 0; int ret = -1; void* sz = this->str_szBuffer; int cp; while (true) { sz = utf8codepoint(sz, &cp); if (cp == 0) { break; } else if (cp == c) { ret = ct; } ct++; } return ret; #endif }
int String::IndexOf(const String &strNeedle) const { MUTEX_LOCK(str_mutex); #ifdef SCRATCH_NO_UTF8 const char* sz = strstr(this->str_szBuffer, strNeedle); if (sz != nullptr) { return sz - this->str_szBuffer; } return -1; #else void* szFound = utf8str(this->str_szBuffer, strNeedle); if (szFound == nullptr) { return -1; } int ret = 0; void* sz = this->str_szBuffer; s_char codepoint; while (sz != szFound) { sz = utf8codepoint(sz, &codepoint); if (codepoint == '\0') { return -1; } ret++; } return ret; #endif }
int String::IndexOf(s_char c) const { MUTEX_LOCK(str_mutex); #ifdef SCRATCH_NO_UTF8 const char* sz = strchr(this->str_szBuffer, c); if (sz != nullptr) { return sz - this->str_szBuffer; } return -1; #else int ret = 0; void* sz = this->str_szBuffer; s_char codepoint; while (true) { sz = utf8codepoint(sz, &codepoint); if (codepoint == '\0') { return -1; } else if (codepoint == c) { return ret; } ret++; } #endif }
String String::SubString(int iStart, int iLen) const { MUTEX_LOCK(str_mutex); // Empty strings if (iStart < 0 || iLen <= 0) { return ""; } // Get the first offset #ifdef SCRATCH_NO_UTF8 String strRet(this->str_szBuffer + iStart); #else void* subFirst = this->str_szBuffer; s_char codepoint; do { subFirst = utf8codepoint(subFirst, &codepoint); } while (--iStart > 0 && codepoint != '\0'); String strRet((const char*)subFirst); #endif // Check for stupid developers #ifdef SCRATCH_NO_UTF8 if ((uint32_t)iLen > strlen(strRet)) { return strRet; } #else if ((uint32_t)iLen > utf8len(strRet)) { return strRet; } #endif // Then set the null terminator at the length the user wants #ifdef SCRATCH_NO_UTF8 strRet.str_szBuffer[iLen] = '\0'; #else void* sz = strRet.str_szBuffer; do { sz = utf8codepoint(sz, &codepoint); } while (--iLen > 0 && codepoint != '\0'); *(char*)sz = '\0'; #endif // Return return strRet; }
String String::SubString(int iStart) const { MUTEX_LOCK(str_mutex); #ifdef SCRATCH_NO_UTF8 return String(this->str_szBuffer + iStart); #else void* ret = this->str_szBuffer; s_char codepoint; do { ret = utf8codepoint(ret, &codepoint); } while (--iStart > 0 && codepoint != '\0'); return (char*)ret; #endif }
const s_char String::operator[](int iIndex) { MUTEX_LOCK(str_mutex); #ifdef SCRATCH_NO_UTF8 return this->str_szBuffer[iIndex]; #else void* sz = this->str_szBuffer; s_char codepoint; do { sz = utf8codepoint(sz, &codepoint); ASSERT(codepoint != '\0'); } while (--iIndex > 0); return codepoint; #endif }
int String::IndexOfLast(const String &strNeedle) const { MUTEX_LOCK(str_mutex); #ifdef SCRATCH_NO_UTF8 const char* sz = strrstr(this->str_szBuffer, strNeedle); if (sz != nullptr) { return sz - this->str_szBuffer; } return -1; #else if (strNeedle.Length() == 0) { return -1; } int len = strNeedle.Length(); int ret = -1; int index = 0; int findStart = -1; int findIndex = 0; int cp; void* p = this->str_szBuffer; while (true) { p = utf8codepoint(p, &cp); if (cp == 0) { break; } if (strNeedle[findIndex] == cp) { if (findIndex == 0) { findStart = index; } findIndex++; if (findIndex == len) { ret = findStart; findIndex = 0; } } index++; } return ret; #endif }
String String::InternalTrim(bool bLeft, bool bRight, s_char c) const { // Copy ourselves into a new buffer #ifdef SCRATCH_NO_UTF8 size_t bytes = strlen(this->str_szBuffer); #else size_t bytes = utf8size(this->str_szBuffer) - 1; #endif char* szBuffer = new char[bytes + 1]; #ifdef SCRATCH_NO_UTF8 #if WINDOWS strcpy_s(szBuffer, bytes + 1, this->str_szBuffer); #else strcpy(szBuffer, this->str_szBuffer); #endif #else utf8ncpy(szBuffer, this->str_szBuffer, bytes); #endif // Keep a pointer to the current offset char* szOffset = szBuffer; if (bLeft) { #ifdef SCRATCH_NO_UTF8 // While there's a space, keep incrementing the offset char lc = *szOffset; while (lc == c && lc != '\0') { // This way, we'll trim all the spaces on the left lc = *(++szOffset); } #else // Find the space int codepoint; void* v = utf8codepoint(szOffset, &codepoint); while (codepoint == c && codepoint != '\0') { szOffset = (char*)v; v = utf8codepoint(szOffset, &codepoint); } #endif } if (bRight) { // Loop from right to left in the string #ifdef SCRATCH_NO_UTF8 for (int i = strlen(szOffset) - 1; i >= 0; i--) { // When we find a space if (szOffset[i] == c) { // Put the null terminator here to trim the right part szOffset[i] = '\0'; } else { // Something other than a space, we can stop now break; } } #else int codepoint; char* lastValid = szOffset; for (void* v = utf8codepoint(szOffset, &codepoint); ; v = utf8codepoint(v, &codepoint)) { if (codepoint == '\0') { break; } if (codepoint != c) { lastValid = (char*)v; } } *(char*)lastValid = '\0'; #endif } // Return String ret(szOffset); delete[] szBuffer; return ret; }