177 lines
4.8 KiB
C++
Executable File

#include "KString.h"
#include <stdarg.h>
#include "MiniCppUnit.hxx"
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// String Helper
static std::string vasprintf(const char *fmt, va_list argv) {
std::string result;
va_list argv_copy; // vsnprintf modifies argv, need copy
#ifndef va_copy
argv_copy = argv;
#else
va_copy(argv_copy, argv);
#endif
int len = vsnprintf(NULL, 0, fmt, argv_copy);
if (len > 0 && len < 255) {
// cover 90% of all calls
char str[256] = {0};
int len2 = vsnprintf(str, 255, fmt, argv);
result = str;
} else if (len > 0) {
char *str = static_cast<char *>(alloca(len + 1)); // alloca on stack, space for null-termination
int len2 = vsnprintf(str, len + 1, fmt, argv);
result = str;
}
return result;
}
static void reportWarning(const std::string &warnStr) {
if (JetBrains::underTeamcity())
gTeamCityListener.messages.messageWarning(warnStr);
else
fprintf(stderr, "%s", warnStr.c_str());
}
static void reportError(const std::string &errorStr) {
if (JetBrains::underTeamcity())
gTeamCityListener.messages.messageError(errorStr);
else
fprintf(stderr, "%s", errorStr.c_str());
}
static void reportInfo(const std::string &infoStr) {
if (JetBrains::underTeamcity())
gTeamCityListener.messages.messageNormal(infoStr);
else
fprintf(stderr, "%s", infoStr.c_str());
}
static void reportDebug(const std::string &debugStr) {
fprintf(stderr, "%s", debugStr.c_str());
}
static void report(ErrorLevel level, const std::string &Str) {
switch (level) {
case WARNLVL:
reportWarning(Str);
break;
case ERRORLVL:
reportError(Str);
break;
case INFOLVL:
reportInfo(Str);
break;
case DEBUGLVL:
reportDebug(Str);
break;
}
}
void KOutputDebug(ErrorLevel lvl, const char *fmt ...) {
va_list argList;
va_start(argList, fmt);
std::string str = vasprintf(fmt, argList);
va_end(argList);
report(lvl, str);
}
#define K_MAX(a, b) ((a>b) ? a : b)
std::string GetFileName(const std::string &thePath, bool noExtension) {
int aLastSlash = K_MAX((int) thePath.rfind('\\'), (int) thePath.rfind('/'));
if (noExtension) {
int aLastDot = (int) thePath.rfind('.');
if (aLastDot > aLastSlash)
return thePath.substr(aLastSlash + 1, aLastDot - aLastSlash - 1);
}
if (aLastSlash == -1)
return thePath;
else
return thePath.substr(aLastSlash + 1);
}
std::string GetFileDir(const std::string &thePath, bool withSlash) {
int aLastSlash = K_MAX((int) thePath.rfind(('\\')), (int) thePath.rfind(('/')));
if (aLastSlash == -1)
return ("");
else {
if (withSlash)
return thePath.substr(0, aLastSlash + 1);
else
return thePath.substr(0, aLastSlash);
}
}
std::string GetFileExt(const std::string &thePath) {
std::string::size_type idx = thePath.find_last_of('.');
if (idx != std::string::npos)
return thePath.substr(idx + 1);
return ("");
}
/**
* g_ascii_strcasecmp:
* @s1: string to compare with @s2.
* @s2: string to compare with @s1.
*
* Compare two strings, ignoring the case of ASCII characters.
*
* Unlike the BSD strcasecmp() function, this only recognizes standard
* ASCII letters and ignores the locale, treating all non-ASCII
* bytes as if they are not letters.
*
* This function should be used only on strings that are known to be
* in encodings where the bytes corresponding to ASCII letters always
* represent themselves. This includes UTF-8 and the ISO-8859-*
* charsets, but not for instance double-byte encodings like the
* Windows Codepage 932, where the trailing bytes of double-byte
* characters include all ASCII letters. If you compare two CP932
* strings using this function, you will get false matches.
*
* Return value: an integer less than, equal to, or greater than
* zero if @s1 is found, respectively, to be less than,
* to match, or to be greater than @s2.
**/
static int g_ascii_compare_caseless(const char *s1, const char *s2) {
#define TOUPPER(c) (((c) >= 'a' && (c) <= 'z') ? (c) - 'a' + 'A' : (c))
#define TOLOWER(c) (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))
#define g_return_val_if_fail(expr, val) { if (!(expr)) return (val); }
int c1, c2;
g_return_val_if_fail(s1 != NULL, 0);
g_return_val_if_fail(s2 != NULL, 0);
while (*s1 && *s2) {
c1 = (int) (unsigned char) TOLOWER(*s1);
c2 = (int) (unsigned char) TOLOWER(*s2);
if (c1 != c2)
return (c1 - c2);
s1++;
s2++;
}
return (((int) (unsigned char) *s1) - ((int) (unsigned char) *s2));
#undef g_return_val_if_fail
#undef TOUPPER
#undef TOLOWER
}
int CompareNoCase(const std::string &str1, const std::string &str2) {
return g_ascii_compare_caseless(str1.c_str(), str2.c_str());
}