/*! \file StdUtils.h \brief useful functions working with std functions. Created: 2015/06/22, author: Jin Bingwen. */ #ifndef __StdUtils_h_ #define __StdUtils_h_ #if (defined(_MSC_VER) && _MSC_VER <= 1600) #define LITTLE_CPP11 1 #else #include #endif #if (defined _WINDOWS) || (defined WIN32) #define USE_WIN_API 1 #endif #include #include #include #include #include #include #include using std::string; using std::vector; using std::stringstream; #if defined(LITTLE_CPP11) #define GET_SIGN(x) (x < 0 ? true : false) #else #define GET_SIGN(x) std::signbit(x) #endif template T sum(_Iter s, _Iter e) { if (s == e) { return T(); } T ret = *s; s++; while (s != e) { ret += *s; s++; } return ret; } template _Iter findTopNPercentEle(_Iter s, _Iter e, float nPersent) { auto maxVal = std::max_element(s, e); T threVal = (*maxVal)*(1.0f - nPersent); while (s != e) { if (*s < threVal) { return s; } ++s; } return s; } template _Iter findSumTopNPercentEle(_Iter s, _Iter e, float nPersent) { T sumVal = sum(s, e); T threVal = sumVal*nPersent; sumVal = 0; while (s != e) { sumVal += *s; if (sumVal > threVal) { s++; return s; } s++; } return e; } template void clearAndResetVec(vector* vec, int n) { if (vec) { vec->clear(); vec->reserve(n); } } template void genIncVec(vector& vec, T start, int count, T step) { for (int i = 0; i < count; ++i) { vec.push_back(start); start += step; } } class SortEle { public: SortEle() : mSortVal(0), pEle(NULL) {} SortEle(double val, const void* pData) : mSortVal(val), pEle(pData) {} double mSortVal; const void* pEle; bool operator< (const SortEle& i) { return mSortVal < i.mSortVal; } bool operator>(const SortEle& i) { return mSortVal > i.mSortVal; } SortEle operator+ (const SortEle& i) { return SortEle(mSortVal + i.mSortVal, pEle); } void operator+= (const SortEle& i) { mSortVal += i.mSortVal; } SortEle operator- (const SortEle& i) { return SortEle(mSortVal - i.mSortVal, pEle); } operator float() { return (float)mSortVal; } operator double() { return mSortVal; } SortEle operator* (float f) { return SortEle(mSortVal*f, pEle); } void operator= (float f) { mSortVal = f; } }; template _It findRange(_It s, _It e, const _Ty& val) { if (s == e) { return s; } _It mi = (e - s) / 2 + s; if (val < *mi) { return findRange(s, mi, val); } else if (val > *mi) { return findRange(mi + 1, e, val); } else { return mi; } } template void add(_It s, _It e, const _Ty& val) { while (s != e) { *s += val; s++; } } template bool allInRange(_It s, _It e, _Ty minVal, _Ty maxVal) { while (s != e) { if (*s < minVal || *s > maxVal) { return false; } ++s; } return true; } template bool anyInRange(_It s, _It e, _Ty minVal, _Ty maxVal) { while (s != e) { if (*s >= minVal && *s <= maxVal) { return true; } ++s; } return false; } template bool anyIn(_It s, _It e, _Ty v) { while (s != e) { if (*s == v) { return true; } ++s; } return false; } template bool loadAValueFromFile(string filePath, _T& ret) { std::fstream fs; fs.open(filePath, std::fstream::in); if (!fs.is_open()) { return false; } fs >> ret; fs.close(); } // search range is [si, ei), not include ei template _PairIter max_first_element(_PairIter si, _PairIter ei) { if (si == ei) { return ei; } // exclude ei _PairIter ret = --ei; ei++; auto maxVal = si->first; si++; while (si != ei) { if (maxVal < si->first) { maxVal = si->first; ret = si; } ++si; } return ret; } template string joinStr(_Ty0 s0, _Ty1 s1) { stringstream ss; ss << s0 << s1; return ss.str(); } template string joinStr(_Ty0 s0, _Ty1 s1, _Ty2 s2) { stringstream ss; ss << s0 << s1 << s2; return ss.str(); } template string joinStr(_Ty0 s0, _Ty1 s1, _Ty2 s2, _Ty3 s3) { stringstream ss; ss << s0 << s1 << s2 << s3; return ss.str(); } #define _DECLARE_PARAMETER_MEM(type, name)\ protected:\ type m##name; #define _DECLARE_PARAMETER_GETFUN(type, name)\ public:\ type get##name() const { return m##name; } #define _DECLARE_PARAMETER_SETFUN(type, name)\ public:\ void set##name(type val) { m##name = val; } #define _DECLARE_PARAMETER_SETFUN2(type, name, val1, val2)\ public:\ void set##name(type val) {\ assert(val >= val1 && val <= val2);\ if (val >= val1 && val <= val2) m##name = val; } #define _DECLARE_PARAMETER_SETENUM(type, name)\ public:\ void set##name(type val) { m##name = val; }\ void set##name(int val) {\ set##name(static_cast(val)); } #define _DECLARE_PARAMETER_SETENUM2(type, name, val1, val2)\ public:\ void set##name(type val) {\ assert(val >= val1 && val <= val2);\ if (val >= val1 && val <= val2) m##name = val; }\ void set##name(int val) {\ set##name(static_cast(val)); } #define _DECLARE_PARAMETER_SETPAIR(type, name)\ public:\ void set##name(type val1, type val2) {\ if (val1 > val2) { m##name##Start = val2; m##name##End = val1; }\ else { m##name##Start = val1; m##name##End = val2; }\ } #define _DECLARE_PARAMETER_SETPAIR2(type, name, val1, val2)\ public:\ void set##name(type value1, type value2) {\ assert(value1 >= val1 && value1 <= val2 && value2 >= val1 && value2 <= val2);\ if (value1 >= val1 && value1 <= val2 && value2 >= val1 && value2 <= val2) {\ if (value1 > value2) { m##name##Start = value2; m##name##End = value1; }\ else { m##name##Start = value1; m##name##End = value2; }\ }\ } #define DECLARE_PARAMETER(type, name)\ _DECLARE_PARAMETER_MEM(type, name)\ _DECLARE_PARAMETER_GETFUN(type, name)\ _DECLARE_PARAMETER_SETFUN(type, name) #define DECLARE_PARAMETER2(type, name, val1, val2)\ _DECLARE_PARAMETER_MEM(type, name)\ _DECLARE_PARAMETER_GETFUN(type, name)\ _DECLARE_PARAMETER_SETFUN2(type, name, val1 , val2) #define DECLARE_PARAMETER_SET(type, name)\ _DECLARE_PARAMETER_MEM(type, name)\ _DECLARE_PARAMETER_SETFUN(type, name) #define DECLARE_PARAMETER_SET2(type, name, val1, val2)\ _DECLARE_PARAMETER_MEM(type, name)\ _DECLARE_PARAMETER_SETFUN2(type, name, val1, val2) #define DECLARE_PARAMETER_GET(type, name)\ _DECLARE_PARAMETER_MEM(type, name)\ _DECLARE_PARAMETER_GETFUN(type, name) #define DECLARE_PARAMETER_ENUM(type, name)\ _DECLARE_PARAMETER_MEM(type, name)\ _DECLARE_PARAMETER_GETFUN(type, name)\ _DECLARE_PARAMETER_SETENUM(type, name) #define DECLARE_PARAMETER_ENUM2(type, name, val1, val2)\ _DECLARE_PARAMETER_MEM(type, name)\ _DECLARE_PARAMETER_GETFUN(type, name)\ _DECLARE_PARAMETER_SETENUM2(type, name, val1, val2) #define DECLARE_PARAMETER_PAIR(type, name)\ _DECLARE_PARAMETER_MEM(type, name##Start)\ _DECLARE_PARAMETER_MEM(type, name##End)\ _DECLARE_PARAMETER_GETFUN(type, name##Start)\ _DECLARE_PARAMETER_GETFUN(type, name##End)\ _DECLARE_PARAMETER_SETPAIR(type, name) #define DECLARE_PARAMETER_PAIR2(type, name, val1, val2)\ _DECLARE_PARAMETER_MEM(type, name##Start)\ _DECLARE_PARAMETER_MEM(type, name##End)\ _DECLARE_PARAMETER_GETFUN(type, name##Start)\ _DECLARE_PARAMETER_GETFUN(type, name##End)\ _DECLARE_PARAMETER_SETPAIR2(type, name, val1, val2) // Declare the provide class as a singleton. // Get instance via Class::getInstance(). // // Note: according to C++11 standard, static object initialization will // be made only by one thread, other threads will wait till it complete. // start from VS2014, this macro is thread-safe. #define DECLARE_SINGLETON(type, ...)\ public:\ static type& getInstance() {\ static type inst(__VA_ARGS__);\ return inst;\ } // Declare the provide class as a singleton. // Get instance via Class::getInstance(). // // Note: according to C++11 standard, static object initialization will // be made only by one thread, other threads will wait till it complete. // start from VS2014, this macro is thread-safe. #define DECLARE_SINGLETON_NOPARA(type)\ public:\ static type& getInstance() {\ static type inst;\ return inst;\ } // A simple version of object factory that use object name as key and hold object instances. // It's thread-safe. // Note: factory own the object instance, aka. own the object instance's memory, which means it will // deallocate the memory when it self is destroyed (when the who application is shutdown). // You don't need to delete the object instance yourself, and even worse, it will cause the double-delete crash. template, TPtr>::value>::type* = nullptr> class ObjectFactory { DECLARE_SINGLETON_NOPARA(ObjectFactory) public: ~ObjectFactory() {} TPtr getObject(const char* name) { //CyclopsLockGuard guard(&mLock); auto it = mLookupTable.find(name); if (it == mLookupTable.end()) { // create new TPtr ptr = std::make_shared(); it = mLookupTable.insert(std::make_pair(name, ptr)).first; } return it->second; } private: ObjectFactory() {} std::map mLookupTable; //CyclopsLock mLock; }; template inline T minMax(T val, T minVal, T maxVal) { return std::min(maxVal, std::max(minVal, val)); } #endif // __StdUtils_h_