//--------------------------------------------------------------------
// 文件名: util_func.cpp
// 内 容: 工具函数
// 说 明:
#include "util_func.h"
#include
#include
#include
#include
#define RAND_MAX1 (RAND_MAX + 1)
#define FLT_EPSILON 1.192092896e-07F
// 返回0-(scale-1)的随机整数
int util_random_int(int scale)
{
if ( (scale <= 0) || (scale > RAND_MAX1) )
{
return 0;
}
return int(float(::rand()) / float(RAND_MAX1) * float(scale));
}
// 返回0-scale)的随机浮点数
float util_random_float(float scale)
{
if (scale <= 0.0f)
{
return 0.0f;
}
return (float(::rand()) / float(RAND_MAX1) * scale);
}
float util_random_float(float min, float max)
{
float val = util_random_float(max-min);
return val + min;
}
// 双精度数转换成字符串
std::string util_double_as_string(double value, int decimals)
{
char str[64];
if (0 <= decimals || decimals >5 )
{
::sprintf(str, "%f", value);
}
else
{
char buff[10];
::sprintf(buff,"%%.0%df",decimals);
::sprintf(str,buff,value);
}
return std::string(str);
}
// 双精度转换成宽字符串
std::wstring util_double_as_widestr(double value, int decimals)
{
wchar_t buf[64];
if (0 == decimals)
{
::swprintf(buf, L"%f", value);
}
else
{
switch (decimals)
{
case 1:
::swprintf(buf, L"%.01f", value);
break;
case 2:
::swprintf(buf, L"%.02f", value);
break;
case 3:
::swprintf(buf, L"%.03f", value);
break;
case 4:
::swprintf(buf, L"%.04f", value);
break;
case 5:
::swprintf(buf, L"%.05f", value);
break;
default:
::swprintf(buf, L"%f", value);
break;
}
}
return std::wstring(buf);
}
// 整型数转换成字符串
std::string util_int64_as_string(__int64 value)
{
char buf[64];
::sprintf(buf, "%I64d", value);
return std::string(buf);
}
// 整型数转换成宽字符串
std::wstring util_int64_as_widestr(__int64 value)
{
wchar_t buf[64];
::swprintf(buf, L"%I64d", value);
return std::wstring(buf);
}
// 字符串转换成宽字符串
std::wstring util_string_as_widestr(const char* s)
{
size_t size = ::GetToWideStrLen(s);
TAutoMem
wchar_t* buffer = auto_buf.GetBuffer();
::ToWideStr(s, buffer, size * sizeof(wchar_t));
return std::wstring(buffer);
}
// 宽字符串转换成字符串
std::string util_widestr_as_string(const wchar_t* ws)
{
size_t size = ::GetToStringLen(ws);
TAutoMem
char* buffer = auto_buf.GetBuffer();
::ToString(ws, buffer, size);
return std::string(buffer);
}
// One-based array of days in year at month start
static const int MONTH_DAYS[13] =
{
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
};
static const double MIN_DATE = -657434.0; // about year 100
static const double MAX_DATE = 2958465.0; // about year 9999
static const double HALF_SECOND = 1.0 / 172800.0;
//
bool date_from_tm(unsigned int wYear, unsigned int wMonth, unsigned int wDay,
unsigned int wHour, unsigned int wMinute,
unsigned int wSecond, double& dtDest)
{
// Validate year and month (ignore day of week and milliseconds)
if ( (wYear > 9999) || (wMonth < 1) || (wMonth > 12) )
{
return false;
}
// Check for leap year and set the number of days in the month
bool bLeapYear = ((wYear & 3) == 0) &&
((wYear % 100) != 0 || (wYear % 400) == 0);
int nDaysInMonth = MONTH_DAYS[wMonth] - MONTH_DAYS[wMonth - 1] +
((bLeapYear && wDay == 29 && wMonth == 2) ? 1 : 0);
// Finish validating the date
if ( (wDay < 1) || (wDay > unsigned int(nDaysInMonth)) ||
(wHour > 23) || (wMinute > 59) || (wSecond > 59) )
{
return false;
}
// Cache the date in days and time in fractional days
long nDate;
double dblTime;
//It is a valid date; make Jan 1, 1AD be 1
nDate = wYear * 365L + wYear / 4 - wYear / 100 + wYear / 400 +
MONTH_DAYS[wMonth - 1] + wDay;
// If leap year and it's before March, subtract 1:
if ( (wMonth <= 2) && bLeapYear)
{
--nDate;
}
// Offset so that 12/30/1899 is 0
nDate -= 693959L;
dblTime = (((long)wHour * 3600L) + ((long)wMinute * 60L) +
((long)wSecond)) / 86400.0;
dtDest = (double) nDate + ((nDate >= 0) ? dblTime : -dblTime);
return true;
}
//
bool decode_date(double date, unsigned int& wYear, unsigned int& wMonth,
unsigned int& wDay, unsigned int& wHour,
unsigned int& wMinute, unsigned int& wSecond)
{
// The legal range does not actually span year 0 to 9999.
if ( (date > MAX_DATE) || date < (MIN_DATE) )
{
return false;
}
long nDays; // Number of days since Dec. 30, 1899
long nDaysAbsolute; // Number of days since 1/1/0
long nSecsInDay; // Time in seconds since midnight
long nMinutesInDay; // Minutes in day
long n400Years; // Number of 400 year increments since 1/1/0
long n400Century; // Century within 400 year block (0,1,2 or 3)
long n4Years; // Number of 4 year increments since 1/1/0
long n4Day; // Day within 4 year block
// (0 is 1/1/yr1, 1460 is 12/31/yr4)
long n4Yr; // Year within 4 year block (0,1,2 or 3)
bool bLeap4 = true; // TRUE if 4 year block includes leap year
double dblDate = date; // tempory serial date
// If a valid date, then this conversion should not overflow
nDays = (long)dblDate;
// Round to the second
dblDate += ((date > 0.0) ? HALF_SECOND : -HALF_SECOND);
nDaysAbsolute = (long)dblDate + 693959L; // Add days from 1/1/0 to 12/30/1899
dblDate = ::fabs(dblDate);
nSecsInDay = (long)((dblDate - ::floor(dblDate)) * 86400.);
// Leap years every 4 yrs except centuries not multiples of 400.
n400Years = (long)(nDaysAbsolute / 146097L);
// Set nDaysAbsolute to day within 400-year block
nDaysAbsolute %= 146097L;
// -1 because first century has extra day
n400Century = (long)((nDaysAbsolute - 1) / 36524L);
// Non-leap century
if (n400Century != 0)
{
// Set nDaysAbsolute to day within century
nDaysAbsolute = (nDaysAbsolute - 1) % 36524L;
// +1 because 1st 4 year increment has 1460 days
n4Years = (long)((nDaysAbsolute + 1) / 1461L);
if (n4Years != 0)
n4Day = (long)((nDaysAbsolute + 1) % 1461L);
else
{
bLeap4 = false;
n4Day = (long)nDaysAbsolute;
}
}
else
{
// Leap century - not special case!
n4Years = (long)(nDaysAbsolute / 1461L);
n4Day = (long)(nDaysAbsolute % 1461L);
}
if (bLeap4)
{
// -1 because first year has 366 days
n4Yr = (n4Day - 1) / 365;
if (n4Yr != 0)
n4Day = (n4Day - 1) % 365;
}
else
{
n4Yr = n4Day / 365;
n4Day %= 365;
}
// n4Day is now 0-based day of year. Save 1-based day of year, year number
wYear = WORD(n400Years * 400 + n400Century * 100 + n4Years * 4 + n4Yr);
// Handle leap year: before, on, and after Feb. 29.
if ( (n4Yr == 0) && bLeap4 )
{
// Leap Year
if (n4Day == 59)
{
/* Feb. 29*/
wMonth = 2;
wDay = 29;
goto DoTime;
}
// Pretend it's not a leap year for month/day comp.
if (n4Day >= 60)
{
--n4Day;
}
}
// Make n4DaY a 1-based day of non-leap year and compute
// month/day for everything but Feb. 29.
++n4Day;
// Month number always >= n/32, so save some loop time*/
for (wMonth = (n4Day >> 5) + 1; n4Day > MONTH_DAYS[wMonth]; ++wMonth);
{
wDay = (int)(n4Day - MONTH_DAYS[wMonth - 1]);
}
DoTime:
if (nSecsInDay == 0)
{
wHour = 0;
wMinute = 0;
wSecond = 0;
}
else
{
wSecond = (int)nSecsInDay % 60L;
nMinutesInDay = nSecsInDay / 60L;
wMinute = (int)nMinutesInDay % 60;
wHour = (int)nMinutesInDay / 60;
}
return true;
}
// 取当前时间
double util_get_now()
{
SYSTEMTIME tm;
::GetLocalTime(&tm);
DATE dt;
date_from_tm(tm.wYear, tm.wMonth, tm.wDay,
tm.wHour, tm.wMinute, tm.wSecond, dt);
return dt;
}
// 取日期
double util_get_date()
{
SYSTEMTIME tm;
::GetLocalTime(&tm);
DATE dt;
date_from_tm(tm.wYear, tm.wMonth, tm.wDay, 0, 0, 0, dt);
return dt;
}
// 取一天内的时间(0.0f - 1.0f)
double util_get_time()
{
SYSTEMTIME tm;
::GetLocalTime(&tm);
double dblTime = (((long)tm.wHour * 3600L) + ((long)tm.wMinute * 60L) +
((long)tm.wSecond)) / 86400.0;
return dblTime;
}
// 取时间差(天数)
double util_get_time_diff(double date1, double date2)
{
return (date1 - date2);
}
// 取年月日
void util_get_year_month_day(int& year, int& month, int& day)
{
SYSTEMTIME tm;
::GetLocalTime(&tm);
year = tm.wYear;
month = tm.wMonth;
day = tm.wDay;
}
// 取时分秒
void util_get_hour_minute_second(int& hour, int& minute, int& second)
{
SYSTEMTIME tm;
::GetLocalTime(&tm);
hour = tm.wHour;
minute = tm.wMinute;
second = tm.wSecond;
}
// 取星期(0为星期天)
int util_get_day_of_week()
{
SYSTEMTIME tm;
::GetLocalTime(&tm);
return tm.wDayOfWeek;
}
// 转换整数日期到浮点日期
bool util_encode_date(int year, int month, int day, double& date)
{
DATE dt;
if (! date_from_tm(year, month, day, 0, 0, 0, dt))
{
return false;
}
date = dt;
return true;
}
// 转换整数时间浮点时间
bool util_encode_time(int hour, int minute, int second, double& time)
{
if ( (hour < 0) || (hour > 23)
|| (minute < 0) || (minute > 59)
|| (second < 0) || (second > 59) )
{
return false;
}
time = (((long)hour * 3600L) + ((long)minute * 60L) +
((long)second)) / 86400.0;
return true;
}
// 转换浮点日期到整数日期
bool util_decode_date(double date, int& year, int& month, int& day)
{
unsigned int wYear, wMonth, wDay, wHour, wMinute, wSecond;
if (! ::decode_date(date, wYear, wMonth, wDay,
wHour, wMinute, wSecond))
{
return false;
}
year = wYear;
month = wMonth;
day = wDay;
return true;
}
// 转换浮点时间到整数时间
bool util_decode_time(double date, int& hour, int& minute, int& second)
{
unsigned int wYear, wMonth, wDay, wHour, wMinute, wSecond;
if (! ::decode_date(date, wYear, wMonth, wDay,
wHour, wMinute, wSecond))
{
return false;
}
hour = wHour;
minute = wMinute;
second = wSecond;
return true;
}
//
void util_get_utc_time(time_t* ttime, struct tm* tmtime)
{
memcpy(tmtime, gmtime(ttime), sizeof(struct tm));
}
//
void util_get_local_time(time_t* ttime, struct tm* tmtime)
{
memcpy(tmtime, localtime(ttime), sizeof(struct tm));
}
//
void util_convert_time_to_string( time_t* ttime, char * strtime)
{
struct tm OutTm;
memset(&OutTm,0,sizeof(OutTm));
util_get_local_time(ttime,&OutTm);
sprintf(strtime, "%d-%d-%d %d:%d:%d", OutTm.tm_year+1900, OutTm.tm_mon+1, OutTm.tm_mday,
OutTm.tm_hour, OutTm.tm_min,OutTm.tm_sec);
}
//将一个字符串转换成日期,必须是标准的yy-mm-dd hour:min格式
void util_convert_string_to_time(const char * strtime, time_t * ttime)
{
int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0;
if (strtime != NULL && strlen(strtime) > 6)
sscanf(strtime, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &min, &sec);
tm tmtemp;
tmtemp.tm_year = year - 1900;
tmtemp.tm_mon = month - 1;
tmtemp.tm_mday = day;
tmtemp.tm_hour = hour;
tmtemp.tm_min = min;
tmtemp.tm_sec = sec;
tmtemp.tm_isdst = 0;
tmtemp.tm_wday = 0;
tmtemp.tm_yday = 0;
*ttime = mktime(&tmtemp);
}
// 获得系统Ticks
unsigned long util_get_ticks()
{
return ::GetTickCount();
}
// 获得64位的当前时间,精确到ms
__time64_t util_get_time_64()
{
SYSTEMTIME stm;
FILETIME ftm;
::GetSystemTime(&stm);
::SystemTimeToFileTime(&stm, &ftm);
__time64_t now = ftm.dwHighDateTime;
now = ((now << 32) | ftm.dwLowDateTime) / 10000;
return now;
}
// 去除字符串前后空格
std::string util_trim_string(std::string str)
{
if (str.empty())
return str;
size_t pos = str.find_first_not_of(' ');
if (pos==str.npos)
return "";
str = str.substr(pos, str.size()-pos);
pos = str.find_last_not_of(' ');
return str.substr(0, pos+1);
}
// 去除宽字符串前后空格
std::wstring util_trim_wstring(std::wstring str)
{
size_t pos = str.find_first_not_of(L' ');
if (pos==str.npos)
return L"";
str = str.substr(pos, str.size()-pos);
pos = str.find_last_not_of(L' ');
return str.substr(0, pos+1);
}
// 分割字符串
void util_split_string(IVarList & result, const std::string& str,
const std::string& delims, unsigned int max_splits)
{
if (0 == str.compare(""))
{
return;
}
unsigned int num_splits = 0;
size_t start, pos;
start = 0;
do
{
pos = str.find_first_of(delims, start);
if (pos == std::string::npos || (max_splits > 0 && num_splits == max_splits))
{
result << util_trim_string(str.substr(start)).c_str();
break;
}
else
{
result << util_trim_string(str.substr(start, pos - start)).c_str();
start = pos + 1;
}
num_splits++;
} while (pos != std::string::npos);
return;
}
// 字符串是否相等
bool string_equal(const char* s1, const char* s2)
{
return strcmp(s1, s2) == 0;
}
// 分割字符串
void util_split_wstring(IVarList & result, const std::wstring& str,
const std::wstring& delims, unsigned int max_splits)
{
if (0 == str.compare(L""))
{
return;
}
unsigned int num_splits = 0;
size_t start, pos;
start = 0;
do
{
pos = str.find_first_of(delims, start);
if (pos == start)
{
start = pos + 1;
}
else if (pos == std::wstring::npos || (max_splits > 0 && num_splits == max_splits))
{
result << util_trim_wstring(str.substr(start)).c_str();
break;
}
else
{
result << util_trim_wstring(str.substr(start, pos - start)).c_str();
start = pos + 1;
}
num_splits++;
} while (pos != std::wstring::npos);
return;
}
// 求两点的距离
float util_dot_distance(float x1, float y1, float x2, float y2)
{
float sx = x1 - x2;
float sy = y1 - y2;
return ::sqrt(sx * sx + sy * sy);
}
// 求三维空间的两点的距离
float util_dot_distance(float x1, float y1, float z1, float x2, float y2, float z2)
{
float sx = x1 - x2;
float sy = y1 - y2;
float sz = z1 - z2;
return ::sqrt(sx * sx + sy * sy + sz * sz);
}
//
float util_square_distance(float x1, float y1, float z1, float x2, float y2, float z2)
{
float sx = x1 - x2;
float sy = y1 - y2;
float sz = z1 - z2;
return (sx * sx + sy * sy + sz * sz);
}
//
float util_dot_angle(float x1, float y1, float x2, float y2)
{
float sx = x2 - x1;
float sy = y2 - y1;
float dist = ::sqrt(sx * sx + sy * sy);
float a = 0.0f;
if( !util_float_equal(dist, 0.0f))
{
a = ::acos(sy / dist);
}
if (sx < 0)
a = -a;
return ::util_normalize_angle(a);
}
//
float util_normalize_angle(float angle)
{
float value = ::fmod(angle, PI2);
if (value < 0)
value = value + PI2;
return value;
}
//
float util_get_angle_diff(const float & angle1, const float & angle2)
{
const float norm_angle1 = util_normalize_angle(angle1);
const float norm_angle2 = util_normalize_angle(angle2);
float angle_diff = fabs(norm_angle1 - norm_angle2);
if (angle_diff > PI)
{
angle_diff = PI2 - angle_diff;
}
return angle_diff;
}
// 判断浮点数是否合法
// 1.#INF 无穷小
// -1.#IND: 除零
// 1.#INF000: 正无穷大
// -1.#INF000: 负无穷大
bool util_float_is_valid(float val)
{
if (_isnan(val))
return false;
if (val+1==val)
return false;
return true;
}
// 判断两个浮点数是否可认为相等
bool util_float_equal( float f1, float f2 )
{
return ( f1 < ( f2 + FLT_EPSILON ) ) && ( f1 > ( f2 - FLT_EPSILON ) );
}
// 判断浮点数f是否等于0
bool util_float_equal_zero(float f)
{
return (f >= -FLT_EPSILON && f <= FLT_EPSILON);
}
void vec_cwr_pi_2(D3DXVECTOR3& vOut, const D3DXVECTOR3& vIn )
{
vOut.x = vIn.z;
vOut.y = vIn.y;
vOut.z = vIn.x * -1.0f;
}
void vec_cwl_pi_2(D3DXVECTOR3& vOut, const D3DXVECTOR3& vIn )
{
vOut.x = vIn.z * -1.0f;
vOut.y = vIn.y;
vOut.z = vIn.x;
}
// 顺时针45°
void vec_cwl_pi_4(D3DXVECTOR3& vOut, const D3DXVECTOR3& vIn)
{
vOut.x = ( vIn.x - vIn.z ) * FLOAT_VALUE_PI_4;
vOut.y = vIn.y;
vOut.z = ( vIn.x + vIn.z ) * FLOAT_VALUE_PI_4;
}
// 逆时针45°
void vec_cwr_pi_4(D3DXVECTOR3& vOut, const D3DXVECTOR3& vIn)
{
vOut.x = ( vIn.x + vIn.z ) * FLOAT_VALUE_PI_4;
vOut.y = vIn.y;
vOut.z = ( vIn.z + vIn.x ) * FLOAT_VALUE_PI_4;
}
// 通过场景ConfigID得到寻路中使用的场景Resource
void util_get_scene_resource_by_configid(std::string& strRet, const std::string& config_id)
{
CVarList strSplit;
std::string strTmp;
// 按照 "\" 分割
util_split_string(strSplit, config_id, "\\");
if (strSplit.GetCount() == 0)
{
strRet = "";
return;
}
// 目标字符串在最后分割的字符串中
strTmp = strSplit.StringVal(strSplit.GetCount() - 1);
// 按照 "_" 分割
strSplit.Clear();
util_split_string(strSplit, strTmp, "_");
if (strSplit.GetCount() == 0)
{
strRet = "";
return;
}
// 目标字符串为第一个
strRet = strSplit.StringVal(0);
return;
}
// 生成唯一的名字id
std::string util_gen_unique_name()
{
GUID id;
if (CoCreateGuid(&id) != S_OK)
{
return std::string();
}
char buf[64];
sprintf(buf, "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X",
id.Data1, id.Data2, id.Data3,
id.Data4[0], id.Data4[1], id.Data4[2], id.Data4[3],
id.Data4[4], id.Data4[5], id.Data4[6], id.Data4[7]);
return std::string(buf);
}
//数据拷贝
bool CopyData(IVar & var, IVarList & list)
{
switch(list.GetType(0))
{
case VTYPE_BOOL:
var.SetBool(list.BoolVal(0));
return true;
case VTYPE_INT:
var.SetInt(list.IntVal(0));
return true;
case VTYPE_INT64:
var.SetInt64(list.Int64Val(0));
return true;
case VTYPE_FLOAT:
var.SetFloat(list.FloatVal(0));
return true;
case VTYPE_DOUBLE:
var.SetDouble(list.DoubleVal(0));
return true;
case VTYPE_STRING:
var.SetString(list.StringVal(0));
return true;
case VTYPE_WIDESTR:
var.SetWideStr(list.WideStrVal(0));
return true;
case VTYPE_OBJECT:
var.SetObject(list.ObjectVal(0));
return true;
}
return false;
}
//数据拷贝
bool VarCopyData(IVar & var, IVar & ivar)
{
switch(ivar.GetType())
{
case VTYPE_BOOL:
var.SetBool(ivar.BoolVal());
return true;
case VTYPE_INT:
var.SetInt(ivar.IntVal());
return true;
case VTYPE_INT64:
var.SetInt64(ivar.Int64Val());
return true;
case VTYPE_FLOAT:
var.SetFloat(ivar.FloatVal());
return true;
case VTYPE_DOUBLE:
var.SetDouble(ivar.DoubleVal());
return true;
case VTYPE_STRING:
var.SetString(ivar.StringVal());
return true;
case VTYPE_WIDESTR:
var.SetWideStr(ivar.WideStrVal());
return true;
case VTYPE_OBJECT:
var.SetObject(ivar.ObjectVal());
return true;
}
return false;
}
// 根据值类型 自动加入VarList
bool VarListAddData(IVarList & list, IVar & ivar)
{
switch(ivar.GetType())
{
case VTYPE_BOOL:
list.AddBool(ivar.BoolVal());
return true;
case VTYPE_INT:
list.AddInt(ivar.IntVal());
return true;
case VTYPE_INT64:
list.AddInt64(ivar.Int64Val());
return true;
case VTYPE_FLOAT:
list.AddFloat(ivar.FloatVal());
return true;
case VTYPE_DOUBLE:
list.AddDouble(ivar.DoubleVal());
return true;
case VTYPE_STRING:
list.AddString(ivar.StringVal());
return true;
case VTYPE_WIDESTR:
list.AddWideStr(ivar.WideStrVal());
return true;
case VTYPE_OBJECT:
list.AddObject(ivar.ObjectVal());
return true;
}
return false;
}
//VarToString
std::string VarToString(const IVar & ivar)
{
switch(ivar.GetType())
{
case VTYPE_BOOL:
if (ivar.BoolVal())
{
return "true";
}else
{
return "false";
}
case VTYPE_INT:
return util_int64_as_string(ivar.IntVal());
case VTYPE_INT64:
return util_int64_as_string((int)ivar.Int64Val());
case VTYPE_FLOAT:
return util_double_as_string(ivar.FloatVal());
case VTYPE_DOUBLE:
return util_double_as_string((float)ivar.DoubleVal());
case VTYPE_STRING:
return ivar.StringVal();
case VTYPE_WIDESTR:
return util_widestr_as_string(ivar.WideStrVal());
//case VTYPE_OBJECT:
}
return "";
}
//数据
bool untl_is_the_same(const IVar & src, const IVar & dest)
{
if (src.GetType() != dest.GetType())
{
return false;
}
switch(src.GetType())
{
case VTYPE_BOOL:
case VTYPE_INT:
case VTYPE_INT64:
if (src.IntVal() == dest.IntVal())
{
return true;
}
return false;
case VTYPE_FLOAT:
case VTYPE_DOUBLE:
if (src.FloatVal() == dest.FloatVal())
{
return true;
}
return false;
case VTYPE_STRING:
if (strcmp(src.StringVal(), dest.StringVal()) == 0)
{
return true;
}
return false;
case VTYPE_WIDESTR:
if (wcscmp(src.WideStrVal(), dest.WideStrVal()) == 0)
{
return true;
}
return false;
case VTYPE_OBJECT:
if (src.ObjectVal() == dest.ObjectVal())
{
return true;
}
return false;
}
return false;
}
// end of file util_func.cpp
DECLARE_FUNCTION_1(std::string, util_widestr_as_string,const wchar_t*);