#ifndef SERVER_UTIL_H
#define SERVER_UTIL_H
#include <string>
#include <sstream>
#include <vector>
namespace utils
{
//-----------------------------------------------------------------------------
template <int iCanBeNonZero>
class CStaticAssert
{
public:
};
template <>
class CStaticAssert<0>
{
public:
CStaticAssert()
{
}
virtual void Error()=0;
};
//-----------------------------------------------------------------------------
template<class ContainerType>
typename ContainerType::pointer GetBeginOf(ContainerType & container)
{
if (container.empty())
return 0;
return &container.front();
}
template<class ContainerType>
typename ContainerType::const_pointer GetBeginOf(const ContainerType & container)
{
if (container.empty())
return 0;
return &container.front();
}
//------------------------------------------------------------------------------------------------
template<class charType>
struct builder
{
typedef std::basic_stringstream<charType> used_stringstream;
typedef std::basic_string<charType> used_string;
private:
used_stringstream stream;
builder(const builder&);
builder& operator = (const builder&);
public:
operator used_string() const
{
return stream.str();
}
template<class T1>
builder(T1 p1)
{
stream << p1;
}
template<class T1, class T2>
builder(T1 p1, T2 p2)
{
stream << p1 << p2;
}
template<class T1, class T2, class T3>
builder(T1 p1, T2 p2, T3 p3)
{
stream << p1 << p2 << p3;
}
template<class T1, class T2, class T3, class T4>
builder(T1 p1, T2 p2, T3 p3, T4 p4)
{
stream << p1 << p2 << p3 << p4;
}
template<class T1, class T2, class T3, class T4, class T5>
builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
{
stream << p1 << p2 << p3 << p4 << p5;
}
template<class T1, class T2, class T3, class T4, class T5, class T6>
builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6)
{
stream << p1 << p2 << p3 << p4 << p5 << p6;
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7>
builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7)
{
stream << p1 << p2 << p3 << p4 << p5 << p6 << p7;
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8)
{
stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8;
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9)
{
stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9;
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10>
builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10)
{
stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9 << p10;
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11>
builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11)
{
stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9 << p10 << p11;
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12>
builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12)
{
stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9 << p10 << p11 << p12;
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13>
builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13)
{
stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9 << p10 << p11 << p12 << p13;
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14>
builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14)
{
stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9 << p10 << p11 << p12 << p13 << p14;
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15>
builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15)
{
stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9 << p10 << p11 << p12 << p13 << p14 << p15;
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15, class T16>
builder(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15, T16 p16)
{
stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9 << p10 << p11 << p12 << p13 << p14 << p15 << p16;
}
template<class T1>
static used_string
build(T1 p1)
{
return (used_string)builder(p1);
}
template<class T1, class T2>
static used_string
build(T1 p1, T2 p2)
{
return (used_string)builder(p1, p2);
}
template<class T1, class T2, class T3>
static used_string
build(T1 p1, T2 p2, T3 p3)
{
return (used_string)builder(p1, p2, p3);
}
template<class T1, class T2, class T3, class T4>
static used_string
build(T1 p1, T2 p2, T3 p3, T4 p4)
{
return (used_string)builder(p1, p2, p3, p4);
}
template<class T1, class T2, class T3, class T4, class T5>
static used_string
build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
{
return (used_string)builder(p1, p2, p3, p4, p5);
}
template<class T1, class T2, class T3, class T4, class T5, class T6>
static used_string
build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6)
{
return (used_string)builder(p1, p2, p3, p4, p5, p6);
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7>
static used_string
build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7)
{
return (used_string)builder(p1, p2, p3, p4, p5, p6, p7);
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
static used_string
build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8)
{
return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8);
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
static used_string
build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9)
{
return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8, p9);
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10>
static used_string
build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10)
{
return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11>
static used_string
build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11)
{
return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12>
static used_string
build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12)
{
return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13>
static used_string
build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13)
{
return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13);
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14>
static used_string
build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14)
{
return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14);
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15>
static used_string
build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15)
{
return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15);
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15, class T16>
static used_string
build(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15, T16 p16)
{
return (used_string)builder(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16);
}
};
typedef builder<char> strBuilder;
typedef builder<wchar_t> strBuilderW;
//-----------------------------------------------------------------------------
template<class wcharVectorType>
inline void char2wstr(const char * str, size_t strSize, wcharVectorType * res, UINT cpId = CP_ACP)
{
if(!strSize)
return;
res->resize(strSize + 1);//it is enough in 99.99%
while(1)
{
int size = MultiByteToWideChar(cpId, 0, str, (int)strSize, &res->front(), (int)res->size());
if(size)
{
res->resize(size + 1);
return;
}
DWORD error = ::GetLastError();
if(error != ERROR_INSUFFICIENT_BUFFER)
return;
size = MultiByteToWideChar(cpId, 0, str, (int)strSize, 0, 0);
if(!size)
return;
res->resize(size + 1);
}
}
//-----------------------------------------------------------------------------
inline void wchar2str(const wchar_t * str, size_t strSize, std::vector<char> * res, UINT cpId = CP_ACP)
{
if(!strSize)
return;
res->resize(strSize + 1);//it is enough in 99%
while(1)
{
int size = WideCharToMultiByte(cpId, 0, str, (int)strSize, &(*res)[0], (int)res->size(), 0, 0);
if(size)
{
res->resize(size + 1);
return;
}
DWORD error = ::GetLastError();
if(error != ERROR_INSUFFICIENT_BUFFER)
return;
size = WideCharToMultiByte(cpId, 0, str, (int)strSize, 0, 0, 0, 0);
if(!size)
return;
res->resize(size + 1);
}
}
//-----------------------------------------------------------------------------
inline std::string wstring2string(const std::wstring &from)
{
std::vector<char> res;
wchar2str(from.c_str(), from.size(), &res);
return res.empty()?"":&res[0];
}
inline std::wstring string2wstring(const std::string &from)
{
std::vector<wchar_t> res;
char2wstr(from.c_str(), from.size(), &res);
return res.empty()?L"":&res[0];
}
//-----------------------------------------------------------------------------
// convert
template<class ToType, class FromType>
struct convert
{
};
// trivials
template<>
struct convert<int, int>
{
static int from(int value)
{
return value;
}
};
template<>
struct convert<long, long>
{
static long from(long value)
{
return value;
}
};
template<>
struct convert<long long, long long>
{
static long long from(long long value)
{
return value;
}
};
// trivials
template<>
struct convert<unsigned int, unsigned int>
{
static unsigned int from(unsigned int value)
{
return value;
}
};
template<>
struct convert<unsigned long, unsigned long>
{
static unsigned long from(unsigned long value)
{
return value;
}
};
template<>
struct convert<unsigned long long, unsigned long long>
{
static unsigned long long from(unsigned long long value)
{
return value;
}
};
inline size_t longlong2size_t(long long val)
{
if(val > ULONG_MAX || val < 0)
throw std::exception("Cannot cast.");
return static_cast<size_t>(val);
}
inline size_t ulonglong2size_t(unsigned long long val)
{
if(val > ULONG_MAX)
throw std::exception("Cannot cast.");
return static_cast<size_t>(val);
}
inline long long ulonglong2longlong(unsigned long long val)
{
if(val > LLONG_MAX)
throw std::exception("Cannot cast.");
return static_cast<long long>(val);
}
// non trivials
template<>
struct convert<size_t, long long>
{
static size_t from(long long value)
{
return longlong2size_t(value);
}
};
template<>
struct convert<size_t, unsigned long long>
{
static size_t from(unsigned long long value)
{
return ulonglong2size_t(value);
}
};
template<>
struct convert<long long, unsigned long long>
{
static long long from(unsigned long long value)
{
return ulonglong2longlong(value);
}
};
// from size_t to dword
template<>
struct convert<unsigned long, size_t>
{
static unsigned long from(size_t value)
{
if (value <= ULONG_MAX)
return (unsigned long)value;
throw std::exception("Cannot cast");
}
};
template<>
struct convert<long, size_t>
{
static long from(size_t value)
{
if (value <= LONG_MAX)
return (long)value;
throw std::exception("Cannot cast");
}
};
template<>
struct convert<int, size_t>
{
static int from(size_t value)
{
if (value <= INT_MAX)
return (int)value;
throw std::exception("Cannot cast");
}
};
template<>
struct convert<unsigned char, unsigned long>
{
static unsigned char from(unsigned long value)
{
if (value > UCHAR_MAX)
throw std::exception("Cannot cast");
return (unsigned char)(value);
}
};
//-----------------------------------------------------------------------------
inline void FromHexString(const std::wstring & str, char * pBegin, size_t size)
{
volatile utils::CStaticAssert<sizeof(unsigned char)==sizeof(char)> char_assert; &char_assert;
size_t iCurrent = 0;
size_t stringSize = str.size();
if (!stringSize)
return;
if (stringSize%2)
throw std::exception("FromHexString.IncorrectInputSize");
char * pEnd = pBegin + size;
while(1)
{
if (iCurrent >= stringSize-1)
break;
if (pBegin >= pEnd)
throw std::exception("BufferTooSmall");
wchar_t buff[] = {str[iCurrent], str[iCurrent+1], 0};
wchar_t * pEnd = 0;
unsigned char ch = utils::convert<unsigned char, unsigned long>::from(wcstoul(buff, &pEnd, 16));
if ((buff + (sizeof(buff)/sizeof(buff[0])) -1) != pEnd)
throw std::exception("InvalidBuffer");
(unsigned char&)(*pBegin) = ch;
++pBegin;
iCurrent+=2;
}
}
inline void FromHexString(const std::wstring & str, std::vector<char> * pVec)
{
pVec->clear();
if (str.empty())
return;
pVec->resize(str.size()/2);
FromHexString(str, utils::GetBeginOf(*pVec), pVec->size());
}
//-----------------------------------------------------------------------------
// CustomSymbol
//------------------------------------------------------------------------------------------------
template<typename char_type, char symbol>
struct CustomSymbol
{
};
template<char symbol>
struct CustomSymbol<char, symbol>
{
static const char sym = symbol;
};
template<char symbol>
struct CustomSymbol<wchar_t, symbol>
{
static const wchar_t sym = (wchar_t)(unsigned char)symbol;
};
//------------------------------------------------------------------------------------------------
template<class charType>
inline bool isHexNumber(charType ch)
{
return ((ch >= CustomSymbol<charType, '0'>::sym && ch <= CustomSymbol<charType, '9'>::sym)
|| (ch >= CustomSymbol<charType, 'A'>::sym && ch <= CustomSymbol<charType, 'F'>::sym)
|| (ch >= CustomSymbol<charType, 'a'>::sym && ch <= CustomSymbol<charType, 'f'>::sym));
}
template<class strType>
inline bool isHexNumberStr(const strType &str)
{
strType::size_type len = str.length();
for (unsigned int i=0; i<len; ++i)
{
if(!isHexNumber(str[i]))
return false;
}
if (len)
return true;
return false;
}
//-----------------------------------------------------------------------------
inline std::string replace_all
( const std::string& src
, const std::string& match
, const std::string& str
)
{
std::string s = src;
for( std::string::size_type pos = 0;;)
{
pos = s.find( match, pos);
if( std::string::npos == pos) break;
s = s.replace( s.begin() + pos, s.begin() + pos + match.size(), str);
pos += str.size();
}
return s;
}
//-----------------------------------------------------------------------------
template<class ItBegin, class ItEnd, class ItOut>
inline void ToUpperCaseA(ItBegin itBegin, // in
ItEnd itEnd, // in
ItOut itOut) // out
{
std::vector<char> temp(itBegin, itEnd);
DWORD dwSize = (DWORD)(itEnd - itBegin);
if (CharUpperBuffA( &temp.front(), dwSize)!=dwSize)
throw std::exception("Cannot convert string");
std::copy(&temp.front(), &temp.front() + dwSize, itOut);
}
template<class ItBegin, class ItEnd, class ItOut>
inline void ToUpperCaseW(ItBegin itBegin, // in
ItEnd itEnd, // in
ItOut itOut) // out
{
std::vector<wchar_t> temp(itBegin, itEnd);
DWORD dwSize = (DWORD)(itEnd - itBegin);
if (CharUpperBuffW( &temp.front(), dwSize)!=dwSize)
throw std::exception("Cannot convert string");
std::copy(&temp.front(), &temp.front() + dwSize, itOut);
}
inline std::string ToUpperCase(const std::string & in_str)
{
std::string result;
result.reserve(in_str.size());
ToUpperCaseA( in_str.begin(), in_str.end(), std::back_inserter(result));
return result;
}
// to upper case
inline void ToUpperCase(std::wstring::const_iterator itBegin, // in
std::wstring::const_iterator itEnd, // in
std::vector<wchar_t> * pVec) // out
{
pVec->assign( itBegin, itEnd );
if (CharUpperBuffW( &pVec->front(), (DWORD)pVec->size() )!=pVec->size())
throw std::exception("Cannot convert string");
}
inline std::wstring ToUpperCase(const std::wstring & in_str)
{
std::wstring result;
result.reserve(in_str.size());
ToUpperCaseW( in_str.begin(), in_str.end(), std::back_inserter(result));
return result;
}
class CHandleGuard
{
HANDLE h_;
CHandleGuard(CHandleGuard&);
CHandleGuard& operator=(CHandleGuard&);
public:
explicit CHandleGuard(HANDLE h=0)
:h_(h){}
~CHandleGuard(void)
{
if(h_)CloseHandle(h_);
}
HANDLE get() const {return h_;}
HANDLE release()
{
HANDLE tmp = h_;
h_ = 0;
return tmp;
}
void reset(HANDLE h)
{
if(h_)CloseHandle(h_);
h_ = h;
}
};
inline void LoadFileToStr(const std::wstring& fileName, std::string& data)
{
HANDLE hFile = CreateFileW(fileName.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
throw std::logic_error(__FUNCTION__" : can't open file " + wstring2string(fileName));
utils::CHandleGuard fileGuard(hFile);
DWORD fileSize = GetFileSize(hFile, NULL);
if(fileSize == INVALID_FILE_SIZE)
throw std::logic_error(__FUNCTION__" : can't get file size for ");
if (!fileSize)
return;
data.resize(fileSize);
DWORD bytesRead = 0;
if(!ReadFile(hFile, &data[0], fileSize, &bytesRead, 0) || bytesRead != fileSize)
throw std::logic_error(__FUNCTION__" : can't read file ");
}
inline std::vector< std::string >
split ( const std::string& str, const std::string& sep )
{
std::vector<std::string> ret;
for( size_t pos = 0; pos <= str.size();)
{
size_t new_pos = str.find( sep, pos);
if( std::string::npos == new_pos)
new_pos = str.size();
ret.push_back( str.substr( pos, new_pos - pos));
pos = new_pos + sep.size();
}
return ret;
}
inline std::vector< std::wstring >
split ( const std::wstring& str, const std::wstring& sep )
{
std::vector<std::wstring> ret;
for( size_t pos = 0; pos <= str.size();)
{
size_t new_pos = str.find( sep, pos);
if( std::string::npos == new_pos)
new_pos = str.size();
ret.push_back( str.substr( pos, new_pos - pos));
pos = new_pos + sep.size();
}
return ret;
}
} // namespace utils
#endif