📄 util.cpp
字号:
} else {
if(str[1] == 0 ||
!((((unsigned char)str[1]) & ~0x3f) == 0x80))
{
str++;
return 0;
}
c = ((wchar_t)(unsigned char)str[0] & 0x1f) << 6 |
((wchar_t)(unsigned char)str[1] & 0x3f);
str += 2;
}
} else {
str++;
return 0;
}
} else {
wchar_t c = Text::asciiToLower((char)str[0]);
str++;
return c;
}
return Text::toLower(c);
}
string::size_type Util::findSubString(const string& aString, const string& aSubString, string::size_type start) throw() {
if(aString.length() < start)
return (string::size_type)string::npos;
if(aString.length() - start < aSubString.length())
return (string::size_type)string::npos;
if(aSubString.empty())
return 0;
// Hm, should start measure in characters or in bytes? bytes for now...
const u_int8_t* tx = (const u_int8_t*)aString.c_str() + start;
const u_int8_t* px = (const u_int8_t*)aSubString.c_str();
const u_int8_t* end = tx + aString.length() - start - aSubString.length() + 1;
wchar_t wp = utf8ToLC(px);
while(tx < end) {
const u_int8_t* otx = tx;
if(wp == utf8ToLC(tx)) {
const u_int8_t* px2 = px;
const u_int8_t* tx2 = tx;
for(;;) {
if(*px2 == 0)
return otx - (u_int8_t*)aString.c_str();
if(utf8ToLC(px2) != utf8ToLC(tx2))
break;
}
}
}
return (string::size_type)string::npos;
}
int Util::stricmp(const char* a, const char* b) {
while(*a) {
wchar_t ca = 0, cb = 0;
int na = Text::utf8ToWc(a, ca);
int nb = Text::utf8ToWc(b, cb);
ca = Text::toLower(ca);
cb = Text::toLower(cb);
if(ca != cb) {
return (int)ca - (int)cb;
}
a+= na < 0 ? 1 : na;
b+= nb < 0 ? 1 : nb;
}
wchar_t ca = 0, cb = 0;
Text::utf8ToWc(a, ca);
Text::utf8ToWc(b, cb);
return (int)Text::toLower(ca) - (int)Text::toLower(cb);
}
int Util::strnicmp(const char* a, const char* b, size_t n) {
const char* end = a + n;
while(*a && a < end) {
wchar_t ca = 0, cb = 0;
int na = Text::utf8ToWc(a, ca);
int nb = Text::utf8ToWc(b, cb);
ca = Text::toLower(ca);
cb = Text::toLower(cb);
if(ca != cb) {
return (int)ca - (int)cb;
}
a+= na < 0 ? 1 : na;
b+= nb < 0 ? 1 : nb;
}
wchar_t ca = 0, cb = 0;
Text::utf8ToWc(a, ca);
Text::utf8ToWc(b, cb);
return (a >= end) ? 0 : ((int)Text::toLower(ca) - (int)Text::toLower(cb));
}
string Util::encodeURI(const string& aString, bool reverse) {
// reference: rfc2396
string tmp = aString;
if(reverse) {
string::size_type idx;
for(idx = 0; idx < tmp.length(); ++idx) {
if(tmp.length() > idx + 2 && tmp[idx] == '%' && isxdigit(tmp[idx+1]) && isxdigit(tmp[idx+2])) {
tmp[idx] = fromHexEscape(tmp.substr(idx+1,2));
tmp.erase(idx+1, 2);
} else { // reference: rfc1630, magnet-uri draft
if(tmp[idx] == '+')
tmp[idx] = ' ';
}
}
} else {
const string disallowed = ";/?:@&=+$," // reserved
"<>#%\" " // delimiters
"{}|\\^[]`"; // unwise
string::size_type idx, loc;
for(idx = 0; idx < tmp.length(); ++idx) {
if(tmp[idx] == ' ') {
tmp[idx] = '+';
} else {
if(tmp[idx] <= 0x1F || tmp[idx] >= 0x7f || (loc = disallowed.find_first_of(tmp[idx])) != string::npos) {
tmp.replace(idx, 1, toHexEscape(tmp[idx]));
idx+=2;
}
}
}
}
return tmp;
}
/**
* This function takes a string and a set of parameters and transforms them according to
* a simple formatting rule, similar to strftime. In the message, every parameter should be
* represented by %[name]. It will then be replaced by the corresponding item in
* the params stringmap. After that, the string is passed through strftime with the current
* date/time and then finally written to the log file. If the parameter is not present at all,
* it is removed from the string completely...
*/
string Util::formatParams(const string& msg, StringMap& params) {
string result = msg;
string::size_type i, j, k;
i = 0;
while (( j = result.find("%[", i)) != string::npos) {
if( (result.size() < j + 2) || ((k = result.find(']', j + 2)) == string::npos) ) {
break;
}
string name = result.substr(j + 2, k - j - 2);
StringMapIter smi = params.find(name);
if(smi == params.end()) {
result.erase(j, k-j + 1);
i = j;
} else {
if(smi->second.find('%') != string::npos) {
string tmp = smi->second; // replace all % in params with %% for strftime
string::size_type m = 0;
while(( m = tmp.find('%', m)) != string::npos) {
tmp.replace(m, 1, "%%");
m+=2;
}
result.replace(j, k-j + 1, tmp);
i = j + tmp.size();
} else {
result.replace(j, k-j + 1, smi->second);
i = j + smi->second.size();
}
}
}
result = formatTime(result, time(NULL));
return result;
}
/** Fix for wide formatting bug in wcsftime in the ms c lib for multibyte encodings of unicode in singlebyte locales */
string fixedftime(const string& format, struct tm* t) {
string ret = format;
const char codes[] = "aAbBcdHIjmMpSUwWxXyYzZ%";
char tmp[4];
tmp[0] = '%';
tmp[1] = tmp[2] = tmp[3] = 0;
StringMap sm;
AutoArray<char> buf(1024);
for(size_t i = 0; i < sizeof(codes); ++i) {
tmp[1] = codes[i];
tmp[2] = 0;
strftime(buf, 1024-1, tmp, t);
sm[tmp] = buf;
tmp[1] = '#';
tmp[2] = codes[i];
strftime(buf, 1024-1, tmp, t);
sm[tmp] = buf;
}
for(StringMapIter i = sm.begin(); i != sm.end(); ++i) {
for(string::size_type j = ret.find(i->first); j != string::npos; j = ret.find(i->first, j)) {
ret.replace(j, i->first.length(), i->second);
j += i->second.length() - i->first.length();
}
}
return ret;
}
string Util::formatTime(const string &msg, const time_t t) {
if (!msg.empty()) {
size_t bufsize = msg.size() + 256;
struct tm* loc = localtime(&t);
if(!loc) {
return Util::emptyString;
}
#if _WIN32
AutoArray<TCHAR> buf(bufsize);
if(!_tcsftime(buf, bufsize-1, Text::toT(msg).c_str(), loc)) {
return fixedftime(msg, loc);
}
return Text::fromT(tstring(buf));
#else
// will this give wide representations for %a and %A?
// surely win32 can't have a leg up on linux/unixen in this area. - Todd
AutoArray<char> buf(bufsize);
while(!strftime(buf, bufsize-1, msg.c_str(), loc)) {
bufsize+=64;
buf = new char[bufsize];
}
return string(buf);
#endif
}
return Util::emptyString;
}
/* Below is a high-speed random number generator with much
better granularity than the CRT one in msvc...(no, I didn't
write it...see copyright) */
/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura.
Any feedback is very welcome. For any question, comments,
see http://www.math.keio.ac.jp/matumoto/emt.html or email
matumoto@math.keio.ac.jp */
/* Period parameters */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0df /* constant vector a */
#define UPPER_MASK 0x80000000 /* most significant w-r bits */
#define LOWER_MASK 0x7fffffff /* least significant r bits */
/* Tempering parameters */
#define TEMPERING_MASK_B 0x9d2c5680
#define TEMPERING_MASK_C 0xefc60000
#define TEMPERING_SHIFT_U(y) (y >> 11)
#define TEMPERING_SHIFT_S(y) (y << 7)
#define TEMPERING_SHIFT_T(y) (y << 15)
#define TEMPERING_SHIFT_L(y) (y >> 18)
static unsigned long mt[N]; /* the array for the state vector */
static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
/* initializing the array with a NONZERO seed */
static void sgenrand(unsigned long seed) {
/* setting initial seeds to mt[N] using */
/* the generator Line 25 of Table 1 in */
/* [KNUTH 1981, The Art of Computer Programming */
/* Vol. 2 (2nd Ed.), pp102] */
mt[0]= seed & 0xffffffff;
for (mti=1; mti<N; mti++)
mt[mti] = (69069 * mt[mti-1]) & 0xffffffff;
}
u_int32_t Util::rand() {
unsigned long y;
static unsigned long mag01[2]={0x0, MATRIX_A};
/* mag01[x] = x * MATRIX_A for x=0,1 */
if (mti >= N) { /* generate N words at one time */
int kk;
if (mti == N+1) /* if sgenrand() has not been called, */
sgenrand(4357); /* a default initial seed is used */
for (kk=0;kk<N-M;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
}
for (;kk<N-1;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
}
y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
mti = 0;
}
y = mt[mti++];
y ^= TEMPERING_SHIFT_U(y);
y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
y ^= TEMPERING_SHIFT_L(y);
return y;
}
string Util::getOsVersion() {
#ifdef _WIN32
string os;
OSVERSIONINFOEX ver;
memset(&ver, 0, sizeof(OSVERSIONINFOEX));
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if(!GetVersionEx((OSVERSIONINFO*)&ver)) {
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if(!GetVersionEx((OSVERSIONINFO*)&ver)) {
os = "Windows (version unknown)";
}
}
if(os.empty()) {
if(ver.dwPlatformId != VER_PLATFORM_WIN32_NT) {
os = "Win9x/ME/Junk";
} else if(ver.dwMajorVersion == 4) {
os = "WinNT4";
} else if(ver.dwMajorVersion == 5) {
if(ver.dwMinorVersion == 0) {
os = "Win2000";
} else if(ver.dwMinorVersion == 1) {
os = "WinXP";
} else if(ver.dwMinorVersion == 2) {
os = "Win2003";
} else {
os = "Unknown WinNT5";
}
if(ver.wProductType & VER_NT_WORKSTATION)
os += " Pro";
else if(ver.wProductType & VER_NT_SERVER)
os += " Server";
else if(ver.wProductType & VER_NT_DOMAIN_CONTROLLER)
os += " DC";
}
if(ver.wServicePackMajor != 0) {
os += "SP";
os += Util::toString(ver.wServicePackMajor);
if(ver.wServicePackMinor != 0) {
os += '.';
os += Util::toString(ver.wServicePackMinor);
}
}
}
return os;
#else // _WIN32
utsname n;
if(uname(&n) != 0) {
return "unix (unknown version)";
}
return string(n.sysname) + " " + string(n.release) + " (" + string(n.machine) + ")";
#endif // _WIN32
}
/* getIpCountry
This function returns the country(Abbreviation) of an ip
for exemple: it returns "PT", whitch standards for "Portugal"
more info: http://www.maxmind.com/app/csv
*/
string Util::getIpCountry (string IP) {
if (BOOLSETTING(GET_USER_COUNTRY)) {
dcassert(count(IP.begin(), IP.end(), '.') == 3);
//e.g IP 23.24.25.26 : w=23, x=24, y=25, z=26
string::size_type a = IP.find('.');
string::size_type b = IP.find('.', a+1);
string::size_type c = IP.find('.', b+2);
u_int32_t ipnum = (Util::toUInt32(IP.c_str()) << 24) |
(Util::toUInt32(IP.c_str() + a + 1) << 16) |
(Util::toUInt32(IP.c_str() + b + 1) << 8) |
(Util::toUInt32(IP.c_str() + c + 1) );
CountryIter i = countries.lower_bound(ipnum);
if(i != countries.end()) {
return string((char*)&(i->second), 2);
}
}
return Util::emptyString; //if doesn't returned anything already, something is wrong...
}
string Util::toDOS(const string& tmp) {
if(tmp.empty())
return Util::emptyString;
string tmp2(tmp);
if(tmp2[0] == '\r' && (tmp2.size() == 1 || tmp2[1] != '\n')) {
tmp2.insert(1, "\n");
}
for(string::size_type i = 1; i < tmp2.size() - 1; ++i) {
if(tmp2[i] == '\r' && tmp2[i+1] != '\n') {
// Mac ending
tmp2.insert(i+1, "\n");
i++;
} else if(tmp2[i] == '\n' && tmp2[i-1] != '\r') {
// Unix encoding
tmp2.insert(i, "\r");
i++;
}
}
return tmp2;
}
/**
* @file
* $Id: Util.cpp,v 1.83 2005/03/03 11:58:30 arnetheduck Exp $
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -