// StringUtils.cpp // Implements the various string helper functions: #include "Globals.h" AString & AppendVPrintf(AString & str, const char *format, va_list args) { ASSERT(format != NULL); char buffer[2048]; size_t len; #ifdef _MSC_VER // MS CRT provides secure printf that doesn't behave like in the C99 standard if ((len = _vsnprintf_s(buffer, ARRAYCOUNT(buffer), _TRUNCATE, format, args)) != -1) #else // _MSC_VER if ((len = vsnprintf(buffer, ARRAYCOUNT(buffer), format, args)) < ARRAYCOUNT(buffer)) #endif // else _MSC_VER { // The result did fit into the static buffer str.append(buffer, len); return str; } // The result did not fit into the static buffer #ifdef _MSC_VER // for MS CRT, we need to calculate the result length len = _vscprintf(format, args); if (len == -1) { return str; } #endif // _MSC_VER // Allocate a buffer and printf into it: std::auto_ptr tmp(new char[len + 1]); ASSERT(tmp.get() != NULL); // Why not alloced? Is the length reasonable? if (tmp.get() == NULL) { throw std::bad_alloc(); } #ifdef _MSC_VER if ((len = vsprintf_s(tmp.get(), len + 1, format, args)) != -1) { str.append(tmp.get(), len); } ASSERT(len != -1); #else // _MSC_VER vsnprintf(tmp.get(), len + 1, format, args); str.append(tmp.get(), len); #endif // else _MSC_VER return str; } AString & Printf(AString & str, const char *format, ...) { str.clear(); va_list args; va_start(args, format); std::string &retval = AppendVPrintf(str, format, args); va_end(args); return retval; } AString & AppendPrintf(AString &str, const char *format, ...) { va_list args; va_start(args, format); std::string &retval = AppendVPrintf(str, format, args); va_end(args); return retval; } AStringVector StringSplit(const AString & str, const AString & delim) { AStringVector results; size_t cutAt = 0; size_t Prev = 0; while ((cutAt = str.find_first_of(delim, Prev)) != str.npos) { if (cutAt > 0) { results.push_back(str.substr(Prev, cutAt - Prev)); } Prev = cutAt + delim.length(); } if (Prev < str.length()) { results.push_back(str.substr(Prev)); } return results; } AString & StrToUpper(AString & s) { AString::iterator i = s.begin(); AString::iterator end = s.end(); while (i != end) { *i = (char)toupper(*i); ++i; } return s; } int NoCaseCompare(const AString & s1, const AString & s2) { #ifdef _MSC_VER // MSVC has stricmp that compares case-insensitive: return _stricmp(s1.c_str(), s2.c_str()); #else // Do it the hard way: AString s1Copy(s1); AString s2Copy(s2); return StrToUpper(s1Copy).compare(StrToUpper(s2Copy)); #endif // else _MSC_VER }