From c57b4410708df60910b9ebcea007cf6f798044ad Mon Sep 17 00:00:00 2001 From: hyzboy Date: Tue, 27 Nov 2018 15:43:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=83=A8=E5=88=86=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E5=BA=93=E5=A4=B4=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 7 +- example/CMakeLists.txt | 1 + example/NullWindow/CMakeLists.txt | 3 + example/NullWindow/main.cpp | 7 + inc/hgl/CompOperator.h | 16 + inc/hgl/Macro.h | 120 ++ inc/hgl/Str.h | 2370 ++++++++++++++++++++++ inc/hgl/TypeFunc.h | 611 ++++++ inc/hgl/algorithm/Math.h | 155 ++ inc/hgl/algorithm/MathMGL.h | 205 ++ inc/hgl/endian/Endian.h | 275 +++ inc/hgl/platform/InputDevice.h | 200 ++ inc/hgl/platform/Platform.h | 334 +++ inc/hgl/platform/compiler/DataTypeGNU.h | 21 + inc/hgl/platform/compiler/DataTypeTiny.h | 29 + inc/hgl/platform/compiler/DataTypeWin.h | 17 + inc/hgl/platform/compiler/EventFunc.h | 250 +++ inc/hgl/platform/compiler/GNU.h | 85 + inc/hgl/platform/compiler/Intel.h | 43 + inc/hgl/platform/compiler/LLVM.h | 25 + inc/hgl/platform/compiler/Microsoft.h | 61 + inc/hgl/platform/compiler/Property.h | 97 + inc/hgl/platform/os/Android.h | 86 + inc/hgl/platform/os/BSD.h | 83 + inc/hgl/platform/os/Linux.h | 75 + inc/hgl/platform/os/MSWindows.h | 80 + inc/hgl/platform/os/MacOS.h | 78 + inc/hgl/platform/os/PosixThread.h | 15 + inc/hgl/thread/ASyncEvent.h | 123 ++ inc/hgl/thread/Atomic.h | 61 + inc/hgl/thread/CondVar.h | 32 + inc/hgl/thread/DataPost.h | 156 ++ inc/hgl/thread/Loader.h | 74 + inc/hgl/thread/RWLock.h | 187 ++ inc/hgl/thread/RingBuffer.cpp | 58 + inc/hgl/thread/RingBuffer.h | 345 ++++ inc/hgl/thread/RingBufferRead.cpp | 210 ++ inc/hgl/thread/RingBufferWrite.cpp | 181 ++ inc/hgl/thread/SemLock.h | 233 +++ inc/hgl/thread/Semaphore.h | 33 + inc/hgl/thread/SwapColl.h | 156 ++ inc/hgl/thread/SwapData.h | 240 +++ inc/hgl/thread/Thread.h | 230 +++ inc/hgl/thread/ThreadMutex.h | 163 ++ inc/hgl/thread/Workflow.h | 371 ++++ inc/hgl/thread/atomic/AtomicGNU.h | 48 + inc/hgl/thread/atomic/AtomicOSX.h | 50 + inc/hgl/thread/atomic/AtomicWin.h | 91 + inc/hgl/type/BaseString.h | 1208 +++++++++++ inc/hgl/type/DataType.h | 11 + inc/hgl/type/Smart.h | 460 +++++ inc/hgl/type/StdString.h | 35 + inc/hgl/type/StringInstance.h | 501 +++++ inc/hgl/type/_Object.h | 42 + 54 files changed, 10647 insertions(+), 1 deletion(-) create mode 100644 example/CMakeLists.txt create mode 100644 example/NullWindow/CMakeLists.txt create mode 100644 example/NullWindow/main.cpp create mode 100644 inc/hgl/CompOperator.h create mode 100644 inc/hgl/Macro.h create mode 100644 inc/hgl/Str.h create mode 100644 inc/hgl/TypeFunc.h create mode 100644 inc/hgl/algorithm/Math.h create mode 100644 inc/hgl/algorithm/MathMGL.h create mode 100644 inc/hgl/endian/Endian.h create mode 100644 inc/hgl/platform/InputDevice.h create mode 100644 inc/hgl/platform/Platform.h create mode 100644 inc/hgl/platform/compiler/DataTypeGNU.h create mode 100644 inc/hgl/platform/compiler/DataTypeTiny.h create mode 100644 inc/hgl/platform/compiler/DataTypeWin.h create mode 100644 inc/hgl/platform/compiler/EventFunc.h create mode 100644 inc/hgl/platform/compiler/GNU.h create mode 100644 inc/hgl/platform/compiler/Intel.h create mode 100644 inc/hgl/platform/compiler/LLVM.h create mode 100644 inc/hgl/platform/compiler/Microsoft.h create mode 100644 inc/hgl/platform/compiler/Property.h create mode 100644 inc/hgl/platform/os/Android.h create mode 100644 inc/hgl/platform/os/BSD.h create mode 100644 inc/hgl/platform/os/Linux.h create mode 100644 inc/hgl/platform/os/MSWindows.h create mode 100644 inc/hgl/platform/os/MacOS.h create mode 100644 inc/hgl/platform/os/PosixThread.h create mode 100644 inc/hgl/thread/ASyncEvent.h create mode 100644 inc/hgl/thread/Atomic.h create mode 100644 inc/hgl/thread/CondVar.h create mode 100644 inc/hgl/thread/DataPost.h create mode 100644 inc/hgl/thread/Loader.h create mode 100644 inc/hgl/thread/RWLock.h create mode 100644 inc/hgl/thread/RingBuffer.cpp create mode 100644 inc/hgl/thread/RingBuffer.h create mode 100644 inc/hgl/thread/RingBufferRead.cpp create mode 100644 inc/hgl/thread/RingBufferWrite.cpp create mode 100644 inc/hgl/thread/SemLock.h create mode 100644 inc/hgl/thread/Semaphore.h create mode 100644 inc/hgl/thread/SwapColl.h create mode 100644 inc/hgl/thread/SwapData.h create mode 100644 inc/hgl/thread/Thread.h create mode 100644 inc/hgl/thread/ThreadMutex.h create mode 100644 inc/hgl/thread/Workflow.h create mode 100644 inc/hgl/thread/atomic/AtomicGNU.h create mode 100644 inc/hgl/thread/atomic/AtomicOSX.h create mode 100644 inc/hgl/thread/atomic/AtomicWin.h create mode 100644 inc/hgl/type/BaseString.h create mode 100644 inc/hgl/type/DataType.h create mode 100644 inc/hgl/type/Smart.h create mode 100644 inc/hgl/type/StdString.h create mode 100644 inc/hgl/type/StringInstance.h create mode 100644 inc/hgl/type/_Object.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c5ae70d..7ae3347c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.0) PROJECT(ULRE) @@ -14,4 +14,9 @@ check_system_version() set_compiler_param() set_output_directory() +include_directories(3rdpty/MathGeoLib/src) +include_directories(inc) + add_subdirectory(3rdpty/MathGeoLib) + +add_subdirectory(example) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt new file mode 100644 index 00000000..0b60fbf1 --- /dev/null +++ b/example/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(NullWindow) diff --git a/example/NullWindow/CMakeLists.txt b/example/NullWindow/CMakeLists.txt new file mode 100644 index 00000000..1dc10f59 --- /dev/null +++ b/example/NullWindow/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(NullWindow main.cpp) + +target_link_libraries(NullWindow PRIVATE MathGeoLib) diff --git a/example/NullWindow/main.cpp b/example/NullWindow/main.cpp new file mode 100644 index 00000000..5b4229ab --- /dev/null +++ b/example/NullWindow/main.cpp @@ -0,0 +1,7 @@ +#include + +int main(int,char **) +{ + std::cout<<"hello,world!"< (name i)const {return compfunc(i)>0;} \ + const bool operator < (name i)const {return compfunc(i)<0;} \ + const bool operator >=(name i)const {return compfunc(i)>=0;}\ + const bool operator <=(name i)const {return compfunc(i)<=0;}\ + const bool operator ==(name i)const {return compfunc(i)==0;}\ + const bool operator !=(name i)const {return compfunc(i)!=0;} + + #define CompOperatorMemcmp(name) int _Comp(name data)const{return memcmp(this,&data,sizeof(name));} \ + CompOperator(name,_Comp) +}//namespace hgl +#endif//HGL_COMP_OPERATOR_INCLUDE diff --git a/inc/hgl/Macro.h b/inc/hgl/Macro.h new file mode 100644 index 00000000..fd051a60 --- /dev/null +++ b/inc/hgl/Macro.h @@ -0,0 +1,120 @@ +#ifndef HGL_MACRO_INCLUDE +#define HGL_MACRO_INCLUDE + +namespace hgl +{ + #define RETURN_OBJECT_OF_ARRAY(array,index,max_count) return (index<0||index>=max_count)?nullptr:array[index]; + + #define NEW_NULL_ARRAY(name,type,count) { \ + name=new type[count]; \ + \ + memset(name,0,sizeof(type)*count); \ + } + + #define SAFE_CLEAR(name) { \ + if(name) \ + { \ + delete name; \ + name=nullptr; \ + } \ + } + + #define SAFE_CLEAR_ARRAY(name) { \ + if(name) \ + { \ + delete[] name; \ + name=nullptr; \ + } \ + } + + #define SAFE_CLEAR_OBJECT_ARRAY(name,num) { \ + if(name&&num>=0) \ + { \ + int safe_clear_object_array_number=num; \ + \ + while(safe_clear_object_array_number--) \ + if(name[safe_clear_object_array_number]) \ + delete name[safe_clear_object_array_number]; \ + \ + delete[] name; \ + name=nullptr; \ + } \ + } + + #define FREE_OBJECT_ARRAY(name,num) { \ + if(name&&num>=0) \ + { \ + int free_object_array_number=num; \ + \ + while(free_object_array_number--) \ + if(name[free_object_array_number]) \ + delete name[free_object_array_number]; \ + \ + cm_free(name); \ + name=nullptr; \ + } \ + } + + #define SAFE_FREE_OBJECT_ARRAY(name,num) { \ + if(name) \ + FREE_OBJECT_ARRAY(name,num); \ + } + + #define SAFE_FREE(name) { \ + if(name) \ + cm_free(name); \ + } + + #define SAFE_RECREATE(name,code) { \ + if(name) \ + delete name; \ + \ + name=code; \ + } + + #define ARRAY_CALL(name,num,code) { \ + int array_call_number=num; \ + \ + while(array_call_number--) \ + name[array_call_number]->code; \ + } + + #define LOAD_FUNC(type,func) type func(void *buf,int buf_size) \ + { \ + if(!buf||buf_size<=0)return 0; \ + \ + MemoryInputStream ms(buf,buf_size); \ + \ + return(func(&ms)); \ + } \ + \ + type func(const UTF16String &filename) \ + { \ + FileInputStream fs; \ + \ + if(fs.Open(filename)) \ + return(func(&fs)); \ + else \ + return 0; \ + } + + #define SAVE_FUNC(type,func) bool func(type data,void *buf,int buf_size) \ + { \ + if(!buf||buf_size<=0)return(false); \ + \ + MemoryOutputStream ms(buf,buf_size); \ + \ + return(func(data,&ms)); \ + } \ + \ + bool func(type data,const UTF16String &filename) \ + { \ + FileOutputStream fs; \ + \ + if(fs.CreateTrunc(filename)) \ + return(func(data,&fs)); \ + else \ + return(false); \ + } +}//namespace hgl +#endif//HGL_MACRO_INCLUDE diff --git a/inc/hgl/Str.h b/inc/hgl/Str.h new file mode 100644 index 00000000..d5fea49c --- /dev/null +++ b/inc/hgl/Str.h @@ -0,0 +1,2370 @@ +#ifndef HGL_STR_TEMPLATE_INCLUDE +#define HGL_STR_TEMPLATE_INCLUDE + +#include +namespace hgl +{ + // 32 空格 + // 33 ! + // 34 " + // 35 # + // 36 $ + // 37 % + // 38 & + // 39 ' + // 40 ( + // 41 ) + // 42 * + // 43 + + // 44 , + // 45 - + // 46 . + // 47 / + // 48 0123456789 + // 58 : + // 59 ; + // 60 < + // 61 = + // 62 > + // 63 ? + // 64 @ + // 65 ABCDEFGHIJKLMNOPQRSTUVWXYZ + // 91 [ + // 92 \ + // 93 ] + // 94 ^ + // 95 _ + // 96 ` + // 97 abcdefghijklmnopqrstuvwxyz + // 123 { + // 124 | + // 125 } + // 126 ~ + + /** + * 测试字符是否是emoji表情
+ * 参见https://unicode.org/Public/emoji/12.0/emoji-data.txt + */ + template + bool isemoji(const T ch) + { + if(ch==0x23)return(true); //# + if(ch==0x2A)return(true); //* + if(ch>=0x30&&ch<=0x39)return(true); //0-9 + if(ch==0xA9)return(true); //© + if(ch==0xAE)return(true); //® + if(ch>=0x203C&&ch<=0x1FFFD)return(true); + + return(false); + } + + /** + * 测试当前字符是否为小写字母 + */ + template + bool islower(const T ch) + { + return(ch>='a'&&ch<='z'); + } + + /** + * 测试当前字符是否为大写字母 + */ + template + bool isupper(const T ch) + { + return(ch>='A'&&ch<='Z'); + } + + /** + * 测试当前字符是否为字母 + */ + template + bool isalpha(const T ch) + { + return(islower(ch)||isupper(ch)); + } + + /** + * 测试当前字符是否为10进制数字 + */ + template + bool isdigit(const T ch) + { + return(ch>='0'&&ch<='9'); + } + + /** + * 测试当前字符串是否为10进制数字以及小数点、正负符号、指数字符 + */ + template + bool isfloat(const T ch) + { + return isdigit(ch) + ||ch=='-' + ||ch=='+' + ||ch=='.' + ||ch=='E' + ||ch=='e'; + } + + template + bool isinteger(const T ch) + { + return isdigit(ch) + ||ch=='-' + ||ch=='+'; + } + + /** + * 测试当前字符是否为16进制数用字符(0-9,A-F) + */ + template + bool isxdigit(const T ch) + { + return((ch>='0'&&ch<='9') + ||(ch>='a'&&ch<='f') + ||(ch>='A'&&ch<='F')); + } + + /** + * 测试当前字符串是否为16进制数用字符 + * @param str 字符串 + * @param length 字符串长度 + */ + template + bool isxdigit(const T *str,int length) + { + if(!str||length<=0) + return(false); + + while(*str&&length) + { + if(!isxdigit(*str)) + return(false); + + ++str; + --length; + } + + return(true); + } + + /** + * 是否为不显示可打印字符(' ','\t','\r','\f','\v','\n') + */ + template + bool isspace(const T ch) + { + return(ch==' '||ch=='\t'||ch=='\r'||ch=='\f'||ch=='\v'||ch=='\n'); + } + + /** + * 测试当前字符是否为字母或数字 + */ + template + bool isalnum(const T ch) + { + return(isalpha(ch)||isdigit(ch)); + } + + /** + * 测试当前字符是否为代码可用字符(仅字母,数字,下划线,常用于文件名之类) + */ + template + bool iscodechar(const T ch) + { + return(isalnum(ch)||ch=='_'); + } + + /** + * 测试当前字符是否为BASE64编码字符 + */ + template + bool isbase64(const T c) + { + return (c == 43 || // + + (c >= 47 && c <= 57) || // /-9 + (c >= 65 && c <= 90) || // A-Z + (c >= 97 && c <= 122)); // a-z + } + + /** + * 如果当前字符为大写英文字符,则转换为小写 + */ + template + T tolower(const T ch) + { + if(ch>='A'&&ch<='Z') + return ch+('a'-'A'); + else + return ch; + } + + /** + * 如果当前字符为小写英文字符,则转换为大写 + */ + template + T toupper(const T ch) + { + if(ch>='a'&&ch<='z') + return ch+('A'-'a'); + else + return ch; + } + + /** + * 比较两个字符的大小(英文不区分大小写) + */ + template + int chricmp(S src,D dst) + { + return tolower(src)-tolower(dst); + } + + /** + * 对宽字符串计算字串长度 + * @param str 要计算长度的字符串指针 + * @return 字符串长度 + */ + template + int strlen(const T *str) + { + if(str&&*str) + { + const T *start=str; + + while(*str) + ++str; + + return int(str-start); + } + + return(0); + } + + /** + * 对宽字符串计算字串长度 + * @param str 要计算长度的字符串指针 + * @param max_len 最大长度 + * @return 字符串长度 + */ + template + int strlen(const T *str,int max_len) + { + if(str&&*str) + { + const T *start=str; + + do + { + ++str; + --max_len; + + }while(max_len>0&&*str); + + return int(str-start); + } + + return(0); + } + + /** + * 复制字符串,并指定最大长度 + * @param dst 目标字符串 + * @param count 目标字符串最大多少个字符 + * @param src 源字符串 + * @return 字符串长度(<0表示出错) + */ + template + int strcpy(T *dst,int count,const T *src) + { + if(!dst)return(-1); + + if(!src||!(*src)||count<=0) + { + //没什么好复制的 + *dst=0; + return(0); + } + + if(dst==src) + return(-1); + + if(!src||!(*src)) + { + *dst=0; + return(-2); + } + + T *start=dst; + + while(*src&&count) + { + *dst=*src; + ++dst; + ++src; + --count; + } + + if(count>0) + *dst=0; + + return(dst-start); + } + + /** + * 复制字符串,并指定最大长度 + * @param dst 目标字符串 + * @param dst_count 目标字符串最大多少个字符 + * @param src 源字符串 + * @param count 最多复制多少个字符 + * @return 字符串长度(<0表示出错) + */ + template + int strcpy(T *dst,int dst_count,const T *src,int count) + { + if(!dst)return(-1); + + if(!src||!(*src)||dst_count<=0||count<=0) + { + //没什么好复制的 + *dst=0; + return(0); + } + + if(dst==src) + return(-1); + + T *start=dst; + + while(*src&&dst_count&&count) + { + *dst=*src; + ++dst; + ++src; + --dst_count; + --count; + } + + if(dst_count) + *dst=0; + + return(dst-start); + } + + /** + * 在字符串str1内查找另一个字符串str2 + * @param str1 完整的字符串 + * @param size1 str1最大查找字符 + * @param str2 要查找的字符串 + * @param size2 str2长度 + * @return str2在str1中所在位置的指针 + */ + template + T1 *strstr(T1 *str1,const uint size1,T2 *str2,const uint size2) + { + if(!str1||!str2)return(nullptr); + if(!*str1||!*str2)return(nullptr); + if(size1<=0)return(nullptr); + if(size2<=0)return(nullptr); + + T1 *cp = str1; + T1 *end= str1+size1-size2; + T1 *s1, *s2; + uint s; + + while (*cp&&cp<=end) + { + s1 = cp; + s2 = (T1 *)str2; + + s=size2; + while ( s && !(*s1-*s2) ) + ++s1, ++s2,--s; + + if(!s) + return(cp); + + ++cp; + } + + return(nullptr); + } + + + /** + * 在字符串str1内查找另一个字符串str2(从后向前) + * @param str1 完整的字符串 + * @param size1 str1最大查找字符 + * @param str2 要查找的字符串 + * @param size2 str2长度 + * @return str2在str1中所在位置的指针 + */ + template + T1 *strrstr(T1 *str1,const uint size1,T2 *str2,const uint size2) + { + if(!str1||!str2)return(nullptr); + if(!*str1||!*str2)return(nullptr); + if(size1<=0)return(nullptr); + if(size2<=0)return(nullptr); + + T1 *cp = str1+size1-size2; + T1 *s1, *s2; + uint s; + + while (*cp&&cp>str1) + { + s1 = cp; + s2 = (T1 *)str2; + + s=size2; + while ( s && !(*s1-*s2) ) + ++s1, ++s2,--s; + + if (!s) + return(cp); + + --cp; + } + + return(nullptr); + } + + /** + * 在字符串str1内查找另一个字符串str2,忽略大小写 + * @param str1 完整的字符串 + * @param size1 str1的长度 + * @param str2 要查找的字符串 + * @param size2 str2的长度 + * @return str2在str1中所在位置的指针 + */ + template + T *stristr(T *str1,const uint size1,T *str2,const uint size2) + { + T *cp = (T *) str1; + T *s1, *s2; + + if ( !*str2) + return (T *)str1; + + while (*cp) + { + s1 = cp; + s2 = (T *) str2; + + while ( *s1 && *s2 ) + { + if(*s1!=*s2) + { + if(*s1>='a'&&*s1<='z') + { + if(*s1!=*s2-('A'-'a')) + break; + } + else + if(*s1>='A'&&*s1<='Z') + { + if(*s1!=*s2+('A'-'a')) + break; + } + else + break; + } + + s1++, s2++; + } + + if (!*s2) + return(cp); + + ++cp; + } + + return(0); + } + + /** + * 复制一个字符到当前字符串后面 + * @param dst 目标字符串 + * @param max_count 目标字符串最大长度 + * @param ch 源字符 + */ + template + void strcat(T *dst,int max_count,const T ch) + { + if(!dst||!ch)return; + + while(*dst&&max_count) + { + ++dst; //找到结束 + --max_count; + } + + if(max_count>=0) + { + *dst++=ch; + *dst=0; + } + } + + /** + * 复制一个字符串到当前字符串后面,并指定最大长度 + * @param dst 目标字符串 + * @param max_count 目标字符串最大长度 + * @param src 要追加的源字符串 + * @param count 源字符串最大长度 + * @return 字符串长度(<0表示出错) + */ + template + int strcat(T *dst,int max_count,const T *src,int count) + { + if(!dst||!src||!(*src)||count<=0)return(-1); + + T *start=dst; + + while(*dst&&max_count) + { + ++dst; //找到结束 + --max_count; + } + + while(*src&&max_count&&count) + { + *dst=*src; + ++dst; + ++src; + --count; + --max_count; + } + + if(max_count>=0) + *dst=0; + + return(dst-start); + } + + /** + * 在字符串中查找某个字符 + * @param str 字符串 + * @param ch 字符 + * @return 查找到的位置指针 + */ + template + TS *strchr(TS *str,TC ch) + { + if(!str||!(*str)||ch==0)return(nullptr); + + while(*str) + { + if(*str==ch) + return(str); + else + ++str; + } + + return(nullptr); + } + + /** + * 在字符串中查找某个字符,指定字符串最大长度 + * @param str 字符串 + * @param ch 字符 + * @param n 字符串长度 + * @return 查找到的位置指针 + */ + template + TS *strchr(TS *str,TC ch,int n) + { + if(!str||!(*str)||ch==0||n<=0)return(nullptr); + + while(*str&&n--) + { + if(*str==ch) + return(str); + else + ++str; + } + + return(nullptr); + } + + /** + * 在字符串中查找某个字符 + * @param str 字符串 + * @param ch 字符列表 + * @param ch_count 字符个数 + * @return 查找到的位置指针 + */ + template + TS *strchr(TS *str,TC *ch,const int ch_count) + { + if(!str||!(*str)||!ch||!(*ch)||ch_count<=0)return(nullptr); + + while(*str) + { + if(strchr(ch,*str,ch_count)) + return(str); + + ++str; + } + + return(nullptr); + } + + /** + * 在字符串中从结尾处开始查找某个字符 + * @param str 字符串 + * @param len 字符串长度 + * @param ch 字符 + * @return 查找到的位置指针 + */ + template + TS *strrchr(TS *str,const int len,const TC ch) + { + if(!str||!(*str)||len<=0||ch==0)return(nullptr); + + TS *ep=str+len-1; + + while(ep>=str) + { + if(*ep==ch) + return ep; + + --ep; + } + + return(nullptr); + } + + /** + * 在字符串中从结尾处开始查找某个字符 + * @param str 字符串 + * @param len 字符串长度 + * @param ch 字符 + * @param ch_count 字符个数 + * @return 查找到的位置指针 + */ + template + TS *strrchr(TS *str,const int len,const TC *ch,const int ch_count) + { + if(!str||!(*str)||len<=0||!ch||!(*ch)||ch_count<=0)return(nullptr); + + TS *ep=str+len-1; + + while(ep>=str) + { + if(strchr(ch,*ep,ch_count)) + return ep; + + --ep; + } + + return(nullptr); + } + + /** + * 在字符串中从结尾处开始查找某个字符 + * @param str 字符串 + * @param len 字符串长度 + * @param off 起始查找位置(倒数) + * @param ch 字符 + * @return 查找到的位置指针 + */ + template + TS *strrchr(TS *str,const int len,const int off,const TC ch) + { + if(!str||!(*str)||len<=0||off>=len||ch==0)return(nullptr); + + TS *ep=str+len-1-off; + + while(ep>=str) + { + if(*ep==ch) + return ep; + + --ep; + } + + return(nullptr); + } + + /** + * 在字符串中从结尾处开始查找某个字符 + * @param str 字符串 + * @param len 字符串长度 + * @param off 起始查找位置(倒数) + * @param ch 字符 + * @param ch_count 字符个数 + * @return 查找到的位置指针 + */ + template + TS *strrchr(TS *str,const int len,const int off,const TC *ch,const int ch_count) + { + if(!str||!(*str)||len<=0||off>=len||!ch||!(*ch)||ch_count<=0)return(nullptr); + + TS *ep=str+len-1-off; + + while(ep>=str) + { + if(strchr(ch,*ep,ch_count)) + return ep; + + --ep; + } + + return(nullptr); + } + + /** + * 比较两个字符串的大小 + * @param src 要比较的字符串 + * @param dst 要比较的字符串 + * @return -1 src < dst + * @return 0 src == dst + * @return +1 src > dst + */ + template + int strcmp(S *src,D *dst) + { + if(!src) + { + if(!dst)return(0); + else return(-1); + } + + if(!dst)return(1); + + while((*src)&&(*dst)&&(*src==*dst)) + { + ++src; + ++dst; + } + + return(*src-*dst); + } + + /** + * 比较两个字符串的大小 + * @param src 要比较的字符串1 + * @param src_size 要比较的字符串1长度 + * @param dst 要比较的字符串2 + * @param dst_size 要比较的字符串2 + * @return -1 src < dst + * @return 0 src == dst + * @return +1 src > dst + */ + template + int strcmp(S *src,int src_size,D *dst,int dst_size) + { + if(!src) + { + if(!dst)return(0); + else return(-1); + } + + if(!dst)return(1); + + if(src_size<=0) + { + if(dst_size<=0)return(0); + else return(-1); + } + + if(dst_size<=0)return(1); + + while((src_size)&&(dst_size)&&(*src==*dst)) + { + ++src; + ++dst; + + --src_size; + --dst_size; + } + + if(src_size) + { + if(dst_size) + return(*src-*dst); + else + return 1; + } + + if(dst_size) + return -1; + else + return 0; + } + + /** + * 比较两个字符串的大小,并指定最大比较长度 + * @param src,dst 要比较的字符串 + * @param count 比较的最大长度 + * @return -1 src < dst + * @return 0 src == dst + * @return +1 src > dst + */ + template + int strcmp(S *src,D *dst,int count) + { + if(count<=0)return(0); + + if(!src) + { + if(!dst)return(0); + else return(-1); + } + + if(!dst)return(1); + + while(count&&(*src)&&(*dst)&&(*src==*dst)) + { + ++src; + ++dst; + --count; + } + + if(count==0) + return(0); + + return(*src-*dst); + } + + /** + * 比较两个字符串的大小(英文不区大小写) + * @param src,dst 要比较的字符串 + * @return -1 src < dst + * @return 0 src == dst + * @return +1 src > dst + */ + template + int stricmp(S *src,D *dst) + { + if(!src) + { + if(!dst)return(0); + else return(-1); + } + + if(!dst)return(1); + + int gap; + + while(*src&&*dst) + { + gap=chricmp(*src,*dst); + + if(gap) + return gap; + + ++src; + ++dst; + } + + return(int(*src)-int(*dst)); + } + + /** + * 比较两个字符串的大小(英文不区大小写) + * @param src 要比较的字符串1 + * @param src_size 要比较的字符串1长度 + * @param dst 要比较的字符串2 + * @param dst_size 要比较的字符串2 + * @return -1 src < dst + * @return 0 src == dst + * @return +1 src > dst + */ + template + int stricmp(S *src,int src_size,D *dst,int dst_size) + { + if(!src) + { + if(!dst)return(0); + else return(-1); + } + + if(!dst)return(1); + + if(src_size<=0) + { + if(dst_size<=0)return(0); + else return(-1); + } + + if(dst_size<=0)return(1); + + int gap; + + while(src_size&&dst_size) + { + gap=chricmp(*src,*dst); + + if(gap) + return gap; + + ++src; + ++dst; + --src_size; + --dst_size; + } + + if(dst_size<=0||src_size<=0) + return(0); + + if(src_size) + { + if(dst_size) + return chricmp(*src,*dst); + else + return 1; + } + + if(dst_size) + return -1; + else + return 0; + } + + /** + * 比较两个字符串的大小(英文不区大小写) + * @param src,dst 要比较的字符串 + * @param count 比较的最大长度 + * @return -1 src < dst + * @return 0 src == dst + * @return +1 src > dst + */ + template + int stricmp(S *src,D *dst,int count) + { + if(!src) + { + if(!dst)return(0); + else return(-1); + } + + if(!dst)return(1); + + int gap; + + while((count)&&(*src)&&(*dst)) + { + gap=chricmp(*src,*dst); + + if(gap) + return gap; + + ++src; + ++dst; + --count; + } + + if(count==0) + return(0); + + return(*src-*dst); + } + + /** + * 字符集专用比较函数,只比较字母与数字,无视各种符号,无视大小写 + */ + template + int charset_cmp(S *src,D *dst) + { + if(!src) + { + if(!dst)return(0); + else return(-1); + } + + if(!dst)return(1); + + int gap; + + while(*src&&*dst) + { + if(!isalnum(*src)){++src;continue;} + if(!isalnum(*dst)){++dst;continue;} + + gap=chricmp(*src,*dst); + + if(gap) + return gap; + + ++src; + ++dst; + } + + return(*src-*dst); + } + + /** + * 截去字符串前端所有的空格、换行等符号字符 + * @param src 源字符串指针 + * @param len 源字符串长度 + * @return 新的字符串,需自行delete[] + */ + template + T *trimleft(T *src,int &len) + { + const T *p=src; + + while(*p&&isspace(*p)&&len) + { + p++; + len--; + } + + if(len<=0) + return(0); + + T *new_str=new T[len+1]; + + memcpy(new_str,p,len*sizeof(T)); + new_str[len]=0; + return new_str; + } + + /** + * 截去字符串尾端所有的空格、换行等符号字符 + */ + template + T *trimright(T *src,int &len) + { + const T *p=src+len-1; + + while(isspace(*p)&&len) + { + p--; + len--; + } + + if(len<=0) + return(0); + + T *new_str=new T[len+1]; + + memcpy(new_str,src,len*sizeof(T)); + new_str[len]=0; + return new_str; + } + + /** + * 截去字符串前端和尾端的所有空格、换行符等符号 + */ + template + T *trim(T *src,int &len) + { + const T *sp=src; + const T *ep=src+len-1; + + while(*sp&&isspace(*sp)&&len) + { + ++sp; + --len; + } + + while(isspace(*ep)&&len) + { + --ep; + --len; + } + + if(len<=0) + return(0); + + T *new_str=new T[len+1]; + + memcpy(new_str,sp,len*sizeof(T)); + new_str[len]=0; + return new_str; + } + + /** + * 给一个文件名更改扩展名 + * @param old_filename 原始文件名称 + * @param new_filename 新文件名称 + * @param max_len 文件名最大长度以 + * @param new_extname 新扩展名(不带.) + */ + template + void replace_extname(T *new_filename,const T *old_filename,int max_len,const T *new_extname) + { + const T *p=strrchr(old_filename,'.'); + + if(p) + { + strcpy(new_filename,max_len,old_filename,p-old_filename+1); + strcpy(new_filename+(p-old_filename+1),max_len,new_extname); + } + else + { + const int l=strlen(old_filename); + + strcpy(new_filename,max_len,old_filename,l); + new_filename[l]='.'; + strcpy(new_filename+l+1,max_len-1,new_extname); + } + } + + /** + * 给一个文件名更改扩展名 + * @param filename 文件名称 + * @param new_extname 新扩展名(不带.) + */ + template + void replace_extname(T *filename,const T *new_extname) + { + T *p=strrchr(filename,u'.'); + + if(p) + { + strcpy(p+1,new_extname); + } + else + { + strcat(filename,u'.'); + strcat(filename,new_extname); + } + } + + /** + * 创建一个复制 + * @param str 要复制的字符串 + * @param size 字符串长度,-1表示自动测试 + * @return 复制出来的字符串 + */ + template + T *create_copy(const T *str,int size=-1) + { + if(!str)return(0); + + T *copy; + + if(size==-1)size=strlen(str); + + if(size==0)return(0); + + ++size; + + copy=new T[size]; + strcpy(copy,str,size); + + return(copy); + } + + /** + * 将一个字符串中的某个字符全部替换为另一个字符 + * @param string 要处理的字符串 + * @param sch 要被替换掉的字符 + * @param tch 替换后的字符 + * @return 替换的次数 + */ + template + int replace(T *str,const T tch,const T sch) + { + if(!str) + return(0); + + int count=0; + + while(*str) + { + if(*str==sch) + { + *str=tch; + ++count; + } + + ++str; + } + + return(count); + } + + /** + * 将一个字符串中的字母全部改为大写 + * @param src 要处理的字符串 + */ + template + void toupper(T *str) + { + if(!str)return; + + while(*str) + { + if(*str>='a'&&*str<='z') + *str-=32; + + ++str; + } + } + + /** + * 将一个字符串中的字母全部改为小写 + * @param src 要处理的字符串 + */ + template + void tolower(T *str) + { + if(!str)return; + + while(*str) + { + if(*str>='A'&&*str<='Z') + *str+=32; + + ++str; + } + } + + /** + * 将一个字符串中的字母全部改为大写 + * @param src 要处理的字符串 + */ + template + void toupper(const T *src,T *dst) + { + if(!dst)return; + + if(!src) + { + *dst=0; + return; + } + + do + { + if(*src>='a'&&*src<='z') + *dst=*src-32; + else + *dst=*src; + + ++src; + ++dst; + }while(*src); + + *dst=0; + } + + /** + * 将一个字符串中的字母全部改为小写 + * @param src 要处理的字符串 + */ + template + void tolower(const T *src,T *dst) + { + if(!dst)return; + + if(!src) + { + *dst=0; + return; + } + + do + { + if(*src>='A'&&*src<='Z') + *dst=*src+32; + else + *dst=*src; + + ++src; + ++dst; + }while(*src); + + *dst=0; + } + + /** + * 统计在字符串中某个字符的出现次数 + * @param str 字符串 + * @param ch + * @return 出现次数 + */ + template + int stat_char(T *str,T ch) + { + if(!str)return(0); + + int count=0; + + while(*str) + { + if(*str==ch) + ++count; + + ++str; + } + + return(count); + } + + /** + * 统计一个字符串的行数 + */ + template + int stat_line(T *str) + { + if(!str)return(0); + + T *p=str+strlen(str)-1; + + if(*p=='\n')return(stat_char(str,'\n')); + else return(stat_char(str,'\n')+1); + } + + template + bool stoi(S *str,R &result) + { + if(!str) + { + result=0; + return(false); + } + + result=0; + bool zf=true; + + if(*str=='+') + ++str; + + if(*str=='-') + { + zf=false; + ++str; + } + + while(*str&&*str>='0'&&*str<='9') + { + result*=10; + result+=(*str-'0'); + + ++str; + } + + if(!zf) + result=-result; + + return(true); + } + + template + bool stoi(S *str,int size,R &result) + { + if(!str||size<=0) + { + result=0; + return(false); + } + + result=0; + bool zf=true; + + if(*str=='+') + { + ++str; + --size; + } + + if(*str=='-') + { + zf=false; + --str; + --size; + } + + while(size>0&&*str&&*str>='0'&&*str<='9') + { + result*=10; + result+=(*str-'0'); + + ++str; + --size; + } + + if(!zf) + result=-result; + + return(true); + } + + template + bool stou(S *str,R &result) + { + if(!str) + { + result=0; + return(false); + } + + result=0; + + while(*str&&*str>='0'&&*str<='9') + { + result*=10; + result+=(*str-'0'); + + ++str; + } + + return(true); + } + + template + bool stou(S *str,int size,R &result) + { + if(!str||size<=0) + { + result=0; + return(false); + } + + result=0; + + while(size>0&&*str&&*str>='0'&&*str<='9') + { + result*=10; + result+=(*str-'0'); + + ++str; + --size; + } + + return(true); + } + + template + bool xtou(S *str,R &result) + { + if(!str) + { + result=0; + return(false); + } + + result=0; + + while(*str&&isxdigit(*str)) + { + result*=16; + + if(*str>='0'&&*str<='9') + result+=(*str-'0'); + else + if(*str>='a'&&*str<='f') + result+=(*str-'a')+10; + else + if(*str>='A'&&*str<='F') + result+=(*str-'A')+10; + + ++str; + } + + return(true); + } + + template + bool xtou(S *str,int size,R &result) + { + if(!str||size<=0) + { + result=0; + return(false); + } + + result=0; + + while(*str&&isxdigit(*str)) + { + result*=16; + + if(*str>='0'&&*str<='9') + result+=(*str-'0'); + else + if(*str>='a'&&*str<='f') + result+=(*str-'a')+10; + else + if(*str>='A'&&*str<='F') + result+=(*str-'A')+10; + + ++str; + --size; + } + + return(true); + } + + template + bool stof(S *str,R &result) + { + if(!str) + { + result=0; + return(false); + } + + bool zf=true; + + result=0; + + if(*str=='+') + ++str; + + if(*str=='-') + { + zf=false; + ++str; + } + + while(*str&&*str>='0'&&*str<='9') + { + result*=10; + result+=(*str-'0'); + + ++str; + } + + if(*str!='.') + { + if(!zf) + result=-result; + + return(true); + } + + ++str; //跳过小数点 + + R pos=0.1f; + + while(*str&&*str>='0'&&*str<='9') + { + result+=R(*str-'0')*pos; + + pos*=0.1f; + + ++str; + } + + if(!zf) + result=-result; + + return(true); + } + + template + bool stof(S *str,int size,R &result) + { + if(!str||size<=0) + { + result=0; + return(false); + } + + bool zf=true; + + result=0; + + if(*str=='+') + { + ++str; + --size; + } + + if(*str=='-') + { + zf=false; + ++str; + --size; + } + + while(size>0&&*str&&*str>='0'&&*str<='9') + { + result*=10; + result+=(*str-'0'); + + ++str; + --size; + } + + if(*str!='.') + { + if(!zf) + result=-result; + + return(true); + } + + ++str; //跳过小数点 + --size; + + R pos=0.1f; + + while(size>0&&*str&&*str>='0'&&*str<='9') + { + result+=R(*str-'0')*pos; + + pos*=0.1f; + + ++str; + --size; + } + + if(!zf) + result=-result; + + return(true); + } + + /** + * 转换带指数的字符串到数值变量(如"1.0123e-10") + */ + template + bool etof(S *str,R &result) + { + double temp; + + if(!stof(str,temp)) + return(false); + + while(*str!='e'&&*str!='E') + { + if(!*str) + { + result=R(temp); + return(true); + } + + ++str; + } + + if(*str=='e'||*str=='E') + { + double power; + + if(stof(str+1,power)) + { + result=R(temp*pow(10,power)); + + return(true); + } + } + + result=R(temp); + return(false); + } + + /** + * 转换一个字符串到bool型 + * @param str 要转换的字符串 + * @return 转换后的值 + */ + template + bool stob(T *str,bool &value) + { + if(!str) + { + value=false; + return(false); + } + + if(*str=='T'||*str=='t' //true/false + ||*str=='Y'||*str=='y' //yes/no + ||*str=='M'||*str=='m' //male/women + ||*str=='1') //1/0 + { + value=true; + return(true); + } + else + { + value=false; + return(false); + } + } + + /** + * 转换一个有符号整数到字符串 + * @param str 转换后的字符串存放处 + * @param size 存放处可容纳的字符数 + * @param num 要转换的数值 + * @return 转换后的字符串长度 + */ + template + int itos_rl(T *str,int size,const I num) + { + if(!str||size<=0)return(-1); + + T *p=str; + T buf[sizeof(I)*8],*bp; + + I value=num; + + if(value<0) + { + *p++='-'; + --size; + + value=-value; + } + + bp=buf; + + while(true) + { + *bp++=(value%10)+'0'; + + if ((value = value / 10) == 0) + break; + } + + while(bp--!=buf&&size--) + *p++=*bp; + + if(size) + *p=0; + + return(p-str); + } + + /** + * 转换一个有符号整数到字符串 + * @param str 转换后的字符串存放处 + * @param size 存放处可容纳的字符数 + * @param num 要转换的数值 + * @return 转换后的字符串 + */ + template + T *itos(T *str,int size,const I num) + { + itos_rl(str,size,num); + return str; + } + + /** + * 转换一个无符号整数到字符串 + * @param str 转换后的字符串存放处 + * @param size 存放处可容纳的字符数 + * @param value 要转换的数值 + * @return 转换后的字符串 + */ + template + T *utos(T *str,int size,U value) + { + if(!str||size<=0)return(nullptr); + + T *p=str; + T buf[sizeof(U)*8],*bp; + + bp=buf; + + while(true) + { + *bp++=(value%10)+'0'; + + if ((value = value / 10) == 0) + break; + } + + while(bp--!=buf&&size--) + *p++=*bp; + + if(size) + *p=0; + + return(str); + } + + /** + * 转换一个无符号整数到字符串(指定进制) + * @param str 转换后的字符串存放处 + * @param size 存放处可容纳的字符数 + * @param value 要转换的数值 + * @param base 数值进制 + * @param upper 字母用大写 + * @return 转换后的字符串 + */ + template + T *utos(T *str,int size,U value,const uint base,bool upper=true) + { + if(!str||size<=0)return(nullptr); + + T *p=str; + T buf[sizeof(U)*8],*bp; + uint m; + + const uchar A=upper?'A':'a'; + + bp=buf; + + while(true) + { + m=value%base; + + if(m<10) + *bp++=m+'0'; + else + *bp++=m-10+A; + + if ((value = value / base) == 0) + break; + } + + while(bp--!=buf&&size--) + *p++=*bp; + + if(size) + *p=0; + + return(str); + } + + template struct htos_bits + { + template static T *conv(T *str,int size,U value,bool upper); + }; + + template<> struct htos_bits<1>{template static T *conv(T *str,int size,U value,bool upper){return utos(str,size,*(uint8 *)&value,16,upper);}}; + template<> struct htos_bits<2>{template static T *conv(T *str,int size,U value,bool upper){return utos(str,size,*(uint16 *)&value,16,upper);}}; + template<> struct htos_bits<4>{template static T *conv(T *str,int size,U value,bool upper){return utos(str,size,*(uint32 *)&value,16,upper);}}; + template<> struct htos_bits<8>{template static T *conv(T *str,int size,U value,bool upper){return utos(str,size,*(uint64 *)&value,16,upper);}}; + + /** + * 转换一个无符号整数到字符串(以16进制表示) + * @param str 转换后的字符串存放处 + * @param size 存放处可容纳的字符数 + * @param value 要转换的数值 + * @param upper 大小写 + * @return 转换后的字符串 + */ + template + T *htos(T *str,int size,U value,bool upper=true) + { + return htos_bits::template conv(str,size,value,upper); + } + + /** + * 转换一个无符号整数到字符串(以大写16进制表示) + * @param str 转换后的字符串存放处 + * @param size 存放处可容纳的字符数 + * @param value 要转换的数值 + * @return 转换后的字符串 + */ + template T *htos_upper(T *str,int size,U value){return htos(str,size,value,true);} + + /** + * 转换一个无符号整数到字符串(以小写16进制表示) + * @param str 转换后的字符串存放处 + * @param size 存放处可容纳的字符数 + * @param value 要转换的数值 + * @return 转换后的字符串 + */ + template T *htos_lower(T *str,int size,U value){return htos(str,size,value,false);} + + /** + * 转换一个浮点数到字符串 + * @param str 字符串保存指针 + * @param size 字符串保存空间长度 + * @param fsize 小数部分保留长度 + * @param value 要转换的值 + */ + template + T *ftos(T *str,int size,int fsize,F value) + { + const long integer=(long)value; //整数部分 + + T *p=str; + + if(integer==0&&value<0) //如果为-0.xx这种,integer会为0所以不增加-号 + *p++='-'; + + itos(p,size,integer); + + int len=strlen(str); + + if(len>=size) + return(str); + + p=str+len; + + value-=integer; //保留小数部分 + + if(value<0) + value=-value; + + const float min_value=pow(0.1,fsize); + + if(valuemin_value&&len + T *ftos(T *str,int size,F value) + { + return ftos(str,size,4,value); + } + + /** + * 转换一个整数到计算机表示法 + * @param str 字符串保存指针 + * @param size 字符串保存空间长度 + * @param value 要转换的值 + * @return 是否转换成功 + */ + template + bool int_to_size(T *str,int size,V value) + { + const T name[]={'K','M','G','T','P','E','Z','Y','B',0}; + + //ps2014,现有磁带机单机柜容量百PB,按组破EB。以每十年破一个的速度,2034年将接近使用Y。届时将按条件扩大。 + + double new_value=value; + int pos=0; + + while(new_value>=1024&&size--) + { + pos++; + new_value/=1024; + + if(name[pos]==0) + return(false); //太大了 + } + + const float f=new_value; + + ftos(str,size,2,f); + + T *p=str+strlen(str); + + *p++=' '; + if(pos) + *p++=name[pos-1]; + + *p++='B'; + *p=0; + + return(true); + } + + template + int find_str_array(int count,const T **str_array,const T *str) + { + for(int i=1;i(str_array[i],str)==0)return(i); + + return(-1); + } + + /** + * 解析数值阵列字符串到数组,如"1,2,3"或"1 2 3" + * @param str 要解析的字符串 + * @param result 结果数组 + * @param max_count 最大个数 + * @param end_char 结尾字符,默认为0 + * @param end_pointer 结束指针 + * @return 解晰出来的数据数量 + */ + template + int parse_number_array(const T *str,I *result,int max_count,const T end_char=0,const T **end_pointer=0) + { + if(!str||!result||max_count<=0)return(-1); + + const T *p,*sp; + int count=0; + + sp=str; + p=sp; + + while(*p&&*p!=end_char) + { + if(IS_FUNC(*p)) + { + p++; + continue; + } + + if(STOV(sp,*result)) + { + ++count; + --max_count; + + if(max_count<=0) + { + if(end_pointer) + *end_pointer=p; + + return(count); + } + + ++result; + + ++p; + sp=p; + + continue; + } + + if(end_pointer) + *end_pointer=p; + + return count; + } + + if(p>sp) + { + STOV(sp,*result); + ++count; + } + + if(end_pointer) + *end_pointer=p; + + return(count); + } + + template inline int parse_float_array(const T *str,I *result,int max_count,const T end_char=0,const T **end_pointer=0){return parse_number_array(str,result,max_count,end_char,end_pointer);} + template inline int parse_int_array (const T *str,I *result,int max_count,const T end_char=0,const T **end_pointer=0){return parse_number_array(str,result,max_count,end_char,end_pointer);} + template inline int parse_uint_array (const T *str,I *result,int max_count,const T end_char=0,const T **end_pointer=0){return parse_number_array(str,result,max_count,end_char,end_pointer);} + template inline int parse_xint_array (const T *str,I *result,int max_count,const T end_char=0,const T **end_pointer=0){return parse_number_array(str,result,max_count,end_char,end_pointer);} + + /** + * 解析数值阵列字符串到数组,如"1,2,3"或"1 2 3" + * @param str 要解析的字符串 + * @param str_len 字符串的长度 + * @param result_list 结果数组 + * @return 解晰出来的数据数量 + * @return -1 出错 + */ + template + int parse_number_array(const T *str,const int str_len,SET &result_list) + { + if(!str||str_len<=0)return(-1); + + const T *p,*sp; + int len=str_len; + int count=0; + I result; + + sp=str; + p=sp; + + while(*p&&len) + { + --len; + if(IS_FUNC(*p)) + { + p++; + continue; + } + + if(STOV(sp,result)) + { + ++count; + + result_list.Add(result); + + ++p; + sp=p; + + continue; + } + + return count; + } + + if(p>sp) + { + STOV(sp,result); + result_list.Add(result); + ++count; + } + + return(count); + } + + template inline int parse_float_array (const T *str,const int len,SET &result_list){return parse_number_array(str,len,result_list);} + template inline int parse_int_array (const T *str,const int len,SET &result_list){return parse_number_array(str,len,result_list);} + template inline int parse_uint_array (const T *str,const int len,SET &result_list){return parse_number_array(str,len,result_list);} + template inline int parse_xint_array (const T *str,const int len,SET &result_list){return parse_number_array(str,len,result_list);} + + /** + * 按指定分隔符拆分字符串为多个字符串 + * @param str 要拆分的字符串 + * @param str_len 字符串长度 + * @param sc 分隔字符 + * @param result_list 拆分后的字符串保存的列表 + * @return 拆分出来的字符串数量 + * @return -1 出错 + */ + template + int split_string(const T *str,const int str_len,const T &sc,S &result_list) + { + if(!str||!(*str))return(-1); + if(str_len<=0)return(-1); + if(sc==0)return(-1); + + const T *p,*sp; + int len=str_len; + int count=0; + + sp=str; + p=sp; + + while(*p&&len) + { + --len; + + if(*p!=sc) + { + ++p; + continue; + } + + result_list.Add(I(sp,p-sp)); + + ++p; + sp=p; + ++count; + } + + if(p>sp) + { + result_list.Add(I(sp,p-sp)); + ++count; + } + + return(count); + } + + /** + * 将一个字符串转换成对应的枚举值 + * @param list 对应的字符串列表,以0结尾,如:const char *target_list[]={"self","line","circle","\0"}; + * @param str 要查找的字节串 + * @return 返回查找出的序号,-1表示失败 + */ + template int string_to_enum(const T **list,const T *str) + { + if(!str||!list)return(-1); + + int index=0; + + do + { + if(stricmp(list[index],str)==0) + return index; + + ++index; + }while(*list[index]); + + return(-1); + } + + /** + * 检测字符串是否符合代码命名规则(仅可使用字母和数字、下划线,不能使用数字开头) + */ + template bool check_codestr(const T *str) + { + if(!str)return(false); + + if((!isalpha(*str))&&(*str!='_')) //不是字母或下划线 + return(false); + + ++str; + + if(!(*str)) //不能仅一个字符 + return(false); + + while(*str) + if(!iscodechar(*str++)) + return(false); + + return(true); + } + + /** + * 检测字符串是否包含不可程序使用字符 + */ + template bool check_error_char(const T *str) + { + if(!str)return(false); + + //const char err_chr[]=u8R"( <>,/\|?%$#@`':"*&!)"; + constexpr char err_chr[] = { ' ', + '<', + '>', + ',', + '/', + '\\', + '|', + '?', + '%', + '$', + '#', + '@', + '`', + '\'', + ':', + '"', + '*', + '&', + '!', + 0}; + const char *sp; + + while(*str) + { + if(isspace(*str)) + return(false); + + sp=err_chr; + + while(*sp) + { + if(*str==*sp) + return(false); + + ++sp; + } + + ++str; + } + + return(true); + } + + /** + * 解晰一个10进制字符到数值 + * @param ch 字符 + * @param num 进制 + * @return 解析出来的值 + */ + inline int parse_dec_number_char(const int ch) + { + if(ch>='0'&&ch<='9') + return ch-'0'; + + return 0; + } + + /** + * 解析一个多进制字符到数值 + * @param ch 字符 + * @return 解析出来的值 + */ + template + inline int parse_number_char(const T ch) + { + if(ch>='0'&&ch<='9') + return ch-'0'; + + if(ch>='a'&&ch<=('z'+NUM-11)) + return 10+ch-'a'; + + if(ch>='A'&&ch<=('Z'+NUM-11)) + return 10+ch-'A'; + + return(0); + } + + /** + * 解晰一个16进制数值字符串 + * @param dst 解晰出来的原始数据存入处 + * @param src 用来解晰的16进制数值字符串 + * @param size 原始数据字节数/2 + */ + template + inline void ParseHexStr(uint8 *dst,const T *src,const int size) + { + for(int i=0;i(*src)<<4; + ++src; + *dst|=parse_number_char<16,T>(*src); + ++src; + ++dst; + } + } + + /** + * 将一个16进制数值字符串转换成原始数据 + * @param str 16进制数值字符串 + * @param hc 解晰出来的原始数据存入处 + */ + template + void ParseHexStr(HC &hc,const T *str) + { + ParseHexStr((uint8 *)&hc,(const uint8 *)str,sizeof(HC)); + } + + /** + * 将一串原始数据转转成16进制数值字符串 + * @param str 16进制数值字符串存入处 + * @param src 原始的数据 + * @param size 原始数据字节长度 + * @param hexstr 用于转换的16进制字符 + * @param gap_char 间隔字符 + */ + template + void DataToHexStr(T *str,const uint8 *src,const int size,const char *hexstr,const T gap_char=0) + { + int i; + + for(i=0;i>4]; + ++str; + *str=hexstr[ (*src)&0x0F ]; + ++str; + + ++src; + } + + *str=0; + } + + template void DataToLowerHexStr(T *str,const uint8 *src,const int size,const T gap_char=0){DataToHexStr(str,src,size,LowerHexChar,gap_char);} + template void DataToUpperHexStr(T *str,const uint8 *src,const int size,const T gap_char=0){DataToHexStr(str,src,size,UpperHexChar,gap_char);} + + /** + * 将一串原始数据转转成16进制数值字符串 + * @param str 16进制数值字符串存入处 + * @param hc 原始的数据 + * @param hexstr 用于转换的16进制字符 + * @param gap_char 间隔字符 + */ + template + void DataToHexStr(T *str,const HC &hc,const T *hexstr,const T gap_char=0) + { + return DataToHexStr(str,(const uint8 *)&hc,sizeof(hc),hexstr,gap_char); + } + + template void ToUpperHexStr(T *str,const HC &hc,const T gap_char=0){DataToHexStr(str,hc,UpperHexChar,gap_char);} + template void ToLowerHexStr(T *str,const HC &hc,const T gap_char=0){DataToHexStr(str,hc,LowerHexChar,gap_char);} + + template void ToUpperHexStr(T *str,const void *data,const int size,const T gap_char=0){DataToHexStr(str,(const uint8 *)data,size,UpperHexChar,gap_char);} + template void ToLowerHexStr(T *str,const void *data,const int size,const T gap_char=0){DataToHexStr(str,(const uint8 *)data,size,LowerHexChar,gap_char);} + }//namespace hgl +#endif//HGL_STR_TEMPLATE_INCLUDE diff --git a/inc/hgl/TypeFunc.h b/inc/hgl/TypeFunc.h new file mode 100644 index 00000000..d4d748a4 --- /dev/null +++ b/inc/hgl/TypeFunc.h @@ -0,0 +1,611 @@ +#ifndef HGL_TYPE_FUNC_INCLUDE +#define HGL_TYPE_FUNC_INCLUDE + +#include +#include +namespace hgl +{ + #define HGL_CONVER_TO_MEM_ALIGN(x) ((((x)+HGL_MEM_ALIGN-1)/HGL_MEM_ALIGN)*HGL_MEM_ALIGN) //内存对齐转换宏 + + #ifndef NULL + #define NULL 0 + #endif// + + template + inline T *zero_new(const int count) + { + T *result=new T[count]; + + if(!result) + return(nullptr); + + memset(result,0,count*sizeof(T)); + return result; + } + + template + inline T *zero_malloc(const int count) + { + T *result=hgl_malloc(count*sizeof(T)); + + if(!result) + return(nullptr); + + memset(result,0,count*sizeof(T)); + return result; + } + + template + inline void hgl_call_construct(T *obj) //呼叫构造函数 + { + new (static_cast(obj)) T(); + } + + #define HGL_BIT(n) (1<<(n)) + #define HGL_64BIT(n) (1L<<(n)) + + template + inline bool hgl_is_one(const T value,int off) + { + return value&(1< + inline bool hgl_is_zero(const T value,int off) + { + return !(value&(1< + inline void hgl_set_one(T &value,int off) + { + value|=(1< + inline void hgl_set_zero(T &value,int off) + { + value&=~T(1< + inline void hgl_set_bit(T &value,int off,bool b) + { + if(b) + hgl_set_one(value,off); + else + hgl_set_zero(value,off); + } + + template + inline int hgl_bit_count(const T value) + { + int count=0; + T bit=1; + + for(int i=0;i + inline int hgl_bit_count(const T value,int size) + { + int count=0; + T bit=1; + + for(int i=0;i T HGL_INTEGER_MAX(); + template T HGL_INTEGER_MIN(); + + template<> inline uint8 HGL_INTEGER_MAX() { return HGL_U8_MAX; } + template<> inline uint16 HGL_INTEGER_MAX() { return HGL_U16_MAX; } + template<> inline uint32 HGL_INTEGER_MAX() { return HGL_U32_MAX; } + template<> inline uint64 HGL_INTEGER_MAX() { return HGL_U64_MAX; } + + template<> inline int8 HGL_INTEGER_MAX() { return HGL_S8_MAX; } + template<> inline int16 HGL_INTEGER_MAX() { return HGL_S16_MAX; } + template<> inline int32 HGL_INTEGER_MAX() { return HGL_S32_MAX; } + template<> inline int64 HGL_INTEGER_MAX() { return HGL_S64_MAX; } + + template<> inline int8 HGL_INTEGER_MIN() { return HGL_S8_MIN; } + template<> inline int16 HGL_INTEGER_MIN() { return HGL_S16_MIN; } + template<> inline int32 HGL_INTEGER_MIN() { return HGL_S32_MIN; } + template<> inline int64 HGL_INTEGER_MIN() { return HGL_S64_MIN; } + + /** + * 星期每天枚举 + */ + enum WeekDay + { + weekNone=-1, + + weekSunday, ///<星期天 + weekMonday, ///<星期一 + weekTuesday, ///<星期二 + weekWednesday, ///<星期三 + weekThursday, ///<星期四 + weekFriday, ///<星期五 + weekSaturday, ///<星期六 + + weekEnd + }; + + /** + * 月份枚举 + */ + enum Month + { + monthNone=0, + + monthJanuary, ///<一月 + monthFebruary, ///<二月 + monthMarch, ///<三月 + monthApril, ///<四月 + monthMay, ///<五月 + monthJune, ///<六月 + monthJuly, ///<七月 + monthAugust, ///<八月 + monthSeptember, ///<九月 + monthOctober, ///<十月 + monthNovember, ///<十一月 + monthDecember, ///<十二月 + + monthEnd + }; + + constexpr uint HGL_TIME_ONE_SECOND =1; + constexpr uint HGL_TIME_HALF_MINUTE =30; + constexpr uint HGL_TIME_ONE_MINUTE =60; + constexpr uint HGL_TIME_HALF_HOUR =30*HGL_TIME_ONE_MINUTE; + constexpr uint HGL_TIME_ONE_HOUR =60*HGL_TIME_ONE_MINUTE; + constexpr uint HGL_TIME_HALF_DAY =12*HGL_TIME_ONE_HOUR; + constexpr uint HGL_TIME_ONE_DAY =24*HGL_TIME_ONE_HOUR; + constexpr uint HGL_TIME_ONE_WEEK =7*HGL_TIME_ONE_DAY; + constexpr uint HGL_TIME_ONE_YEAR =365*HGL_TIME_ONE_DAY; + + constexpr uint HGL_HOUR_HALF_DAY =12; + constexpr uint HGL_HOUR_ONE_DAY =24; + + constexpr uint HGL_DAY_ONE_WEEK =7; + constexpr uint HGL_DAY_ONE_YEAR =365; + + constexpr uint HGL_MONTH_ONE_YEAR =12; + + constexpr uint HGL_MILLI_SEC_PRE_SEC =1000; //毫秒 + constexpr uint HGL_MICRO_SEC_PER_SEC =1000*1000; //微秒 + constexpr uint HGL_NANO_SEC_PER_SEC =1000*1000*1000; //纳秒 + + constexpr char LowerHexChar[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; ///<小写16进制字符 + constexpr char UpperHexChar[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; ///<大写16进制字符 + + constexpr double HGL_E =2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274; //欧拉数(自然对数的底数) + constexpr double HGL_LOG2E =1.44269504088896340736; + constexpr double HGL_LOG10E =0.434294481903251827651; + constexpr double HGL_LN2 =0.693147180559945309417; + constexpr double HGL_LN10 =2.30258509299404568402; + constexpr double HGL_PI =3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068; + constexpr double HGL_PI_2 =1.57079632679489661923; + constexpr double HGL_PI_4 =0.785398163397448309616; + constexpr double HGL_PI_3_4 =2.356194490192344928938; + constexpr double HGL_1_PI =0.318309886183790671538; + constexpr double HGL_2_PI =0.636619772367581343076; + constexpr double HGL_2_SQRTPI =1.12837916709551257390; + constexpr double HGL_SQRT2 =1.41421356237309504880168872420969807; + constexpr double HGL_SQRT1_2 =0.707106781186547524401; + + constexpr double HGL_COS_ANG_0 =1; + constexpr double HGL_COS_ANG_45 =0.707106781187; + constexpr double HGL_COS_ANG_90 =0; + constexpr double HGL_COS_ANG_135=-0.707106781187; + constexpr double HGL_COS_ANG_180=-1; + constexpr double HGL_COS_ANG_225=-0.707106781187; + constexpr double HGL_COS_ANG_270=0; + constexpr double HGL_COS_ANG_315=0.707106781187; + + constexpr double HGL_GOLDEN_RATIO =0.61803398874989484820458683436563811772030917980576;//黄金比例 + constexpr double HGL_SILVER_RATIO =2.4142135623730950488; //白银比例 + + constexpr double HGL_SPEED_OF_SOUND =331.3f; //音速(米/秒) + constexpr double HGL_SPEED_OF_LIGHT =299792458; //光速(米/秒) + + constexpr double HGL_ABSOLUTE_ZERO =-273.15f; //绝对零度 + + constexpr double HGL_UNIVERSAL_GRAVITATION =6.67384e-11; //万有引力常数 + + constexpr double HGL_EARTH_GRAVITATIONAL_ACCELERATION =9.80665; //地球上的重力加速度(牛顿) + constexpr double HGL_EARTH_MASS =5.9722e+24; //地球质量 + constexpr double HGL_EARTH_RADIUS =6371000; //地球半径(米) + + /** + * 物体万有引力计算 + * @param m1 星球质量 + * @param m2 物体质量 + * @param length 到星球中心的距离 + */ + template + inline T UniversalGravitation(const T m1,const T m2,const T length) + { + return HGL_UNIVERSAL_GRAVITATION*((m1*m2)/(length*length)); + } + + /** + * 星球重力加速度计算
+ * 理论上: (地球质量*万有引力常数)/(地球半径的平方)=地球上的重力加速度 + * @param m 星球质量 + * @param raidus 星球半径 + * @return 星球的重力加速度(牛顿) + */ + template + inline T UniversalGravitation(const T m,const T radius) + { + return (HGL_UNIVERSAL_GRAVITATION*m)/(radius*radius); + } + + /** + * 向心力计算 + * @param m 质量 + * @param v 速度 + * @param r 距离 + */ + template + inline T CentripetalForce(const T m,const T v,const T r) + { + return (m*v*v)/r; + } + + /** + * 加速度计算 + * @param power 推力 + * @param weight 质量 + */ + template + inline T AddSpeed(const T &power,const T &weight) + { + return power/weight; + } + + /** + * 物体运动质量计算(物体运动越快,质量越大) + * @param m0 静止质量 + * @param v 运动速度 + */ + template + inline T RunWeight(const T &m0,const T &v) + { + return m0/sqrt(1-(v*v)/(HGL_SPEED_OF_LIGHT*HGL_SPEED_OF_LIGHT)); + } + + inline float half_to_float(const uint16 &h) + { + return ((h&0x8000)<<16) | (((h&0x7c00)+0x1C000)<<13) | ((h&0x03FF)<<13); + } + + inline uint16 float_to_half(const float &f) + { + const uint32 x = *((uint32 *)&f); + + return ((x>>16)&0x8000)|((((x&0x7f800000)-0x38000000)>>13)&0x7c00)|((x>>13)&0x03ff); + } + + /** + * 正圆面积计算 + * @param radius 半径 + */ + inline double CircleArea(const double radius) + { + return(radius*radius*HGL_PI); + } + + /** + * 椭圆面积计算 + * @param l_radius 长半径 + * @param s_radius 短半径 + */ + inline double ElipseArea(const double l_radius,const double s_radius) + { + return(l_radius*s_radius*HGL_PI); + } + + /** + * 球体积计算 + * @param radius 球半径 + */ + inline double SphereVolume(const double radius) + { + return(radius*radius*radius*(HGL_PI*4.0f))/3.0f; + } + + /** + * 椭球体积计算 + * @param x_radius x半径 + * @param y_radius y半径 + * @param z_radius z半径 + */ + inline double EllipsoidVolume(const double x_radius,const double y_radius,const double z_radius) + { + return(x_radius*y_radius*z_radius*(HGL_PI*4.0f))/3.0f; + } + + /** + * 取适合正巧大于当前数的2次幂值 + */ + template + inline T power_to_2(T value) + { + T result=1; + + while(result inline void hgl_swap(T &x,T &y) + { + T t; + + memcpy(&t,&x,sizeof(T)); + memcpy(&x,&y,sizeof(T)); + memcpy(&y,&t,sizeof(T)); + } + + template inline T hgl_abs(const T &v){return (v>=0?v:-v);} + + template inline T hgl_min(const T &a,const T &b){return (a>b?b:a);} + template inline T hgl_max(const T &a,const T &b){return (a>b?a:b);} + + template inline T hgl_min(const T *data,int count,T min_value) + { + T value=min_value; + + for(int i=0;i inline T hgl_max(const T *data,int count,T max_value) + { + T value=max_value; + + for(int i=0;ivalue) + value=*data; + + ++data; + } + + return(value); + } + + /** + * 角度转弧度 + */ + inline double hgl_ang2rad(const double ang) + { + return ang*(HGL_PI/180.0f); + } + + /** + * 弧度转角度 + */ + inline double hgl_rad2ang(const double rad) + { + return rad*(180.0f/HGL_PI); + } + + /** + * 浮点数截取小数点后指定位度 + * @param value 要截取的浮点数 + * @param num 要截取的位数 + */ + template + inline T hgl_clip_float(const T value,const int num) + { + if(num<=0) + return int64(value); + + if(value==0)return(0); + + double per=pow(10,num); + + return double(floor(value*per))/per; + } + + /** + * 等值类型复制 + */ + template + inline void hgl_cpy(T &dst,const T &src) + { + memcpy(&dst,&src,sizeof(T)); + } + + /** + * 不同类型数据块复制 + */ + template + inline void hgl_cpy(D *dst,const S *src,const size_t count) + { + for(size_t i=0;i + inline void hgl_typecpy(T *dst,const T *src,const size_t count) + { + memcpy(dst,src,count*sizeof(T)); + } + + /** + * 同类型数据块移动 + */ + template + inline void hgl_typemove(T *dst,const T *src,const size_t count) + { + memmove(dst,src,count*sizeof(T)); + } + + /** + * 指定类型数据块赋值 + */ + template + inline void hgl_set(T *data,const T value,const size_t count) + { + for(size_t i=0;i + inline void hgl_zero(T *data,const size_t count) + { + memset(data,0,count*sizeof(T)); + } + + /** + * 指定类型数据清0 + */ + template + inline void hgl_zero(T &data) + { + memset(&data,0,sizeof(T)); + } +}//namespace hgl + +/** +* 比较处理模板基类 +*/ +template class Comparator ///比较处理模板基类 +{ +public: + + /** + * 比较函数,需被特例化或派生实现 + */ + virtual int compare(const T &a,const T &b)const + { + return 0; // 如 return(a-b); ,但这个函数正确情况下不应该会被调用 + } + + /** + * 交换函数 + */ + virtual void exchange(T &a,T &b) + { + T t; + + memcpy(&t,&a,sizeof(T)); + memcpy(&a,&b,sizeof(T)); + memcpy(&b,&t,sizeof(T)); + } + + /** + * 复制数据 + */ + virtual void cpy(T *t,T *s) + { + memcpy(t,s,sizeof(T)); + } +};//class Comparator + +//针对原生类型的特例化版本,做适当加速 +#define COMPARATOR_ORIGIN_TYPE(type) template<> class Comparator \ + { \ + public: \ + int compare(const type &a,const type &b)const{return a-b;} \ + void exchange(type &a,type &b){type t;t=a;a=b;b=t;} \ + void cpy(type *t,type *s){*t=*s;} \ + }; + + COMPARATOR_ORIGIN_TYPE(hgl::int8) + COMPARATOR_ORIGIN_TYPE(hgl::int16) + COMPARATOR_ORIGIN_TYPE(hgl::int32) + COMPARATOR_ORIGIN_TYPE(hgl::int64) + + COMPARATOR_ORIGIN_TYPE(hgl::uint8) + COMPARATOR_ORIGIN_TYPE(hgl::uint16) + COMPARATOR_ORIGIN_TYPE(hgl::uint32) + COMPARATOR_ORIGIN_TYPE(hgl::uint64) + + COMPARATOR_ORIGIN_TYPE(float) + COMPARATOR_ORIGIN_TYPE(double) + + COMPARATOR_ORIGIN_TYPE(char) + COMPARATOR_ORIGIN_TYPE(wchar_t) + +#if HGL_OS != HGL_OS_Windows + COMPARATOR_ORIGIN_TYPE(u16char) +#endif//HGL_OS != HGL_OS_Windows + + COMPARATOR_ORIGIN_TYPE(char32_t) +#undef COMPARATOR_ORIGIN_TYPE +#endif//HGL_TYPE_FUNC_INCLUDE diff --git a/inc/hgl/algorithm/Math.h b/inc/hgl/algorithm/Math.h new file mode 100644 index 00000000..953ce538 --- /dev/null +++ b/inc/hgl/algorithm/Math.h @@ -0,0 +1,155 @@ +#ifndef HGL_ALGORITHM_VECTOR_MATH_INCLUDE +#define HGL_ALGORITHM_VECTOR_MATH_INCLUDE + +#include + +//注:GLM/CML(OpenGLMode)是列矩阵,计算坐标matrix*pos +// 而MGL是行矩阵,需要反过来pos*matrix + +#include // Game Math and Geometry Library + +namespace hgl +{ + namespace algorithm + { + double Lsin(int angle); ///<低精度sin计算,注意传入的参数为角度而非弧度 + double Lcos(int angle); ///<低精度cos计算,注意传入的参数为角度而非弧度 + void Lsincos(int angle, double &s, double &c); ///<低精度sin+cos计算,注意传入的参数为角度而非弧度 + + /** + * 低精度atan函数 + */ + double inline Latan(double z) + { + constexpr double n1 = 0.97239411f; + constexpr double n2 = -0.19194795f; + + return (n1 + n2 * z * z) * z; + } + + double Latan2(double y, double x); ///<低精度atan2函数 + + inline float length_squared(const Vector2f &v) + { + return (v.x*v.x) + (v.y*v.y); + } + + inline float length_squared_2d(const Vector3f &v) + { + return (v.x*v.x) + (v.y*v.y); + } + + inline float length_squared(const Vector3f &v) + { + return (v.x*v.x) + (v.y*v.y) + (v.z*v.z); + } + + inline float length_squared(const Vector4f &v) + { + return (v.x*v.x) + (v.y*v.y) + (v.z*v.z); + } + + template + inline float length(const T &v) + { + return sqrt(length_squared(v)); + } + + inline float length_2d(const Vector3f &v) + { + return sqrt(length_squared_2d(v)); + } + + template + inline float length_squared(const T1 &v1, const T2 &v2) + { + const float x = (v1.x - v2.x); + const float y = (v1.y - v2.y); + + return x*x + y*y; + } + + template + inline float length(const T1 &v1, const T2 &v2) + { + return sqrt(length_squared(v1, v2)); + } + + inline float length_squared(const Vector3f &v1, const Vector3f &v2) + { + const float x = (v1.x - v2.x); + const float y = (v1.y - v2.y); + const float z = (v1.z - v2.z); + + return x*x + y*y + z*z; + } + + template + inline float length_squared_2d(const T1 &v1, const T2 &v2) + { + const float x = (v1.x - v2.x); + const float y = (v1.y - v2.y); + + return x*x + y*y; + } + + inline float length(const Vector3f &v1, const Vector3f &v2) + { + return sqrt(length_squared(v1, v2)); + } + + template + inline float length_2d(const T1 &v1, const T2 &v2) + { + return sqrt(length_squared_2d(v1, v2)); + } + + inline Vector2f to(const Vector2f &start, const Vector2f &end, float pos) + { + return Vector2f(start.x + (end.x - start.x)*pos, + start.y + (end.y - start.y)*pos); + } + + inline Vector3f to(const Vector3f &start, const Vector3f &end, float pos) + { + return Vector3f(start.x + (end.x - start.x)*pos, + start.y + (end.y - start.y)*pos, + start.z + (end.z - start.z)*pos); + } + + template + inline void to_2d(T &result, const T &start, const T &end, float pos) + { + result.x = start.x + (end.x - start.x)*pos; + result.y = start.y + (end.y - start.y)*pos; + } + + inline float ray_angle_cos(const Vector3f &ray_dir, const Vector3f &ray_pos, const Vector3f &pos) + { + return dot(ray_dir, normalized(pos - ray_pos)); + } + + /** + * 做一个2D旋转计算 + * @param result 结果 + * @param source 原始点坐标 + * @param center 圆心坐标 + * @param ang 旋转角度 + */ + template + inline void rotate2d(T1 &result, const T2 &source, const T3 ¢er, const double ang) + { + double as, ac; + // double nx,ny; + + // as=sin(ang*(HGL_PI/180.0f)); + // ac=cos(ang*(HGL_PI/180.0f)); + //sincos(ang*(HGL_PI/180.0f),&as,&ac); //在80x87指令上,sin/cos是一个指令同时得出sin和cos,所以可以这样做 + Lsincos(ang, as, ac); //低精度sin/cos计算 + + result.x = center.x + ((source.x - center.x)*ac - (source.y - center.y)*as); + result.y = center.y + ((source.x - center.x)*as + (source.y - center.y)*ac); + } + }//namespace algorithm +}//namespace hgl +#endif//HGL_ALGORITHM_VECTOR_MATH_INCLUDE diff --git a/inc/hgl/algorithm/MathMGL.h b/inc/hgl/algorithm/MathMGL.h new file mode 100644 index 00000000..67eb7052 --- /dev/null +++ b/inc/hgl/algorithm/MathMGL.h @@ -0,0 +1,205 @@ +#ifndef HGL_ALGORITHM_VECTOR_MATH_MGL_INCLUDE +#define HGL_ALGORITHM_VECTOR_MATH_MGL_INCLUDE + +#ifdef _MSC_VER +#pragma warning(disable:4244) // double -> int 精度丢失警告 +#endif//_MSC_VER + +#include + +/** + * MathGeoLib + * Game Math and Geometry Library + * + * My C++ library for 3D mathematics and geometry manipulation. + * Jukka Jylänki + * + * offical web: http://clb.demon.fi/MathGeoLib/nightly/ + * + * License: + * + * This library is licensed under the Apache 2 license. I am not a lawyer, but to me that + * license means that you can use this code for any purpose, both commercial and closed source. + * You are however restricted from claiming you wrote it yourself, and cannot hold me liable + * for anything over this code. + * I acknowledge that most of the non-trivial math routines are taken off a book or a + * research paper. In all places, I have tried to be diligent to properly attribute the original + * source. Please contact me if you feel I have misattributed something. + */ + +namespace hgl +{ + using namespace math; + + typedef float2 Vector2f; + typedef float3 Vector3f; + typedef float4 Vector4f; + + typedef float3x3 Matrix3f; + typedef float4x4 Matrix4f; + + inline bool operator == (const Vector2f &lhs,const Vector2f &rhs) + { + if(lhs.x!=rhs.x)return(false); + if(lhs.y!=rhs.y)return(false); + return(true); + } + + inline bool operator != (const Vector2f &lhs,const Vector2f &rhs) + { + if(lhs.x!=rhs.x)return(true); + if(lhs.y!=rhs.y)return(true); + return(false); + } + + inline bool operator == (const Vector3f &lhs,const Vector3f &rhs) + { + if(lhs.x!=rhs.x)return(false); + if(lhs.y!=rhs.y)return(false); + if(lhs.z!=rhs.z)return(false); + return(true); + } + + inline bool operator != (const Vector3f &lhs,const Vector3f &rhs) + { + if(lhs.x!=rhs.x)return(true); + if(lhs.y!=rhs.y)return(true); + if(lhs.z!=rhs.z)return(true); + return(false); + } + + inline bool operator == (const Vector4f &lhs,const Vector4f &rhs) + { + if(lhs.x!=rhs.x)return(false); + if(lhs.y!=rhs.y)return(false); + if(lhs.z!=rhs.z)return(false); + if(lhs.w!=rhs.w)return(false); + return(true); + } + + inline bool operator != (const Vector4f &lhs,const Vector4f &rhs) + { + if(lhs.x!=rhs.x)return(true); + if(lhs.y!=rhs.y)return(true); + if(lhs.z!=rhs.z)return(true); + if(lhs.w!=rhs.w)return(true); + return(false); + } + + inline void vec3to2(Vector2f &dst,const Vector3f &src) + { + dst.x=src.x; + dst.y=src.y; + } + + inline Vector2f vec3to2(const Vector3f &src) + { + return Vector2f(src.x,src.y); + } + + inline void vec2to3(Vector3f &dst,const Vector2f &src,const float z) + { + dst.x=src.x; + dst.y=src.y; + dst.z=z; + } + + inline Vector3f vec2to3(const Vector2f &src,const float z) + { + return Vector3f(src.x,src.y,z); + } + + inline Matrix4f identity() + { + return Matrix4f::identity; + } + + inline Matrix4f inverse(const Matrix4f &m) + { + return m.Inverted(); + } + + inline Matrix4f ortho2d(float width,float height,float znear=0,float zfar=1) + { + //MathGeoLib生成的2D正交矩阵中心是0,0,所以需要偏移 + + return Matrix4f::OpenGLOrthoProjRH(znear,zfar,width,height)*Matrix4f::Scale(1,-1,1)*Matrix4f::Translate(-(width/2.0f),-(height/2.0f),0); + } + + inline Matrix4f translate(const Vector3f &v) + { + return Matrix4f::Translate(v); + } + + inline Matrix4f translate(float x,float y,float z) + { + return Matrix4f::Translate(x,y,z); + } + + inline Matrix4f scale(const Vector3f &v) + { + return Matrix4f::Scale(v,Vector3f::zero); + } + + inline Matrix4f scale(float x,float y,float z) + { + return Matrix4f::Scale(Vector3f(x,y,z),Vector3f::zero); + } + + inline Matrix4f scale(float s) + { + return Matrix4f::Scale(Vector3f(s,s,s),Vector3f::zero); + } + + inline Matrix4f rotate(float angle,const Vector3f &axis) + { + return Matrix4f::RotateAxisAngle(axis.Normalized(),angle); + } + + inline Matrix4f rotate(float angle,float x,float y,float z) + { + return rotate(angle,Vector3f(x,y,z)); + } + + inline Matrix4f rotate(float angle,const Vector4f &axis) + { + return rotate(angle,Vector3f(axis.x,axis.y,axis.z)); + } + + inline Vector3f rotate(const Vector3f &v3f,float angle,const Vector3f &axis) + { + Vector4f result=rotate(angle,axis)*Vector4f(v3f,1.0f); + + return result.xyz(); + } + + template + inline T normalized(const T &v) + { + return v.Normalized(); + } + + template + inline void normalize(T &v) + { + v.Normalize(); + } + + template + inline T cross(const T &v1,const T &v2) + { + return v1.Cross(v2); + } + + template + inline float dot(const T &v1,const T &v2) + { + return v1.Dot(v2); + } + + inline float ray_angle_cos(const Ray &ray,const vec &pos) + { + return ray.dir.Dot((pos-ray.pos).Normalized()); + } +}//namespace hgl +#endif//HGL_ALGORITHM_VECTOR_MATH_MGL_INCLUDE diff --git a/inc/hgl/endian/Endian.h b/inc/hgl/endian/Endian.h new file mode 100644 index 00000000..f54bbc1b --- /dev/null +++ b/inc/hgl/endian/Endian.h @@ -0,0 +1,275 @@ +#ifndef HGL_ENDIAN_INCLUDE +#define HGL_ENDIAN_INCLUDE + +#include // 平台定义 +namespace hgl +{ + namespace endian + { + /** + * Windows代码页枚举 + * 全部Windows所支持代码页请参见 http://msdn.microsoft.com/en-us/library/dd317756 + */ + enum CharCodePage ///代码页枚举 + { + ccpNone=0, ///<起始定义,无意义 + + //中文 + ccpGBK =936, ///<中国GBK标准中文 + ccpBig5 =950, ///<中国台湾Big5标准繁体中文 + ccpGB2312 =20936, ///<中国GB2312标准简体中文 + ccpGB18030 =54936, ///<中国GB18030-2000标准中文 + + //日文 + ccpShiftJIS =932, ///<日文ShiftJIS + ccpJISX =50222, ///<日文JIS X/ISO 2022 + + //韩文 + ccpKorean =949, ///<韩文 + + //苹果编码 + ccpMacJanpan =10001, ///<日文 + ccpMacTraditionalChinese =10002, ///<繁体中文 + ccpMacSimplifiedChinese =10008, ///<简体中文 + + //unicode + ccpUTF7 =65000, /// const CharSetName &GetCurCharSet(); ///<取得当前程序编码字符集 + + constexpr CharSetName utf8_charset="utf8"; + constexpr CharSetName utf16le_charset="utf-16le"; + constexpr CharSetName utf16be_charset="utf-16be"; + constexpr CharSetName utf32le_charset="utf-32le"; + constexpr CharSetName utf32be_charset="utf-32be"; + + template<> inline const CharSetName &GetCurCharSet<2,HGL_LITTLE_ENDIAN >(){return utf16le_charset;} + template<> inline const CharSetName &GetCurCharSet<2,HGL_BIG_ENDIAN >(){return utf16be_charset;} + template<> inline const CharSetName &GetCurCharSet<4,HGL_LITTLE_ENDIAN >(){return utf32le_charset;} + template<> inline const CharSetName &GetCurCharSet<4,HGL_BIG_ENDIAN >(){return utf32be_charset;} + + template inline const CharSetName &GetCharSet() + { + return GetCurCharSet(); + } + + /** + * 字节序文件头数据结构 + */ + struct BOMFileHeader + { + int size; ///<字节序文件头长度 + unsigned char data[4]; ///<字节序数据 + + ByteOrderMask bom; ///<字节序枚举 + const CharSetName *char_set;///<字符集名称 + CharCodePage code_page; ///<代码页 + }; + + /** + * 字节序文件头定义 + */ + constexpr BOMFileHeader BOMData[bomEnd]= + { + {0,{} ,bomNone, nullptr ,ccpNone }, + {3,{0xEF,0xBB,0xBF} ,bomUTF8, &utf8_charset ,ccpUTF8 }, + {2,{0xFF,0xFE} ,bomUTF16LE,&utf16le_charset ,ccpUTF16LE }, + {2,{0xFE,0xFF} ,bomUTF16BE,&utf16be_charset ,ccpUTF16BE }, + {4,{0xFF,0xFE,0x00,0x00},bomUTF32LE,&utf32le_charset ,ccpUTF32LE }, + {4,{0x00,0x00,0xFE,0xFF},bomUTF32BE,&utf32be_charset ,ccpUTF32BE } + }; + + template + inline T EndianSwap(const T value) + { + union + { + T v; + uint8 bytes[sizeof(T)]; + }a,b; + + a.v=value; + + for(uint i=0;i inline int8 EndianSwap< int8>(const int8 value){return value;} + template<> inline uint8 EndianSwap(const uint8 value){return value;} + + template<> inline uint16 EndianSwap(const uint16 value) + { + return ((value&0xFF)<<8) + |((value&0xFF00)>>8); + } + + template<> inline uint32 EndianSwap(const uint32 value) + { + return ((value&0xFF)<<24) + |((value&0xFF00)<<8) + |((value&0xFF0000)>>8) + |((value&0xFF000000)>>24); + } + + template<> inline uint64 EndianSwap(const uint64 value) + { + return ((value&0xFF)<<56) + |((value&0xFF00)<<40) + |((value&0xFF0000)<<24) + |((value&0xFF000000)<<8) + |((value&0xFF00000000)>>8) + |((value&0xFF0000000000)>>24) + |((value&0xFF000000000000)>>40) + |((value&0xFF00000000000000)>>56); + } + + template<> inline u16char EndianSwap(const u16char value){return EndianSwap(uint16(value));} + + template + inline void EndianSwap(T *value,const int64 count) + { + for(int64 i=0;i + inline void EndianSwap(T *dst,const T *src,const int64 count) + { + for(uint i=0;i + inline void EndianSwap(D *dst,const S *src,const int64 count) + { + for(uint i=0;i T ToBigEndian(T value){return value;} + + template inline void ToBigEndian(T *value,const int64 count){} + template inline void ToBigEndian(D *dst,const S *src,const int64 count){cm_cpy(dst,src,count);} + + template T ToLittleEndian(T value){return EndianSwap(value);} + + template inline void ToLittleEndian(T *value,const int64 count){EndianSwap(value,count);} + template inline void ToLittleEndian(D *dst,const S *src,const int64 count){EndianSwap(dst,src,count);} + + #else + + constexpr uint HGL_BOM_UTF16LE =0xfeff; + constexpr uint HGL_BOM_UTF16BE =0xfffe; + constexpr uint HGL_BOM_UTF32LE =0x0000feff; + constexpr uint HGL_BOM_UTF32BE =0xfffe0000; + + #define LittleToCurrentEndian ToLittleEndian + #define BigToCurrentEndian EndianSwap + + template T ToBigEndian(T value){return EndianSwap(value);} + + template inline void ToBigEndian(T *value,const int64 count){EndianSwap(value,count);} + template inline void ToBigEndian(D *dst,const S *src,const int64 count){EndianSwap(dst,src,count);} + + template T ToLittleEndian(T value){return value;} + + template inline void ToLittleEndian(T *,const int64){} + template inline void ToLittleEndian(D *dst,const S *src,const int64 count){cm_cpy(dst,src,count);} + + #endif//HGL_BIG_ENDIAN + + template struct UTF16CharConvert; + + template<> struct UTF16CharConvert + { + #if HGL_ENDIAN == HGL_BIG_ENDIAN + static void convert(u16char *str,const int length) + { + EndianSwap(str,length); + } + #else + static void convert(const u16char *,const int){} + #endif//HGL_ENDIAN == HGL_LITTLE_ENDIAN + + static void convert(u16char *out_str,const u16char *in_str,const int length) + { + #if HGL_ENDIAN == HGL_LITTLE_ENDIAN + memcpy(out_str,in_str,length*sizeof(u16char)); + #else + EndianSwap(in_str,length); + #endif//HGL_ENDIAN == HGL_LITTLE_ENDIAN + } + };//template<> struct UTF16CharConvert + + template<> struct UTF16CharConvert + { + static void convert(u16char *str,const int length) + { + #if HGL_ENDIAN == HGL_LITTLE_ENDIAN + EndianSwap(str,length); + #endif//HGL_ENDIAN == HGL_LITTLE_ENDIAN + } + + static void convert(u16char *out_str,const u16char *in_str,const int length) + { + #if HGL_ENDIAN == HGL_LITTLE_ENDIAN + memcpy(out_str,in_str,length*sizeof(u16char)); + #else + EndianSwap(in_str,length); + #endif//HGL_ENDIAN == HGL_LITTLE_ENDIAN + } + };//template<> struct UTF16ToWideChar + }//namespace endian + + using namespace endian; +}//namespace hgl +#endif//HGL_ENDIAN_INCLUDE diff --git a/inc/hgl/platform/InputDevice.h b/inc/hgl/platform/InputDevice.h new file mode 100644 index 00000000..7513d25a --- /dev/null +++ b/inc/hgl/platform/InputDevice.h @@ -0,0 +1,200 @@ +#ifndef HGL_INPUT_DEVICE_INCLUDE +#define HGL_INPUT_DEVICE_INCLUDE + +namespace hgl +{ + /** + * 鼠标按钮枚举 + */ + enum MouseButton:int + { + mbLeft=0, + mbRight, + mbMiddle, + + mbX1, + mbX2, + + mbEnd + };//enum MouseButton + + /** + * 按键枚举定义 + */ + enum KeyboardButton + { + kb_NONE=0, ///<起始定义,无意义 + + //主键盘区 + kbEsc, /// + + #if HGL_COMPILER == HGL_COMPILER_Microsoft + #include + #elif HGL_COMPILER == HGL_COMPILER_Intel + #include + #elif HGL_COMPILER == HGL_COMPILER_IBM + #include + #elif HGL_COMPILER == HGL_COMPILER_MINGW32 + #include + #elif HGL_COMPILER == HGL_COMPILER_GNU + #include + #else + #error Unrecognized compiler + #endif + +#elif HGL_OS == HGL_OS_Cygwin + + #include + + #if HGL_COMPILER == HGL_COMPILER_LLVM + #include + #elif HGL_COMPILER == HGL_COMPILER_GNU + #include + #else + #error Unrecognized compiler + #endif//GNU + +#elif (HGL_OS == HGL_OS_FreeBSD)||(HGL_OS == HGL_OS_NetBSD)||(HGL_OS == HGL_OS_OpenBSD) + + #include + + #if HGL_COMPILER == HGL_COMPILER_LLVM + #include + #elif HGL_COMPILER == HGL_COMPILER_GNU + #include + #else + #error Unrecognized compiler + #endif//GNU + +#elif HGL_OS == HGL_OS_Linux + + #include + + #if HGL_COMPILER == HGL_COMPILER_CBuilder + #include + #elif HGL_COMPILER == HGL_COMPILER_Intel + #include + #elif HGL_COMPILER == HGL_COMPILER_IBM + #include + #elif HGL_COMPILER == HGL_COMPILER_Watcom + #include + #elif HGL_COMPILER == HGL_COMPILER_LLVM + #include + #elif HGL_COMPILER == HGL_COMPILER_GNU + #include + #else + #error Unrecognized compiler + #endif + +#elif HGL_OS == HGL_OS_macOS + + #include + + #if HGL_COMPILER == HGL_COMPILER_Intel + #include + #elif HGL_COMPILER == HGL_COMPILER_LLVM + #include + #else + #error Unrecognized compiler + #endif + +#elif HGL_OS == HGL_OS_iOS + + #include + #include + +#elif HGL_OS == HGL_OS_PSP2 + + #include + + #if HGL_COMPILER == HGL_COMPILER_GNU + #include + #else + #error Unrecognized compiler + #endif + +#elif HGL_OS == HGL_OS_AIX + + #include + + #if HGL_COMPILER == HGL_COMPILER_IBM + #include + #elif HGL_COMPILER == HGL_COMPILER_SGI + #include + #elif HGL_COMPILER == HGL_COMPILER_GNU + #include + #else + #error Unrecognized compiler + #endif + +#elif HGL_OS == HGL_OS_Android + + #include + + #if HGL_COMPILER == HGL_COMPILER_LLVM + #include + #elif HGL_COMPILER == HGL_COMPILER_GNU + #include + #else + #error Unrecognized compiler + #endif//GNU +#endif//HGL_OS + +namespace hgl +{ + #define HGL_WINDOW_DIRECTORY_SEPARATOR OS_TEXT('\\') + #define HGL_UNIX_DIRECTORY_SPEARATOR OS_TEXT('/') +}//namespace hgl + +#endif//HGL_PLATFORM_INCLUDE diff --git a/inc/hgl/platform/compiler/DataTypeGNU.h b/inc/hgl/platform/compiler/DataTypeGNU.h new file mode 100644 index 00000000..de3df8d4 --- /dev/null +++ b/inc/hgl/platform/compiler/DataTypeGNU.h @@ -0,0 +1,21 @@ +#ifndef HGL_DATATYPE_GNU_INCLUDE +#define HGL_DATATYPE_GNU_INCLUDE + +namespace hgl +{ + using int8 = signed char; ///<有符号 8位整型 + using uint8 =unsigned char; ///<无符号 8位整型 + using int16 = signed short; ///<有符号16位整型 + using uint16 =unsigned short; ///<无符号16位整型 + using int32 = signed int; ///<有符号32位整型 + using uint32 =unsigned int; ///<无符号32位整型 + + //64位系统下long/long long都是64位,32位系列下只有long long是64位 + + using int64 = signed long long; ///<有符号64位整型 + using uint64 =unsigned long long; ///<无符号64位整型 + + using float32 =float; + using float64 =double; +}//namespace hgl +#endif//HGL_DATATYPE_GNU_INCLUDE diff --git a/inc/hgl/platform/compiler/DataTypeTiny.h b/inc/hgl/platform/compiler/DataTypeTiny.h new file mode 100644 index 00000000..d3cc858e --- /dev/null +++ b/inc/hgl/platform/compiler/DataTypeTiny.h @@ -0,0 +1,29 @@ +#ifndef HGL_DATA_TYPE_TINY_INCLUDE +#define HGL_DATA_TYPE_TINY_INCLUDE + +namespace hgl +{ + using i8=int8; + using i16=int16; + using i32=int32; + using i64=int64; + + using u8=uint8; + using u16=uint16; + using u32=uint32; + using u64=uint64; + + using f32=float; + using f64=double; + + #define enum_int(name) enum name:int + #define enum_uint(name) enum name:uint + + using void_pointer=void *; + + using uchar = unsigned char; ///< 无符号字符型 + using ushort = unsigned short; ///< 无符号短整型 + using uint = unsigned int; ///< 无符号整型 + using ulong = unsigned long; ///< 无符号长整型 +}//namespace hgl +#endif//HGL_DATA_TYPE_TINY_INCLUDE diff --git a/inc/hgl/platform/compiler/DataTypeWin.h b/inc/hgl/platform/compiler/DataTypeWin.h new file mode 100644 index 00000000..75386460 --- /dev/null +++ b/inc/hgl/platform/compiler/DataTypeWin.h @@ -0,0 +1,17 @@ +#ifndef HGL_DATATYPE_WINDOWS_INCLUDE +#define HGL_DATATYPE_WINDOWS_INCLUDE +namespace hgl +{ + using int8 = signed __int8 ; ///<有符号 8位整型 + using uint8 =unsigned __int8 ; ///<无符号 8位整型 + using int16 = signed __int16; ///<有符号16位整型 + using uint16 =unsigned __int16; ///<无符号16位整型 + using int32 = signed __int32; ///<有符号32位整型 + using uint32 =unsigned __int32; ///<无符号32位整型 + using int64 = signed __int64; ///<有符号64位整型 + using uint64 =unsigned __int64; ///<无符号64位整型 + + using float32 =float; + using float64 =double; +}//namespace hgl +#endif//HGL_DATATYPE_WINDOWS_INCLUDE diff --git a/inc/hgl/platform/compiler/EventFunc.h b/inc/hgl/platform/compiler/EventFunc.h new file mode 100644 index 00000000..84aeaeee --- /dev/null +++ b/inc/hgl/platform/compiler/EventFunc.h @@ -0,0 +1,250 @@ +#ifndef HGL_EVENT_FUNC_INCLUDE +#define HGL_EVENT_FUNC_INCLUDE + +#include +#include +namespace hgl +{ + #ifdef __BORLANDC__ + + #define SetEventCall(event_obj,obj_this,class_name,event_func) event_obj=obj_this->class_name::event_func + #define SafeCallEvent(event_obj,intro) {if(event_obj)event_obj intro;} + #define CallEvent(event_obj,intro) event_obj intro + #define DefEvent(result,name,intro) result (__closure *name)intro + + #else + + template struct EventFunc + { + typedef EventFunc SelfClass; + + union + { + void *vp_this; + _Object *this_pointer; + }; + + union + { + void *vp_func; + Func func_pointer; + ObjectMemberFunc omf; + }; + + public: + + EventFunc() + { + ClearFunc(); + } + + EventFunc(void *t,void *f) + { + ClearFunc(); + + vp_this=t; + vp_func=f; + } + + void ClearFunc() + { + memset(this,0,sizeof(SelfClass)); + } + + bool operator !()const + { + if(!vp_func)return(true); + + return(false); + } + + void operator = (void *v) + { + if(v==0) + memset(this,0,sizeof(SelfClass)); //omf可能不止一个指针的长度,所以必须这样清 + } + + void operator = (const SelfClass &ef) + { + memcpy(this,&ef,sizeof(SelfClass)); + } + + bool operator == (void *v) + { + return(vp_func==v); + } + + bool operator != (void *v) + { + return(vp_func!=v); + } + + template + RT operator()(ARGS...args) + { + return (this_pointer->*(func_pointer))(args...); + } + + template + RT operator()(ARGS...args)const + { + return (this_pointer->*(func_pointer))(args...); + } + + template + RT ThisCall(void *tp,ARGS...args) + { + return (((_Object *)tp)->*(func_pointer))(args...); + } + + template + RT ThisCall(void *tp,ARGS...args)const + { + return (((_Object *)tp)->*(func_pointer))(args...); + } + };//template struct EventFunc + + template struct EventFunc + { + typedef EventFunc SelfClass; + + union + { + void *vp_this; + _Object *this_pointer; + }; + + union + { + void *vp_func; + Func func_pointer; + ObjectMemberFunc omf; + }; + + public: + + EventFunc() + { + memset(this,0,sizeof(SelfClass)); + } + + EventFunc(void *t,void *f) + { + memset(this,0,sizeof(SelfClass)); + + vp_this=t; + vp_func=f; + } + + bool operator !()const + { + if(!vp_func)return(true); + + return(false); + } + + void operator = (void *v) + { + if(v==0) + memset(this,0,sizeof(SelfClass)); //omf可能不止一个指针的长度,所以必须这样清 + } + + void operator = (const SelfClass &ef) + { + memcpy(this,&ef,sizeof(SelfClass)); + } + + bool operator == (void *v) + { + return(vp_func==v); + } + + bool operator != (void *v) + { + return(vp_func!=v); + } + + template + void operator()(ARGS...args) + { + (this_pointer->*(func_pointer))(args...); + } + + template + void operator()(ARGS...args)const + { + (this_pointer->*(func_pointer))(args...); + } + + template + void ThisCall(void *tp,ARGS...args) + { + (((_Object *)tp)->*(func_pointer))(args...); + } + + template + void ThisCall(void *tp,ARGS...args)const + { + (((_Object *)tp)->*(func_pointer))(args...); + } + };//template struct EventFunc + + #define SetEventCall(event_obj,obj_this,class_name,event_func) { \ + event_obj.vp_this=obj_this; \ + event_obj.vp_func=GetMemberFuncPointer(class_name,event_func); \ + } + + #define SetEventThis(event_obj,obj_this) event_obj.vp_this=obj_this; + +// #define CallEvent(event_obj,intro) ((event_obj.this_pointer->*(event_obj.func_pointer))intro) + + #define SafeCallEvent(event_obj,intro) {if(event_obj.vp_func)event_obj intro;} + + #define DefEvent(result,name,intro) EventFunc name; + + #endif//__BORLANDC__ + + /* + + 使用方法: + + class Example + { + //原Borland/CodeGear方式 + void (__closure *OnClick)(Object *); + + //现通用方式 + DefEvent(void,OnClick,(Object *)); + }; + + void Test::ClickProc(Object *); + + void Test::func() + { + Example *exp; + + { + //原Borland/CodeGear方式 + exp->OnClick=this->ClickProc; + 或 + exp->OnClick=ClickProc; + + //现通用方式 + SetEventCall(exp->OnClick,this,Test,ClickProc); + } + + { + //原Borland/CodeGear方式 + exp->OnClick(nullptr); + + //现通用方式 + CallEvent(exp->OnClick,(nullptr)); + + //C++11方式 + exp->OnClick(nullptr); + } + } + + */ +}//namespace hgl +#endif//HGL_EVENT_FUNC_INCLUDE diff --git a/inc/hgl/platform/compiler/GNU.h b/inc/hgl/platform/compiler/GNU.h new file mode 100644 index 00000000..f7a28b27 --- /dev/null +++ b/inc/hgl/platform/compiler/GNU.h @@ -0,0 +1,85 @@ +#ifndef HGL_COMPILER_GNU_INCLUDE +#define HGL_COMPILER_GNU_INCLUDE +//-------------------------------------------------------------------------------------------------- +#define HGL_COMPILER_NAME OS_TEXT("GNU C/C++") +#define HGL_LIB_COMPILER_NAME OS_TEXT("GCC") + +#if (__GNUC__<4)||(__GNUC__==4&&__GNUC_MINOR__<8) + #error Please upgrade your compiler or development tools to GNU C/C++ 4.8 or later +#else + + #if __GNUC__ == 4 + #define HGL_LIB_COMPILER_MAIOR_VER OS_TEXT("4") + #elif __GNUC__ == 5 + #define HGL_LIB_COMPILER_MAIOR_VER OS_TEXT("5") + #elif __GNUC__ == 6 + #define HGL_LIB_COMPILER_MAIOR_VER OS_TEXT("6") + #elif __GNUC__ == 7 + #define HGL_LIB_COMPILER_MAIOR_VER OS_TEXT("7") + #elif __GNUC__ == 8 + #define HGL_LIB_COMPILER_MAIOR_VER OS_TEXT("8") + #elif __GNUC__ == 9 + #define HGL_LIB_COMPILER_MAIOR_VER OS_TEXT("9") + #elif __GNUC__ == 10 + #define HGL_LIB_COMPILER_MAIOR_VER OS_TEXT("10") + #endif//__GNUC__ + + #if __GNUC_MINOR__ == 0 + #define HGL_LIB_COMPILER_MINOR_VER OS_TEXT("0") + #elif __GNUC_MINOR__ == 1 + #define HGL_LIB_COMPILER_MINOR_VER OS_TEXT("1") + #elif __GNUC_MINOR__ == 2 + #define HGL_LIB_COMPILER_MINOR_VER OS_TEXT("2") + #elif __GNUC_MINOR__ == 3 + #define HGL_LIB_COMPILER_MINOR_VER OS_TEXT("3") + #elif __GNUC_MINOR__ == 4 + #define HGL_LIB_COMPILER_MINOR_VER OS_TEXT("4") + #elif __GNUC_MINOR__ == 5 + #define HGL_LIB_COMPILER_MINOR_VER OS_TEXT("5") + #elif __GNUC_MINOR__ == 6 + #define HGL_LIB_COMPILER_MINOR_VER OS_TEXT("6") + #elif __GNUC_MINOR__ == 7 + #define HGL_LIB_COMPILER_MINOR_VER OS_TEXT("7") + #elif __GNUC_MINOR__ == 8 + #define HGL_LIB_COMPILER_MINOR_VER OS_TEXT("8") + #elif __GNUC_MINOR__ == 9 + #define HGL_LIB_COMPILER_MINOR_VER OS_TEXT("9") + #endif// + + #if __GNUC_PATCHLEVEL__ == 0 + #define HGL_LIB_COMPILER_PATCH_LEVEL OS_TEXT("0") + #elif __GNUC_PATCHLEVEL__ == 1 + #define HGL_LIB_COMPILER_PATCH_LEVEL OS_TEXT("1") + #elif __GNUC_PATCHLEVEL__ == 2 + #define HGL_LIB_COMPILER_PATCH_LEVEL OS_TEXT("2") + #elif __GNUC_PATCHLEVEL__ == 3 + #define HGL_LIB_COMPILER_PATCH_LEVEL OS_TEXT("3") + #elif __GNUC_PATCHLEVEL__ == 4 + #define HGL_LIB_COMPILER_PATCH_LEVEL OS_TEXT("4") + #elif __GNUC_PATCHLEVEL__ == 5 + #define HGL_LIB_COMPILER_PATCH_LEVEL OS_TEXT("5") + #elif __GNUC_PATCHLEVEL__ == 6 + #define HGL_LIB_COMPILER_PATCH_LEVEL OS_TEXT("6") + #elif __GNUC_PATCHLEVEL__ == 7 + #define HGL_LIB_COMPILER_PATCH_LEVEL OS_TEXT("7") + #elif __GNUC_PATCHLEVEL__ == 8 + #define HGL_LIB_COMPILER_PATCH_LEVEL OS_TEXT("8") + #elif __GNUC_PATCHLEVEL__ == 9 + #define HGL_LIB_COMPILER_PATCH_LEVEL OS_TEXT("9") + #endif// + + #define HGL_LIB_COMPILER_VERSION HGL_LIB_COMPILER_MAIOR_VER OS_TEXT(".") HGL_LIB_COMPILER_MINOR_VER OS_TEXT(".") HGL_LIB_COMPILER_PATCH_LEVEL + +#endif//__GNUC__ + +#define HGL_THREAD_LOCAL_STORAGE __thread //线程本地储存 +//-------------------------------------------------------------------------------------------------- +#define HGL_LIB_FRONT HGL_LIB_OS "_" HGL_LIB_COMPILER_NAME "_" HGL_LIB_DEBUG_NAME "_" + +#define HGL_LIB_END ".a" +//-------------------------------------------------------------------------------------------------- +#include +#include +#include +//-------------------------------------------------------------------------------------------------- +#endif//HGL_COMPILER_GNU_INCLUDE diff --git a/inc/hgl/platform/compiler/Intel.h b/inc/hgl/platform/compiler/Intel.h new file mode 100644 index 00000000..e9246be8 --- /dev/null +++ b/inc/hgl/platform/compiler/Intel.h @@ -0,0 +1,43 @@ +#ifndef HGL_COMPILER_INTEL_INCLUDE +#define HGL_COMPILER_INTEL_INCLUDE +//-------------------------------------------------------------------------------------------------- +#define HGL_COMPILER_NAME u"Intel C/C++" +//-------------------------------------------------------------------------------------------------- +#if __INTEL_COMPILER < 1200 + #error Please upgrade your compiler To Intel C/C++ 12.1 or later. +#else + #if __INTEL_COMPILER >=1200 && __INTEL_COMPILER < 1300 + #define HGL_LIB_COMPILER_NAME "IntelCPP12" + #else + #define HGL_LIB_COMPILER_NAME "IntelCPP_UnknownVersion" + #endif//__INTEL_COMPILER + + #define enum_uint(name) enum name:unsigned int +#endif//__INTEL_COMPILER + +#define vsnwprintf _vsnwprintf +//-------------------------------------------------------------------------------------------------- +#include +#include +#include + +#if HGL_OS == HGL_OS_Windows + #define HGL_THREAD __declspec(thread) +#else + #define HGL_THREAD __thread +#endif//HGL_OS == HGL_OS_Windows +//-------------------------------------------------------------------------------------------------- +#ifdef _DLL + #define HGL_LIB_CRT "Dynamic" +#else + #define HGL_LIB_CRT "Static" +#endif//_DLL + +#define HGL_LIB_FRONT HGL_LIB_OS "_" HGL_LIB_COMPILER_NAME "_" HGL_LIB_DEBUG_NAME "_" HGL_LIB_CRT "_" + +#if HGL_OS == HGL_OS_Windows + #define HGL_LIB_END ".LIB" +#elif + #define HGL_LIB_END ".a" +#endif//HGL_OS == HGL_OS_Windows +#endif//HGL_COMPILER_INTEL_INCLUDE diff --git a/inc/hgl/platform/compiler/LLVM.h b/inc/hgl/platform/compiler/LLVM.h new file mode 100644 index 00000000..a3cabe58 --- /dev/null +++ b/inc/hgl/platform/compiler/LLVM.h @@ -0,0 +1,25 @@ +#ifndef HGL_COMPILER_LLVM_CLANG_INCLUDE +#define HGL_COMPILER_LLVM_CLANG_INCLUDE +//-------------------------------------------------------------------------------------------------- +#define HGL_COMPILER_NAME OS_TEXT("LLVM Clang") +#define HGL_LIB_COMPILER_NAME OS_TEXT("LLVM") + +#if (__clang_major__<3)||(__clang_major__==3&&__clang_minor__<7) + #error Please upgrade your compiler or development tools to LLVM Clang 3.7 or later +#else + + #define HGL_LIB_COMPILER_VERSION __clang_version__ + +#endif//__clang__ + +#define HGL_THREAD_LOCAL_STORAGE __thread //线程本地储存 +//-------------------------------------------------------------------------------------------------- +#define HGL_LIB_FRONT HGL_LIB_OS "_" HGL_LIB_COMPILER_NAME "_" HGL_LIB_DEBUG_NAME "_" + +#define HGL_LIB_END ".a" + +#include +#include +#include +//-------------------------------------------------------------------------------------------------- +#endif//HGL_COMPILER_LLVM_CLANG_INCLUDE diff --git a/inc/hgl/platform/compiler/Microsoft.h b/inc/hgl/platform/compiler/Microsoft.h new file mode 100644 index 00000000..b3ee8b32 --- /dev/null +++ b/inc/hgl/platform/compiler/Microsoft.h @@ -0,0 +1,61 @@ +#ifndef HGL_COMPILER_MICROSOFT_INCLUDE +#define HGL_COMPILER_MICROSOFT_INCLUDE +//-------------------------------------------------------------------------------------------------- +#define HGL_COMPILER_NAME OS_TEXT("Microsoft C/C++") +#define HGL_LIB_COMPILER_NAME OS_TEXT("MSC") + +#if _MSC_VER < 1900 //Visual C++ 2015(19) + #error Please upgrade your compiler or development tools to Microsoft C/C++ 19.0 (Visual C++ 2015) or later. +#else + #if _MSC_VER >= 1910 + #define HGL_LIB_COMPILER_VERSION OS_TEXT("19.1") //Visual C++ 2017 + #elif _MSC_VER == 1900 + #define HGL_LIB_COMPILER_VERSION OS_TEXT("19") //Visual C++ 2015 + #else + #define HGL_LIB_COMPILER_VERSION OS_TEXT("Unknow") + #endif//_MSC_VER +#endif//_MSC_VER + +#define HGL_THREAD_LOCAL_STORAGE __declspec(thread) //线程本地储存 +//-------------------------------------------------------------------------------------------------- +#define HGL_FMT_I64 "%I64d" +#define HGL_FMT_U64 "%I64u" +//参考文档最后查阅支持版本为VC2013,网址:http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx +//-------------------------------------------------------------------------------------------------- +#define _USE_MATH_DEFINES // 使用数学常数定义 +//-------------------------------------------------------------------------------------------------- +#pragma warning(disable:4819) // ansi -> unicode +#pragma warning(disable:4311) // 模板警告 +#pragma warning(disable:4800) // -> bool 性能损失警告 +#pragma warning(disable:4244) // -> int 精度丢失警告 +#pragma warning(disable:4804) // 不安全的类型比较 +#pragma warning(disable:4805) // 不安全的类型比较 + +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif// + +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE +#endif// + +#ifndef _CRT_NON_CONFORMING_SWPRINTFS +#define _CRT_NON_CONFORMING_SWPRINTFS +#endif// + +#ifdef _DLL + #define HGL_LIB_CRT "Dynamic" +#else + #define HGL_LIB_CRT "Static" +#endif//_DLL + +#define HGL_LIB_FRONT HGL_LIB_OS "_" HGL_LIB_COMPILER_NAME "_" HGL_LIB_DEBUG_NAME "_" HGL_LIB_CRT "_" + +#define HGL_LIB_END ".LIB" +//-------------------------------------------------------------------------------------------------- +#include +#include +#include +//-------------------------------------------------------------------------------------------------- +#endif//HGL_COMPILER_MICROSOFT_INCLUDE + diff --git a/inc/hgl/platform/compiler/Property.h b/inc/hgl/platform/compiler/Property.h new file mode 100644 index 00000000..f0f11fc3 --- /dev/null +++ b/inc/hgl/platform/compiler/Property.h @@ -0,0 +1,97 @@ +#ifndef HGL_PROPERTY_INCLUDE +#define HGL_PROPERTY_INCLUDE + +#include +namespace hgl +{ + /** + * 只读属性 + */ + template class PropertyRead + { + public: + + DefEvent(T,Get,() const); + };//template class PropertyRead + + /** + * 属性 + */ + template class Property + { + public: + + DefEvent(T,Get,() const); + DefEvent(void,Set,(T)); + + public: + + Property() + { + Get=0; + Set=0; + } + + virtual ~Property() {} + + operator T() const{return Get();} + void operator = (T v){Set(v);} + void operator = (const Property &v){Set(v.operator T());} + + T operator !(){ return !(operator T());} + T operator ~(){ return ~(operator T());} + + T operator ++ () { T v=operator T(); Set(++v); return v; } ///<前置++ + T operator -- () { T v=operator T(); Set(--v); return v; } ///<前置-- + + T operator ++ (int) { T r,v; v=operator T(); r=v; Set(++v); return r; } ///<后置++ + T operator -- (int) { T r,v; v=operator T(); r=v; Set(--v); return r; } ///<后置-- + + void operator += (T v) { if(v){Set(operator T() + v);} } + void operator -= (T v) { if(v){Set(operator T() - v);} } + void operator *= (T v) { Set(operator T() * v); } + void operator /= (T v) { Set(operator T() / v); } + void operator %= (T v) { Set(operator T() % v); } + + void operator &= (T v) { Set(operator T() & v); } + void operator |= (T v) { Set(operator T() | v); } + + void operator >>= (int n) { Set((operator T())>>n);} + void operator <<= (int n) { Set((operator T())<> (int n) { return (operator T())>>n;} + T operator << (int n) { return (operator T())< class PropertyObject:public Property + { + public: + + T *operator ->()const{return Property::Get();} + void operator =(void *pointer){Property::Set((T *)pointer);} + };//class PropertyObject + + #ifdef __BORLANDC__ + #define cmSetPropertyRead(name,tp,get) {name.Get=tp->get;} + #define cmSetPropertyWrite(name,tp,set) {name.Set=tp->set;} + #else + #define cmSetPropertyRead(name,tp,get) { \ + name.Get.vp_this=tp; \ + name.Get.omf=ObjectMemberFunc(&get); \ + } + + #define cmSetPropertyWrite(name,tp,set) { \ + name.Set.vp_this=tp; \ + name.Set.omf=ObjectMemberFunc(&set); \ + } + #endif// + + #define cmSetProperty(name,tp,get,set) { \ + cmSetPropertyRead(name,tp,get); \ + cmSetPropertyWrite(name,tp,set); \ + } +}//namespace hgl +#endif//HGL_PROPERTY_INCLUDE diff --git a/inc/hgl/platform/os/Android.h b/inc/hgl/platform/os/Android.h new file mode 100644 index 00000000..40371e09 --- /dev/null +++ b/inc/hgl/platform/os/Android.h @@ -0,0 +1,86 @@ +#ifndef HGL_OS_ANDROID_INCLUDE +#define HGL_OS_ANDROID_INCLUDE + +#include +//-------------------------------------------------------------------------------------------------- +using u32char =char32_t; +using u16char =char16_t; +using os_char =char; +#define to_oschar to_u8 +#define OS_TEXT(str) u8##str +#define U8_TEXT(str) u8##str +#define U16_TEXT(str) u##str + +#define HGL_OS_NAME OS_TEXT("Android") +#define HGL_LIB_OS "Android" //库操作系统前缀 +//-------------------------------------------------------------------------------------------------- +#define HGL_PLUGIN_FRONTNAME "libCMP." //插件文件名前缀 +#define HGL_PLUGIN_EXTNAME ".so" //插件文件扩展名 +#define HGL_PLUGIN_FUNC extern "C" //插件函数定义 + +#define HGL_DIRECTORY_SEPARATOR '/' //目录分隔符 +#define HGL_DIRECTORY_SEPARATOR_STR OS_TEXT("/") //目录分隔符 +#define HGL_DIRECTORY_SEPARATOR_U8STR U8_TEXT("/") //目录分隔符 + +#define HGL_LINE_END "\n" //换行符 +#define HGL_LINE_END_SIZE 1 //换行符长度 + +#define HGL_MEM_ALIGN 16 //内存对齐字节数 + +#define HGL_MAX_PATH _POSIX_PATH_MAX + +#define HGL_FMT_I64 "%lld" +#define HGL_FMT_U64 "%llu" +#define HGL_FMT_DOUBLE "%lf" +#define HGL_FMT_LONG_DOUBLE "%le" +//-------------------------------------------------------------------------------------------------- +#include +#include +#include + +#define hgl_malloc(size) memalign(HGL_MEM_ALIGN,size) //这个所有版本linux libc都支持 +//#define hgl_malloc(size) aligned_alloc(HGL_MEM_ALIGN,size) //这个是C11新增,需要libc 2.16 +#define hgl_realloc(ptr,size) realloc(ptr,size) +#define hgl_free free + +template +inline T *hgl_aligned_malloc(size_t n) +{ + return (T *)memalign(alignof(T),n*sizeof(T)); +} + +#define OS_EXTERNAL_H +typedef void * ExternalModulePointer; +#define pi_get dlsym +#define pi_close dlclose + +#define iconv_str char * + +#define hgl_stat64 stat +#define hgl_open64 open +#define hgl_lseek64 lseek +#define hgl_tell64(fp) lseek(fp,0,SEEK_CUR) +#define hgl_fstat64 fstat +#define hgl_lstat64 lstat +#define hgl_read64 read +#define hgl_write64 write +#define hgl_pread64 pread +#define hgl_pwrite64 pwrite + +#define struct_stat64 struct stat +#define struct_dirent64 struct dirent +#define hgl_dirent64 dirent +#define hgl_readdir64 readdir + +#define sprintf_s snprintf +//-------------------------------------------------------------------------------------------------- +//初始化Android支持,以下函数二选一 + +#include + +void InitAndroidSupport(JNIEnv *env,jobject obj); //JNI混编模式初始化Android支持 + +struct ANativeActivity; +void InitAndroidSupport(struct ANativeActivity *app); //NativeActivity模式初始化Android支持 +//-------------------------------------------------------------------------------------------------- +#endif//HGL_OS_ANDROID_INCLUDE diff --git a/inc/hgl/platform/os/BSD.h b/inc/hgl/platform/os/BSD.h new file mode 100644 index 00000000..f093d1c8 --- /dev/null +++ b/inc/hgl/platform/os/BSD.h @@ -0,0 +1,83 @@ +#ifndef HGL_OS_BSD_INCLUDE +#define HGL_OS_BSD_INCLUDE + +#include +//-------------------------------------------------------------------------------------------------- +using u32char =char32_t; +using u16char =char16_t; +using os_char =char; +#define to_oschar to_u8 +#define OS_TEXT(str) u8##str +#define U8_TEXT(str) u8##str +#define U16_TEXT(str) u##str + +#if defined(__FreeBSD__)||defined(__FreeBSD) + #define HGL_OS_NAME OS_TEXT("FreeBSD") + #define HGL_LIB_OS_NAME "FreeBSD" +#elif defined(__NetBSD__)||defined(__NetBSD) + #define HGL_OS_NAME OS_TEXT("NetBSD") + #define HGL_LIB_OS_NAME "NetBSD" +#elif defined(__OpenBSD__)||defined(__OPENBSD) + #define HGL_OS_NAME OS_TEXT("OpenBSD") + #define HGL_LIB_OS_NAME "OpenBSD" +#else + #define HGL_OS_NAME OS_TEXT("BSD") + #define HGL_LIB_OS_NAME "BSD" +#endif// + +#define HGL_LIB_OS "BSD" //库操作系统前缀 +//-------------------------------------------------------------------------------------------------- +#define HGL_PLUGIN_FRONTNAME "libCMP." //插件文件名前缀 +#define HGL_PLUGIN_EXTNAME ".so" //插件文件扩展名 +#define HGL_PLUGIN_FUNC extern "C" //插件函数定义 + +#define HGL_DIRECTORY_SEPARATOR '/' //目录分隔符 +#define HGL_DIRECTORY_SEPARATOR_STR OS_TEXT("/") //目录分隔符 +#define HGL_DIRECTORY_SEPARATOR_U8STR U8_TEXT("/") //目录分隔符 + +#define HGL_LINE_END "\n" //换行符 +#define HGL_LINE_END_SIZE 1 //换行符长度 + +#define HGL_MEM_ALIGN 16 //内存对齐字节数 + +#define HGL_MAX_PATH _POSIX_PATH_MAX + +#define HGL_FMT_I64 "%lld" +//-------------------------------------------------------------------------------------------------- +#include +#include + +#define hgl_malloc(size) aligned_alloc(HGL_MEM_ALIGN,size) //这个是C11新增,需要libc 2.16 +#define hgl_realloc realloc +#define hgl_free free + +template +inline T *hgl_aligned_malloc(size_t n) +{ + return (T *)aligned_alloc(alignof(T),n*sizeof(T)); +} + +#define OS_EXTERNAL_H +typedef void * ExternalModulePointer; +#define pi_get dlsym +#define pi_close dlclose + +typedef pthread_mutex_t hgl_thread_mutex; + +#define hgl_stat64 stat +#define hgl_open64 open +#define hgl_lseek64 lseek +#define hgl_tell64(fp) lseek(fp,0,SEEK_CUR) +#define hgl_fstat64 fstat +#define hgl_lstat64 lstat +#define hgl_read64 read +#define hgl_write64 write +#define hgl_pread64 pread +#define hgl_pwrite64 pwrite + +#define struct_stat64 struct stat +#define struct_dirent64 struct dirent +#define hgl_dirent64 dirent +#define hgl_readdir64 readdir +//-------------------------------------------------------------------------------------------------- +#endif//HGL_OS_BSD_INCLUDE diff --git a/inc/hgl/platform/os/Linux.h b/inc/hgl/platform/os/Linux.h new file mode 100644 index 00000000..2b3f84df --- /dev/null +++ b/inc/hgl/platform/os/Linux.h @@ -0,0 +1,75 @@ +#ifndef HGL_OS_LINUX_INCLUDE +#define HGL_OS_LINUX_INCLUDE + +#include +//-------------------------------------------------------------------------------------------------- +using u32char =char32_t; +using u16char =char16_t; +using os_char =char; +#define to_oschar to_u8 +#define OS_TEXT(str) u8##str +#define U8_TEXT(str) u8##str +#define U16_TEXT(str) u##str + +#define HGL_OS_NAME OS_TEXT("Linux") +#define HGL_LIB_OS "Linux" //库操作系统前缀 +//-------------------------------------------------------------------------------------------------- +#define HGL_PLUGIN_FRONTNAME "libCMP." //插件文件名前缀 +#define HGL_PLUGIN_EXTNAME ".so" //插件文件扩展名 +#define HGL_PLUGIN_FUNC extern "C" //插件函数定义 + +#define HGL_DIRECTORY_SEPARATOR '/' //目录分隔符 +#define HGL_DIRECTORY_SEPARATOR_STR OS_TEXT("/") //目录分隔符 +#define HGL_DIRECTORY_SEPARATOR_U8STR U8_TEXT("/") //目录分隔符 + +#define HGL_LINE_END "\n" //换行符 +#define HGL_LINE_END_SIZE 1 //换行符长度 + +#define HGL_MEM_ALIGN 16 //内存对齐字节数 + +#define HGL_MAX_PATH _POSIX_PATH_MAX + +#define HGL_FMT_I64 "%lld" +#define HGL_FMT_U64 "%llu" +#define HGL_FMT_DOUBLE "%lf" +#define HGL_FMT_LONG_DOUBLE "%le" +//-------------------------------------------------------------------------------------------------- +#include +#include +#include + +//#define hgl_malloc(size) memalign(HGL_MEM_ALIGN,size) //这个所有版本linux libc都支持 +#define hgl_malloc(size) aligned_alloc(HGL_MEM_ALIGN,size) //这个是C11新增,需要libc 2.16 +#define hgl_realloc(ptr,size) realloc(ptr,size) +#define hgl_free free + +template +inline T *hgl_aligned_malloc(size_t n) +{ + return (T *)aligned_alloc(alignof(T),n*sizeof(T)); +} + +#define OS_EXTERNAL_H +typedef void * ExternalModulePointer; +#define pi_get dlsym +#define pi_close dlclose + +#define hgl_stat64 stat64 +#define hgl_open64 open64 +#define hgl_lseek64 lseek64 +#define hgl_tell64(fp) lseek64(fp,0,SEEK_CUR) +#define hgl_fstat64 fstat64 +#define hgl_lstat64 lstat64 +#define hgl_read64 read +#define hgl_write64 write +#define hgl_pread64 pread64 +#define hgl_pwrite64 pwrite64 + +#define struct_stat64 struct stat64 +#define struct_dirent64 struct dirent64 +#define hgl_dirent64 dirent64 +#define hgl_readdir64 readdir64 + +#define sprintf_s snprintf +//-------------------------------------------------------------------------------------------------- +#endif//HGL_OS_LINUX_INCLUDE diff --git a/inc/hgl/platform/os/MSWindows.h b/inc/hgl/platform/os/MSWindows.h new file mode 100644 index 00000000..b388f7c0 --- /dev/null +++ b/inc/hgl/platform/os/MSWindows.h @@ -0,0 +1,80 @@ +#ifndef HGL_OS_WIN_INCLUDE +#define HGL_OS_WIN_INCLUDE + +#include +#include //winsock2必须在Windows.h前面,不然会报错 +#include + +#undef min +#undef max +//-------------------------------------------------------------------------------------------------- +using u32char =char32_t; +using u16char =wchar_t; +using os_char =wchar_t; +#define to_oschar to_u16 +#define OS_TEXT(str) L##str +#define U8_TEXT(str) u8##str +#define U16_TEXT(str) L##str + +#define HGL_OS_NAME OS_TEXT("Windows") + +#if HGL_CPU == HGL_CPU_X86_32 + #define HGL_LIB_OS "Win32" //库操作系统前缀 +#elif HGL_CPU == HGL_CPU_X86_64 + #define HGL_LIB_OS "Win64" //库操作系统前缀 +#endif//HGL_CPU +//-------------------------------------------------------------------------------------------------- +#define HGL_PLUGIN_FRONTNAME OS_TEXT("CMP.") //插件文件名前缀 +#define HGL_PLUGIN_EXTNAME OS_TEXT(".DLL") //插件文件扩展名 +#define HGL_PLUGIN_FUNC extern "C" __declspec(dllexport) //插件函数定义 + +#define HGL_DIRECTORY_SEPARATOR OS_TEXT('\\') //目录分隔符 +#define HGL_DIRECTORY_SEPARATOR_STR OS_TEXT("\\") //目录分隔符 +#define HGL_DIRECTORY_SEPARATOR_U8STR U8_TEXT("\\") + +#define HGL_LINE_END OS_TEXT("\r\n") //换行符 +#define HGL_LINE_END_SIZE 2 //换行符长度 + +#define HGL_MAX_PATH MAX_PATH + +#define HGL_MEM_ALIGN 16 //内存对齐字节数 + +#define HGL_GL_WINDOW_INCLUDE_FILE //指定OpenGL窗口引用头文件 +#define HGL_GL_WINDOW_CLASS WinGLWindow //指定OpenGL窗口类名称 +//-------------------------------------------------------------------------------------------------- +#if HGL_COMPILER == HGL_COMPILER_Microsoft + #define hgl_malloc(size) _aligned_malloc(size,HGL_MEM_ALIGN) + #define hgl_realloc(ptr,size) _aligned_realloc(ptr,size,HGL_MEM_ALIGN) + #define hgl_free _aligned_free + + template + inline T *hgl_aligned_malloc(size_t n) + { + return (T *)_aligned_malloc(n*sizeof(T),alignof(T)); + } +#else + #define hgl_malloc(size) memalign(HGL_MEM_ALIGN,size) + #define hgl_realloc(ptr,size) realloc(ptr,size) + #define hgl_free free +#endif// + +#define OS_EXTERNAL_H +typedef HMODULE ExternalModulePointer; +#define pi_get GetProcAddress +#define pi_close FreeLibrary + +#define struct_stat64 struct _stat64 +//#define hgl_stat64 _stat64 +#define hgl_lseek64 _lseeki64 +#define hgl_tell64(fp) _telli64(fp) +#define hgl_fstat64 _fstati64 +#define hgl_lstat64 _wstat64 +#define hgl_read64 _read +#define hgl_write64 _write + +using hgl_thread_mutex =CRITICAL_SECTION; +using thread_ptr =HANDLE; +#define THREAD_FUNC DWORD WINAPI +#define HGL_THREAD_DETACH_SELF +//-------------------------------------------------------------------------------------------------- +#endif//HGL_OS_WIN_INCLUDE diff --git a/inc/hgl/platform/os/MacOS.h b/inc/hgl/platform/os/MacOS.h new file mode 100644 index 00000000..43d22579 --- /dev/null +++ b/inc/hgl/platform/os/MacOS.h @@ -0,0 +1,78 @@ +#ifndef HGL_OS_MACOS_INCLUDE +#define HGL_OS_MACOS_INCLUDE + +#include +//------------------------------------------------------------------ +using u32char =char32_t; +using u16char =char16_t; +using os_char =char; +#define to_oschar to_u8 +#define OS_TEXT(str) u8##str +#define U8_TEXT(str) u8##str +#define U16_TEXT(str) u##str + +//-------------------------------------------------------------------------------------------------- +#if HGL_OS == HGL_OS_iOS + #define HGL_OS_NAME OS_TEXT("iOS") + #define HGL_LIB_OS "iOS" //库操作系统前缀 +#else + #define HGL_OS_NAME OS_TEXT("macOS") + #define HGL_LIB_OS "mac" //库操作系统前缀 +#endif//HGL_OS == HGL_OS_iOS + +#define HGL_PLUGIN_FRONTNAME "libCMP." //插件文件名前缀 +#define HGL_PLUGIN_EXTNAME OS_TEXT(".dylib") //插件文件扩展名 +#define HGL_PLUGIN_FUNC extern "C" //插件函数定义 + +#define HGL_DIRECTORY_SEPARATOR '/' //目录分隔符 +#define HGL_DIRECTORY_SEPARATOR_STR OS_TEXT("/") //目录分隔符 +#define HGL_DIRECTORY_SEPARATOR_U8STR U8_TEXT("/") //目录分隔符 + +#define HGL_LINE_END "\n" //换行符 +#define HGL_LINE_END_SIZE 1 //换行符长度 + +#define HGL_MEM_ALIGN 16 //内存对齐字节数 + +#define HGL_MAX_PATH __DARWIN_MAXPATHLEN + +#define HGL_FMT_I64 "%lld" +#define HGL_FMT_U64 "%llu" +#define HGL_FMT_DOUBLE "%lf" +#define HGL_FMT_LONG_DOUBLE "%le" + +//-------------------------------------------------------------------------------------------------- +#include +#include + +#define hgl_malloc(size) malloc(size) +#define hgl_realloc(ptr,size) realloc(ptr,size) +#define hgl_free free + +template +inline T *hgl_aligned_malloc(size_t n) +{ + return (T *)hgl_malloc(n*sizeof(T)); +} + +#define OS_EXTERNAL_H +using ExternalModulePointer=void *; +#define pi_get dlsym +#define pi_close dlclose + +#define hgl_stat64 stat +#define hgl_open64 open +#define hgl_lseek64 lseek +#define hgl_tell64(fp) lseek(fp,0,SEEK_CUR) +#define hgl_fstat64 fstat +#define hgl_lstat64 lstat +#define hgl_read64 read +#define hgl_write64 write +#define hgl_pread64 pread +#define hgl_pwrite64 pwrite + +#define struct_stat64 struct stat +#define struct_dirent64 struct dirent +#define hgl_dirent64 dirent +#define hgl_readdir64 readdir +//-------------------------------------------------------------------------------------------------- +#endif//HGL_OS_MACOS_INCLUDE diff --git a/inc/hgl/platform/os/PosixThread.h b/inc/hgl/platform/os/PosixThread.h new file mode 100644 index 00000000..65842a47 --- /dev/null +++ b/inc/hgl/platform/os/PosixThread.h @@ -0,0 +1,15 @@ +#ifndef HGL_POSIX_THREAD_INCLUDE +#define HGL_POSIX_THREAD_INCLUDE + +#include + +namespace hgl +{ + using hgl_thread_mutex =pthread_mutex_t; + + using thread_ptr =pthread_t; + using THREAD_FUNC =void *; + + #define HGL_THREAD_DETACH_SELF pthread_detach(pthread_self()); +}//namespace hgl +#endif//HGL_POSIX_THREAD_INCLUDE diff --git a/inc/hgl/thread/ASyncEvent.h b/inc/hgl/thread/ASyncEvent.h new file mode 100644 index 00000000..eacb2f6d --- /dev/null +++ b/inc/hgl/thread/ASyncEvent.h @@ -0,0 +1,123 @@ +#ifndef HGL_THREAD_ASYNC_EVENT_INCLUDE +#define HGL_THREAD_ASYNC_EVENT_INCLUDE + +#include +#include +#include +#include + +namespace hgl +{ + namespace async + { + /** + * 事件基类 + */ + class EventProc + { + public: + + EventProc()=default; + virtual ~EventProc()=default; + + virtual bool Proc(const double &cur_time)=0; + };//class EventProc + + using EventProcQueue=Queue; + using MTEventProcQueue=SemSwapData; + using MTEventProcPost=PostToSemSwapData; ///<多线程事件结果投递对象重定义 + + /** + * 增加事件到队列 + * @param queue 事件队列 + * @param event 事件 + */ + inline void AddToEventQueue(MTEventProcQueue *queue,EventProc *event) + { + if(!queue||!event) + return; + + MTEventProcPost post(queue); + + post->Push(event); + } + + /** + * 刷新执行事件队列 + * @param proc_queue 要执行的事件队列 + * @param cur_time 当前时间 + * @param wait 是否等待有事件 + */ + inline void UpdateEventProcQueue(MTEventProcQueue *proc_queue,const double &cur_time,bool wait=false) + { + if(!proc_queue) + return; + + if(wait) + { + if(!proc_queue->WaitSemSwap()) + return; + } + else + { + if(!proc_queue->TrySemSwap()) + return; + } + + EventProcQueue &epq=proc_queue->GetReceive(); + + if(epq.GetCount()<=0) + return; + + EventProc *event; + + while(epq.Pop(event)) + { + event->Proc(cur_time); + delete event; + } + } + + /** + * 异步事件执行线程 + */ + class EventThread:public Thread + { + MTEventProcQueue *event_proc_queue; + + public: + + EventThread(MTEventProcQueue *queue):event_proc_queue(queue){} + virtual ~EventThread()=default; + + bool Execute() override + { + if(!event_proc_queue) + return(false); + + UpdateEventProcQueue(event_proc_queue,GetDoubleTime(),true); + + return(true); + } + };//class EventThread:public Thread + + /** + * 使用范例 + */ +/* + // 公用部分 + + MTEventProcQueue event_queue; ///<事件队列 + + // 其它 thread + + class MyEvent:public EventProc{...}; //自有事件 + + AddToEventQueue(&event_queue,new MyEvent); //添加一个事件到事件队列 + + // 事件执行线程 + EventThread *et=new EventThread(&event_queue); + et->Start();*/ + }//namespace async +}//namespace hgl +#endif//HGL_THREAD_ASYNC_EVENT_INCLUDE diff --git a/inc/hgl/thread/Atomic.h b/inc/hgl/thread/Atomic.h new file mode 100644 index 00000000..2fe5a37c --- /dev/null +++ b/inc/hgl/thread/Atomic.h @@ -0,0 +1,61 @@ +#ifndef HGL_ATOMIC_INCLUDE +#define HGL_ATOMIC_INCLUDE + +#include + +#if HGL_OS == HGL_OS_Windows + #include +#elif (HGL_OS == HGL_OS_macOS)||(HGL_OS == HGL_OS_Android) + #include + + template using atom=std::atomic; +#elif defined(__GNUC__) + #if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1) || __GNUC__ > 4) && (defined(__x86_64__) || defined(__i386__) || defined(__powerpc__)) + #include + #else + #include + #endif// +#endif// + +//ps.1:老旧的Linux/32bit下原子仅支持24位,但我们设定为不支持旧的Linux +//ps.2:使用GCC 4.1内置宏实现的AtomicGNU的不支持doubel型处理,如需支持,则尽可能不要用atom_double + +//ps..........GCC4.7/4.8/4.9下如果使用c++11的atomic会造成一些valgrind-memcheck报错,所以暂不使用。待valgrind更新 + +namespace hgl +{ + #if (HGL_OS == HGL_OS_Windows)//&&(!defined(HGL_ATOMIC_CPP11)) + typedef atom_win32 atom_int; + typedef atom_win32 atom_uint; + typedef atom_win32 atom_int32; + typedef atom_win32 atom_uint32; + typedef atom_win64 atom_int64; + typedef atom_win64 atom_uint64; + typedef atom_win32 atom_float; +// typedef atom_win64 atom_double; + + typedef atom_win32 atom_bool; + typedef atom_win32 atom_char; + typedef atom_win32 atom_uchar; +// typedef atom_win32 atom_wchar; + typedef atom_win32 atom_char16; +// typedef atom_win32 atom_char32; + #else + typedef atom atom_bool; + typedef atom atom_int; + typedef atom atom_uint; + typedef atom atom_int32; + typedef atom atom_uint32; + typedef atom atom_int64; + typedef atom atom_uint64; + typedef atom atom_float; +// typedef atom atom_double; + + typedef atom atom_char; + typedef atom atom_uchar; +// typedef atom atom_wchar; + typedef atom atom_char16; +// typedef atom atom_char32; + #endif//windows & !c++11 +}//namespace hgl +#endif//HGL_ATOMIC_INCLUDE diff --git a/inc/hgl/thread/CondVar.h b/inc/hgl/thread/CondVar.h new file mode 100644 index 00000000..3103a9d9 --- /dev/null +++ b/inc/hgl/thread/CondVar.h @@ -0,0 +1,32 @@ +#ifndef HGL_MULTI_THREAD_CONDITION_VARIABLE_INCLUDE +#define HGL_MULTI_THREAD_CONDITION_VARIABLE_INCLUDE + +#include +namespace hgl +{ + class ThreadMutex; + class RWLock; + + /** + * 条件变量 + */ + class CondVar + { + void *cond_var; + + public: + + CondVar(); + virtual ~CondVar(); + + bool Wait(ThreadMutex *,double time=0); ///<释放指定ThreadMutex,在条件符合后重新锁定并结束等待,0表示永久 + +#if HGL_OS == HGL_OS_Windows + bool Wait(RWLock *,double time=0,bool read=false); ///<释放指定RWLock,在条件符合后重新锁定并结束等待。(注:此函数仅在Windows 2008/Vista及更新版本中支持,Linux/BSD版不支持) +#endif//HGL_OS == HGL_OS_Windows + + void Signal(); ///<发送一个信号,让一个等待的线程解锁 + void Broadcast(); ///<广播一个信号,让所有等待的线程都解锁 + };//class CondVar +}//namespace hgl +#endif//HGL_MULTI_THREAD_CONDITION_VARIABLE_INCLUDE diff --git a/inc/hgl/thread/DataPost.h b/inc/hgl/thread/DataPost.h new file mode 100644 index 00000000..9e1d4ea1 --- /dev/null +++ b/inc/hgl/thread/DataPost.h @@ -0,0 +1,156 @@ +#ifndef HGL_THREAD_DATA_POST_INCLUDE +#define HGL_THREAD_DATA_POST_INCLUDE + +#include +#include +#include + +namespace hgl +{ + /** + * 多线程数据投递模板
+ * 需要注意每个任务都会重新由空闲线程来进行获取,所以请将连续的任务合并为一个任务,而不是一次大量投递。 + */ + template class DataPost + { + protected: + + List data_list[2]; + + int post_index,recv_index; + int recv_offset; + + ThreadMutex post_lock,recv_lock; + + protected: + + void _Swap() + { + if(recv_index){recv_index=0;post_index=1;} + else{recv_index=1;post_index=0;} + + recv_offset=0; + } + + public: + + DataPost() + { + post_index=0; + recv_index=1; + + recv_offset=0; + } + + virtual ~DataPost()=default; + + /** + * 投递一个数据 + */ + void Post(T *obj) + { + if(!obj)return; + + post_lock.Lock(); + data_list[post_index].Add(obj); + post_lock.Unlock(); + } + + /** + * 投递一批数据 + */ + void Post(T **obj,int count) + { + if(!obj)return; + + post_lock.Lock(); + data_list[post_index].Add(obj,count); + post_lock.Unlock(); + } + + public: + + /** + * 获取一个数据 + */ + T *Receive() + { + T *obj=nullptr; + + recv_lock.Lock(); + int count=data_list[recv_index].GetCount(); + + if(recv_offset0) //如果换出来的区有数据 + { + obj=*(data_list[recv_index].GetData()+recv_offset); + + ++recv_offset; + } + } + recv_lock.Unlock(); + + return obj; + } + };//template class DataPost + + /** + * 信号自动交换数据访问模板 + */ + template class SemDataPost:public DataPost + { + Semaphore sem; + + public: + + using DataPost::DataPost; + ~SemDataPost()=default; + + /** + * 释放接收信号 + * @param count 信号个数 + */ + void PostSem(int count=1) + { + sem.Post(count); + } + + /** + * 等待获取一个信号并获取数据 + * @param time_out 等待时长 + */ + T *WaitSemReceive(const double time_out=5) + { + if(!sem.Acquire(time_out)) + return(nullptr); + + return this->Receive(); + } + + /** + * 尝试获取一个信号并获取数据 + */ + T *TrySemReceive() + { + if(!sem.TryAcquire()) + return(nullptr); + + return this->Receive(); + } + };//template class SemDataPost:public DataPost +}//namespace hgl +#endif//HGL_THREAD_DATA_POST_INCLUDE diff --git a/inc/hgl/thread/Loader.h b/inc/hgl/thread/Loader.h new file mode 100644 index 00000000..3e8a61cc --- /dev/null +++ b/inc/hgl/thread/Loader.h @@ -0,0 +1,74 @@ +#ifndef HGL_LOADER_INCLUDE +#define HGL_LOADER_INCLUDE + +#include +#include +#include +#include +namespace hgl +{ + class HAC; + + /** + * 加载器,用于异步加载数据 + */ + class Loader:public EnumObject,public Thread ///加载器 + { + public: + + /** + * 加载器状态枚举 + */ + enum LoaderStatus //加载器状态 + { + lsNone=0, //未使用 + + lsLoad, //正在加载 + lsProc, //正在处理 + lsProcFinish, //处理完成 + lsClear, //清理 + lsClearFinish, //清理完成 + + lsEnd, //完成 + }; + + protected: + + LoaderStatus status; + + void SetStatus(LoaderStatus); + + HAC *loader_hac; + UTF16String loader_filename; + void *loader_pointer; + void *loader_data; + int loader_size; + + protected: //被动事件 + + virtual void ProcFinish()=default; ///<加载完成(异步事件) + virtual void ProcEnd()=default; ///<结束处理 + virtual void ProcClear()=default; ///<清理处理(异步事件) + + public: //事件 + + DefEvent(void,OnError,(Loader *)); ///<出错事件 + DefEvent(void,OnEnd,(Loader *)); ///<完成事件,在ProcEnd之后,ProcClear之前被调用 + + public: + + Loader(); + virtual ~Loader()=default; + + bool Execute(); + + void Update(); + + public: //方法 + + bool Load(HAC *,const u16char *); ///<加载一个文件到某个对象 + + LoaderStatus GetStatus(); ///<取得状态 + };//class Loader +}//namespace hgl +#endif//HGL_LOADER_INCLUDE diff --git a/inc/hgl/thread/RWLock.h b/inc/hgl/thread/RWLock.h new file mode 100644 index 00000000..65ca68cb --- /dev/null +++ b/inc/hgl/thread/RWLock.h @@ -0,0 +1,187 @@ +#ifndef HGL_RWLOCK_INCLUDE +#define HGL_RWLOCK_INCLUDE + +#include +namespace hgl +{ + /** + * 读写锁/共享锁 + */ + class RWLock ///读写锁/共享锁 + { + void *lock; + + public: + + RWLock(); + virtual ~RWLock(); + + void *GetRWLock(){ return lock; } ///<返回操作系级锁 + + bool TryReadLock(); ///<尝试读(共享访问)锁定 + bool ReadLock(); ///<读(共享访问)锁定 + bool ReadUnlock(); ///<读(共享访问)解锁 + + bool TryWriteLock(); ///<尝试写(独占访问)锁定 + bool WriteLock(); ///<写(独占访问)锁定 + bool WriteUnlock(); ///<写(独占访问)解锁 + +#if (HGL_OS != HGL_OS_Windows)&&(HGL_OS != HGL_OS_macOS) + bool WaitReadLock(double); ///<等待读(共享访问)锁定 + bool WaitWriteLock(double); ///<等待写(独占访问)锁定 +#endif//(HGL_OS != HGL_OS_Windows)&&(HGL_OS != HGL_OS_macOS) + };//class RWLock + + #define HGL_RWLOCK(lock) bool ReadLock() {return lock.ReadLock(); } \ + bool WriteLock() {return lock.WriteLock(); } \ + bool TryReadLock() {return lock.TryReadLock(); } \ + bool TryWriteLock() {return lock.TryWriteLock();} \ + bool ReadUnlock() {return lock.ReadUnlock(); } \ + bool WriteUnlock() {return lock.WriteUnlock(); } + + #define HGL_RWLOCK_PTR(lock) bool ReadLock() {return lock->ReadLock(); } \ + bool WriteLock() {return lock->WriteLock(); } \ + bool TryReadLock() {return lock->TryReadLock(); } \ + bool TryWriteLock() {return lock->TryWriteLock(); } \ + bool ReadUnlock() {return lock->ReadUnlock(); } \ + bool WriteUnlock() {return lock->WriteUnlock(); } + + #define HGL_NULL_RWLOCK bool ReadLock() {return true;} \ + bool WriteLock() {return true;} \ + bool TryReadLock() {return true;} \ + bool TryWriteLock() {return true;} \ + bool ReadUnlock() {return true;} \ + bool WriteUnlock() {return true;} \ + + #define HGL_VIRTUAL_NULL_RWLOCK virtual bool ReadLock() {return true;} \ + virtual bool WriteLock() {return true;} \ + virtual bool TryReadLock() {return true;} \ + virtual bool TryWriteLock() {return true;} \ + virtual bool ReadUnlock() {return true;} \ + virtual bool WriteUnlock() {return true;} \ + + /** + * 读写锁/共享锁对象 + */ + template class RWLockObject:public RWLock + { + T *data; + + public: + + RWLockObject() + { + data=new T; + } + + RWLockObject(T *t) + { + data=t; + } + + virtual ~RWLockObject() + { + SAFE_CLEAR(data); + } + + void operator = (T *t) + { + if(data) + delete data; + + data=t; + } + + T *operator ->() + { + return data; + } + + bool valid()const + { + return data; + } + + bool operator !() + { + return !data; + } + };//class RWLockObject + + /** + * 读写锁共享锁定自动释放类 + */ + class OnlyReadLock + { + RWLock *rw; + + public: + + OnlyReadLock(RWLock &rw_lock) + { + rw=&rw_lock; + + rw->ReadLock(); + } + + OnlyReadLock(RWLock *rw_lock) + { + rw=rw_lock; + + rw->ReadLock(); + } + + ~OnlyReadLock() + { + Unlock(); + } + + void Unlock() + { + if(rw) + { + rw->ReadUnlock(); + rw=nullptr; + } + } + };//class ReadLock + + /** + * 读写锁独占访问锁定自动释放类 + */ + class OnlyWriteLock + { + RWLock *rw; + + public: + + OnlyWriteLock(RWLock &rw_lock) + { + rw=&rw_lock; + + rw->WriteLock(); + } + + OnlyWriteLock(RWLock *rw_lock) + { + rw=rw_lock; + + rw->WriteLock(); + } + + ~OnlyWriteLock() + { + Unlock(); + } + + void Unlock() + { + if(rw) + { + rw->WriteUnlock(); + rw=nullptr; + } + } + };//class WriteLock +}//namespace hgl +#endif//HGL_RWLOCK_INCLUDE diff --git a/inc/hgl/thread/RingBuffer.cpp b/inc/hgl/thread/RingBuffer.cpp new file mode 100644 index 00000000..4a62ab48 --- /dev/null +++ b/inc/hgl/thread/RingBuffer.cpp @@ -0,0 +1,58 @@ +#ifndef HGL_THREAD_RING_BUFFER_SOURCE +#define HGL_THREAD_RING_BUFFER_SOURCE + +/** +* 由于设定read_pos=write_pos表示无数据,所以当数据刚好读写到结尾时,不立即转成0,而是仍为buffer_size +*/ +//-------------------------------------------------------------------------------------------------- +namespace hgl +{ + template + RingBuffer::RingBuffer(int size) + { + buffer_size=size; + + buffer=new T[size]; + +// memset(buffer,0,size); //有write_pos/read_pos没有根本读不出数据,所以无需清0 + + read_pos=0; + write_pos=0; + } + + template + RingBuffer::~RingBuffer() + { + delete[] buffer; + } + + template + void RingBuffer::Clear() + { + read_pos=0; + write_pos=0; + } + + template + void RingBuffer::SafeClear() + { + Lock(); + Clear(); + Unlock(); + } + + template + void RingBuffer::ClampPosition() + { + if(read_pos +#include +#include +namespace hgl +{ + /** + * 多线程环形数据流,用于随时被读或写的情况以及在多线程应用中同时被读与写的情况。 + */ + template class RingBuffer:protected ThreadMutex ///多线程环形数据流 + { + protected: + + T *buffer; + int buffer_size; + + int read_pos,write_pos; + + int read_cur,write_cur; + int read_off,write_off; + int read_max,write_max; + int read_count,write_count; + + bool read_peek; + + protected: + + void ClampPosition(); + + int _GetReadSize()const{return write_pos-read_pos;} + int _GetWriteSize()const{return buffer_size-(write_pos-read_pos);} + + int _SafeWriteStart(); + int _SafeReadStart(bool); + + int _Write(const T *,int); + int _Read(T *,int,bool); + + public: + + RingBuffer(int); ///<本类构造函数 + virtual ~RingBuffer(); ///<本类析构函数 + + const int GetBufferSize()const{return buffer_size;} ///<除取缓冲区长度 + + void Clear(); ///<清除整个缓冲区 + void SafeClear(); ///<安全清除整个缓冲区 + + public: //写处理函数 + + int WriteStart(); ///<开始写入 + int GetWriteSize()const{return write_max;} ///<取得可写入数据长度 + int Write(const T *,int); ///<向流中写入数据 + int WriteEnd(); ///<结束写入 + + int SafeTryWriteStart(); ///<安全尝试开始写入 + int SafeWriteStart(); ///<安全开始写入 + int SafeWriteEnd(); ///<安全结束写入 + + int SafeGetWriteSize(); ///<安全取得可写入数据长度 + int SafeWrite(const T *,int); ///<安全写入,用于简单的一次性写入 + + public: //读处理函数 + + int ReadStart(bool=true); ///<开始读取 + int GetReadSize()const{return read_max;} ///<取得可读取数据长度 + int Read(T *,int,bool=true); ///<从流中读取数据 + int Peek(T *ptr,int size){return Read(ptr,size,false);} ///<从流中预读数据 + int Skip(int size){return Read(0,size,true);} ///<跳过流中的指定长度数据 + int ReadEnd(); ///<结束写入 + + int SafeTryReadStart(bool=true); ///<安全尝试开始读取 + int SafeReadStart(bool=true); ///<安全开始读取 + int SafeReadEnd(); ///<安全结束读取 + + int SafeGetReadSize(); ///<安全取得可读取数据长度 + bool SafeTryGetReadSize(int &); ///<安全尝试取得可读取数据长度 + int SafeRead(T *,int,bool=true); ///<安全读取,用于简单的一次性读取 + int SafePeek(T *ptr,int size){return SafeRead(ptr,size,false);} ///<安全预读数据 + };//class RingBuffer +}//namespace hgl + +#include +#include +#include + +namespace hgl +{ + namespace io + { + class RingInputStream:public InputStream + { + RingBuffer *rb; + + public: + + RingInputStream (RingBuffer *_rb){rb=_rb;} + + RingBuffer *GetRingBuffer(){return rb;} + + int Start (){return rb?rb->ReadStart():-1;} + int End (){return rb?rb->ReadEnd():-1;} + int SafeStart (){return rb?rb->SafeReadStart():-1;} + int SafeEnd (){return rb?rb->SafeReadEnd():-1;} + + void Close (){} + + public: + + int64 Read (void *buf,int64 size){return rb?rb->Read((char *)buf,size):-1;} ///<读取数据 + int64 Peek (void *buf,int64 size){return rb?rb->Peek((char *)buf,size):-1;} ///<预览数据 + + bool CanRestart ()const{return false;} ///<是否可以复位 + bool CanSeek ()const{return false;} ///<是否可以定位 + bool CanSize ()const{return false;} ///<是否可以取得尺寸 + bool CanPeek ()const{return false;} ///<是否可以预览数据 + + bool Restart (){return false;} ///<复位访问指针 + int64 Skip (int64 size){return rb?rb->Skip(size):-1;} ///<跳过指定字节不访问 + int64 Seek (int64,SeekOrigin){return -1;} ///<移动访问指针 + int64 Tell ()const{return -1;} ///<返回当前访问位置 + int64 GetSize ()const{return -1;} ///<取得流长度 + int64 Available ()const{return rb?rb->GetReadSize():-1;} ///<剩下的可以不受阻塞访问的字节数 + };//class RingInputStream + + class RingOutputStream:public OutputStream + { + RingBuffer *rb; + + public: + + RingOutputStream (RingBuffer *_rb){rb=_rb;} + + RingBuffer *GetRingBuffer(){return rb;} + + int Start (){return rb?rb->WriteStart():-1;} + int End (){return rb?rb->WriteEnd():-1;} + int SafeStart (){return rb?rb->SafeWriteStart():-1;} + int SafeEnd (){return rb?rb->SafeWriteEnd():-1;} + + void Close (){} + + public: + + int64 Write (const void *buf,int64 size){return rb?rb->Write((char *)buf,size):-1;} ///<写入数据 + + bool CanRestart ()const{return false;}; ///<是否可以复位 + bool CanSeek ()const{return false;}; ///<是否可以定位 + bool CanSize ()const{return false;} ///<是否可以取得尺寸 + + bool Restart (){return false;} ///<复位访问指针 + int64 Seek (int64,SeekOrigin){return -1;} ///<移动访问指针 + int64 Tell ()const{return -1;} ///<返回当前访问位置 + int64 GetSize ()const{return -1;} ///<取得流长度 + int64 Available ()const{return rb?rb->GetWriteSize():-1;} ///<剩下的可以不受阻塞写入的字节数 + };//class RingOutputStream + }//namespace io + + class RingBufferRead + { + RingBuffer *rb; + int size; + + public: + + RingBufferRead(RingBuffer *_rb) + { + rb=_rb; + + size=rb->ReadStart(); + } + + RingBufferRead(io::RingInputStream *ris) + { + rb=ris->GetRingBuffer(); + + size=rb->ReadStart(); + } + + ~RingBufferRead() + { + Unlock(); + } + + void Unlock() + { + if(size>0) + { + rb->ReadEnd(); + size=0; + } + } + + int GetSize() const + { + return size; + } + };//class RingBufferRead + + class RingBufferSafeRead + { + RingBuffer *rb; + int size; + + public: + + RingBufferSafeRead(RingBuffer *_rb) + { + rb=_rb; + size=-1; + } + + RingBufferSafeRead(io::RingInputStream *ris) + { + rb=ris->GetRingBuffer(); + size=-1; + } + + int Start() + { + size=rb->SafeReadStart(); + return size; + } + + int TryStart() + { + size=rb->SafeTryReadStart(); + return size; + } + + int GetSize() + { + size=rb->GetReadSize(); + return size; + } + + ~RingBufferSafeRead() + { + Unlock(); + } + + void Unlock() + { + if(size>0) + { + rb->SafeReadEnd(); + size=0; + } + } + };//class RingBufferSafeRead + + class RingBufferWrite + { + RingBuffer *rb; + int size; + + public: + + RingBufferWrite(RingBuffer *_rb) + { + rb=_rb; + + size=rb->WriteStart(); + } + + RingBufferWrite(io::RingOutputStream *ros) + { + rb=ros->GetRingBuffer(); + + size=rb->WriteStart(); + } + + ~RingBufferWrite() + { + Unlock(); + } + + void Unlock() + { + if(size>0) + { + rb->WriteEnd(); + size=0; + } + } + + int GetSize() const + { + return size; + } + };//class RingBufferWrite + + class RingBufferSafeWrite + { + RingBuffer *rb; + int size; + + public: + + RingBufferSafeWrite(RingBuffer *_rb) + { + rb=_rb; + + size=-1; + } + + RingBufferSafeWrite(io::RingOutputStream *ros) + { + rb=ros->GetRingBuffer(); + } + + int Start() + { + size=rb->SafeWriteStart(); + return(size); + } + + int TryStart() + { + size=rb->SafeTryWriteStart(); + return(size); + } + + ~RingBufferSafeWrite() + { + Unlock(); + } + + int Unlock() + { + int result=size; + + if(size>0) + { + rb->SafeWriteEnd(); + size=0; + } + + return result; + } + };//class RingBufferSafeWrite +}//namespace hgl +#endif//HGL_THREAD_RING_BUFFER_INCLUDE diff --git a/inc/hgl/thread/RingBufferRead.cpp b/inc/hgl/thread/RingBufferRead.cpp new file mode 100644 index 00000000..ea1eb67b --- /dev/null +++ b/inc/hgl/thread/RingBufferRead.cpp @@ -0,0 +1,210 @@ +#ifndef HGL_THREAD_RING_BUFFER_READ_SOURCE +#define HGL_THREAD_RING_BUFFER_READ_SOURCE +#include + +namespace hgl +{ + /** + * 安全取得可读取数据长度 + */ + template + int RingBuffer::SafeGetReadSize() + { + Lock(); + + const int result=_GetReadSize(); + + Unlock(); + + return(result); + } + + /** + * 安全尝试取得可读取数据长度 + */ + template + bool RingBuffer::SafeTryGetReadSize(int &result) + { + if(!TryLock()) + return(false); + + result=_GetReadSize(); + + Unlock(); + + return(true); + } + + template + int RingBuffer::ReadStart(bool peek) + { + ClampPosition(); + + write_off=write_pos%buffer_size; + + read_max=_GetReadSize(); + + read_peek=peek; //标记是否真的取走 + read_count=0; + read_cur=read_pos; + + return(read_max); + } + + template + int RingBuffer::_SafeReadStart(bool peek) + { + ReadStart(peek); + + if(read_max<=0) + Unlock(); + + return(read_max); + } + + /** + * 尝试开始读取数据,如失败或没有数据会立即解锁,不必再次调用SafeReadEnd + * @param peek 是否真的取出数据 + * @return >0 可供读取的数据数量 + * @return =0 没有可供读取的数据 + * @return <0 暂时不能读取 + */ + template + int RingBuffer::SafeTryReadStart(bool peek) + { + if(!TryLock()) + return(-1); + + return _SafeReadStart(peek); + } + + /** + * 开始读取数据,如果没有数据会立即关闭缓冲区,不必再次调用SafeReadEnd + * @param peek 是否真的取出数据 + * @return 可供读取的数据数量 + */ + template + int RingBuffer::SafeReadStart(bool peek) + { + Lock(); + + return _SafeReadStart(peek); + } + + /** + * 读取数据 + * @param data 欲将访问数据存放的内存地址,可为NULL用于单纯后移读取指针 + * @param size 欲访问的数据长度 + * @param peek 是否后移访问指针(默认为真,仅针对当前这一次) + * @return 实际可访问的数据长度 + */ + template + int RingBuffer::Read(T *data,int size,bool peek) + { + if(size<=0)return(-1); + + const int result=_Read(data,size,peek); + + if(peek) + read_count+=result; + + return(result); + } + + /** + * 读取结束 + * @return 返回读取的数据长度 + */ + template + int RingBuffer::ReadEnd() + { + const int result=read_count; + + if(read_peek&&result) + read_pos=read_cur; + + return result; + } + + /** + * 安全读取结束 + * @return 返回读取的数据长度 + */ + template + int RingBuffer::SafeReadEnd() + { + const int result=ReadEnd(); + + Unlock(); + + return result; + } + + /** + * 安全的读取数据,,此函数会直接开锁解锁,用于少量的一次性处理。如大量的数据要分次读取,请使用SafeReadStart/SafeReadEnd + * @param data 欲将访问数据存放的内存地址,可为NULL用于单纯后移读取指针 + * @param size 欲访问的数据长度 + * @param peek 是否真的取出数据 + * @return 实际读取的数据长度 + * @return -1 出错 + */ + template + int RingBuffer::SafeRead(T *data,int size,bool peek) + { + if(size<0)return(-1); + if(size&&!data)return(-1); + + if(SafeReadStart(peek)<=0) + return(-1); + + Read(data,size,peek); + + return SafeReadEnd(); + } + + template + int RingBuffer::_Read(T *data,int size,bool peek) + { + if(size<=0||read_max<=0)return(0); + + if(size>read_max) + size=read_max; + + if(size>0) + { + if(data) //data可以为空,用于先尝试取数据后直接移走 + { + const int temp_read =read_cur %buffer_size; + + if(temp_readtemp) + { + memcpy(data,buffer+temp_read,temp*sizeof(T)); + + memcpy((char *)(data+temp),buffer,(size-temp)*sizeof(T)); + } + else + { + memcpy(data,buffer+temp_read,size*sizeof(T)); + } + } + }//if(data) + + if(peek) + { + read_cur+=size; + read_max-=size; + } + } + + return(size); + } +}//namespace hgl +#endif//HGL_THREAD_RING_BUFFER_READ_SOURCE diff --git a/inc/hgl/thread/RingBufferWrite.cpp b/inc/hgl/thread/RingBufferWrite.cpp new file mode 100644 index 00000000..2eada887 --- /dev/null +++ b/inc/hgl/thread/RingBufferWrite.cpp @@ -0,0 +1,181 @@ +#ifndef HGL_THREAD_RING_BUFFER_WRITE_SOURCE +#define HGL_THREAD_RING_BUFFER_WRITE_SOURCE +#include + +namespace hgl +{ + /** + * 安全取得可写入数据长度 + */ + template + int RingBuffer::SafeGetWriteSize() + { + Lock(); + + const int result=_GetWriteSize(); + + Unlock(); + + return(result); + } + + template + int RingBuffer::WriteStart() + { + ClampPosition(); + + read_off=read_pos%buffer_size; + + write_max=_GetWriteSize(); + + write_count=0; + write_cur=write_pos; + + return write_max; + } + + template + int RingBuffer::_SafeWriteStart() + { + WriteStart(); + + if(write_max<=0) + Unlock(); + + return write_max; + } + + /** + * 尝试开始写入 + * @return >0 成功开始,可写入的数据长度 + * @return =0 没有可以写入的空间 + * @return <0 暂时不可写入 + */ + template + int RingBuffer::SafeTryWriteStart() + { + if(!TryLock()) + return(-1); + + return _SafeWriteStart(); + } + + /** + * 开始写入数据,如果没有空间会立即关闭缓冲区,不必再次调用SafeWriteEnd + * @return 可写入的数据长度 + */ + template + int RingBuffer::SafeWriteStart() + { + Lock(); + + return _SafeWriteStart(); + } + + /** + * 结束写入数据 + * @param data 要写入的数据 + * @param size 要写入的数据长度 + * @return 实际写入的数据长度 + */ + template + int RingBuffer::Write(const T *data,int size) + { + if(!data||size<=0)return(-1); + + const int result=_Write(data,size); + + write_count+=result; + + return result; + } + + /** + * 写入结束 + * @return 返回写入的数据长度 + */ + template + int RingBuffer::WriteEnd() + { + const int result=write_count; + + if(result) + write_pos=write_cur; + + return result; + } + + /** + * 安全写入结束 + * @return 返回写入的数据长度 + */ + template + int RingBuffer::SafeWriteEnd() + { + const int result=WriteEnd(); + + Unlock(); + + return result; + } + + /** + * 安全写入数据,此函数会直接开锁解锁,用于少量的一次性处理。如大量的数据要分次写入,请使用SafeWriteStart/SafeWriteEnd + * @param data 要写入的数据 + * @param size 要写入的数据长度 + * @return 实际写入的数据长度 + * @return -1 出错 + */ + template + int RingBuffer::SafeWrite(const T *data,int size) + { + if(!data||size<=0)return(-1); + + if(SafeWriteStart()<=0) + return(-1); + + Write(data,size); + + return SafeWriteEnd(); + } + + template + int RingBuffer::_Write(const T *data,int size) + { + if(size<=0||write_max<=0)return(0); + + if(size>write_max) + size=write_max; + + if(size>0) + { + const int temp_write=write_cur%buffer_size; + + if(read_off<=temp_write) + { + int temp=buffer_size-temp_write; + + if(size>temp) + { + memcpy(buffer+temp_write,data,temp*sizeof(T)); + + memcpy(buffer,(char *)(data+temp),(size-temp)*sizeof(T)); + } + else + { + memcpy(buffer+temp_write,data,size*sizeof(T)); + } + } + else + { + memcpy(buffer+temp_write,data,size*sizeof(T)); + } + + write_cur+=size; + write_max-=size; + } + + return size; + } +}//namespace hgl +#endif//HGL_THREAD_RING_BUFFER_WRITE_SOURCE diff --git a/inc/hgl/thread/SemLock.h b/inc/hgl/thread/SemLock.h new file mode 100644 index 00000000..c5e96faf --- /dev/null +++ b/inc/hgl/thread/SemLock.h @@ -0,0 +1,233 @@ +#ifndef HGL_THREAD_SEM_LOCK_INCLUDE +#define HGL_THREAD_SEM_LOCK_INCLUDE + +#include +#include +#include +namespace hgl +{ + template class SemLockTemplate + { + protected: + + T data; + + L lock; + Semaphore sem; + + public: + + SemLockTemplate(){} + + /** + * 本类构造函数 + * @param d 数据 + * @param sem_count 最大信号数量(默认0表示不限制) + */ + SemLockTemplate(T &d,int sem_count=0):sem(sem_count) + { + data=d; + } + + public: //数据相关 + + void operator = (T &d){data=d;} + T *operator->(){return &data;} + + public: //信号相关 + + /** + * 释放信号 + * @param n 释放的信号数量 + * @return 是否成功 + */ + bool Post(int n=1) + { + if(n<=0)return(false); + return sem.Post(n); + } + + bool TryAcquire(){return sem.TryAcquire();} ///<尝试获取一个信号 + /** + * 获取一个信号 + * @param time_out 超时时间 + * @return 是否成功 + */ + bool Acquire(double time_out=0.0f){return sem.Acquire();} + };//template class SemLockTemplate + + /** + * 信号线程排斥 + */ + template class SemThreadMutex:public SemLockTemplate + { + public: + + using SemLockTemplate::SemLockTemplate; + + public: //线程排斥相关 + + void Lock(){this->lock.Lock();} ///<取得的控制权(如果对象处于排斥状态,则等待) + bool TryLock(){return this->lock.TryLock();} ///<尝试取得控制权 + bool WaitLock(double time_out=0){return this->lock.WaitLock();} ///<等待并取得控制权 + void Unlock(){this->lock.Unlock();} ///<放弃控制权 + + public: //综合应用相关 + + /** + * 在指定时间内如果成功捕获到信号则锁定 + * @param time_out 最长等待时间 + * @return 是否锁定了 + */ + bool WaitSemLock(double time_out) + { + if(!this->sem.Acquire(time_out)) + return(false); + + this->lock.Lock(); + return(true); + } + + /** + * 尝试捕获一个信号,如果成功则锁定 + * @return 是否锁定了 + */ + bool TrySemLock() + { + if(!this->sem.TryAcquire()) + return(false); + + this->lock.Lock(); + return(true); + } + + /** + * 锁定 + * @param try_lock 是否是尝试锁定 + * @param time_out 如果不是尝试锁定,则等待锁定的超时时间 + */ + bool SemLock(bool try_lock,double time_out) + { + if(try_lock) + { + if(!this->sem.TryAcquire()) + return(false); + } + else //当前没人,那就慢慢等吧 + { + if(!this->sem.Acquire(time_out)) + return(false); + } + + this->lock.Lock(); + return(true); + } + + /** + * 解锁并释放信号 + * @param n 释放的信号数量 + */ + void SemUnlock(int n=1) + { + this->lock.Unlock(); + + if(n>0) + this->sem.Post(n); + } + };//template class SemThreadMutex + + /** + * 信号读写锁 + */ + template class SemRWLock:public SemLockTemplate + { + public: + + using SemLockTemplate::SemLockTemplate; + + public: //读写锁相关 + + HGL_RWLOCK(this->lock); + + public: //综合应用相关 + + /** + * 在指定时间内如果成功捕获到信号则共享锁定 + * @param time_out 最长等待时间 + * @return 是否锁定了 + */ + bool WaitSemReadLock(double time_out) + { + if(!this->sem.Acquire(time_out)) + return(false); + + this->lock.ReadLock(); + return(true); + } + + /** + * 在指定时间内如果成功捕获到信号则独占锁定 + * @param time_out 最长等待时间 + * @return 是否锁定了 + */ + bool WaitSemWriteLock(double time_out) + { + if(!this->sem.Acquire(time_out)) + return(false); + + this->lock.WriteLock(); + return(true); + } + + /** + * 尝试捕获一个信号,如果成功则共享锁定 + * @return 是否锁定了 + */ + bool TrySemReadLock() + { + if(!this->sem.TryAcquire()) + return(false); + + this->lock.ReadLock(); + return(true); + } + + /** + * 尝试捕获一个信号,如果成功则独占锁定 + * @return 是否锁定了 + */ + bool TrySemWriteLock() + { + if(!this->sem.TryAcquire()) + return(false); + + this->lock.WriteLock(); + return(true); + } + + /** + * 解除共享锁并释放信号 + * @param n 释放的信号数量 + */ + void SemReadUnlock(int n=1) + { + this->lock.ReadUnlock(); + + if(n>0) + this->sem.Post(n); + } + + /** + * 解除独占锁并释放信号 + * @param n 释放的信号数量 + */ + void SemWriteUnlock(int n=1) + { + this->lock.WriteUnlock(); + + if(n>0) + this->sem.Post(n); + } + };//template class SemRWLock +}//namespace hgl +#endif//HGL_THREAD_SEM_LOCK_INCLUDE diff --git a/inc/hgl/thread/Semaphore.h b/inc/hgl/thread/Semaphore.h new file mode 100644 index 00000000..f9024446 --- /dev/null +++ b/inc/hgl/thread/Semaphore.h @@ -0,0 +1,33 @@ +#ifndef HGL_SEMAPHORE_INCLUDE +#define HGL_SEMAPHORE_INCLUDE + +#ifdef __APPLE__ +#include +#endif//__APPLE__ + +namespace hgl +{ + /** + * 信号是用于多线程同步中常用的一种技术
+ * 注意信号的用法是要有信号被发送出来,才能获取到信号。 + */ + class Semaphore ///信号 + { +#ifdef __APPLE__ + dispatch_semaphore_t ptr; +#else + void *ptr; +#endif//__APPLE__ + + public: + + Semaphore(int=1024); + virtual ~Semaphore(); + + virtual bool Post(int n=1); ///<发送信号 + + virtual bool TryAcquire(); ///<尝试取得一个信号 + virtual bool Acquire(double time=0.0); ///<等待并获取一个信号 + };//class Semaphore +}//namespace hgl +#endif//HGL_SEMAPHORE_INCLUDE diff --git a/inc/hgl/thread/SwapColl.h b/inc/hgl/thread/SwapColl.h new file mode 100644 index 00000000..92078c06 --- /dev/null +++ b/inc/hgl/thread/SwapColl.h @@ -0,0 +1,156 @@ +#ifndef HGL_THREAD_SWAP_LIST_INCLUDE +#define HGL_THREAD_SWAP_LIST_INCLUDE + +#include +#include +#include +#include +namespace hgl +{ + /** + * 数据交换合集 + */ + template class S> class SwapColl + { + protected: + + S join_list; + S proc_list; + + ThreadMutex lock; + + public: + + virtual ~SwapColl(){} + + /** + * 加入一个数据到合集中 + */ + bool Add(T &item) + { + lock.Lock(); + int result=join_list.Add(item); + lock.Unlock(); + + return(result!=-1); + } + + /** + * 增加一批数据到合集中 + */ + int Add(T *item_list,const int count) + { + lock.Lock(); + int result=join_list.Add(item_list,count); + lock.Unlock(); + + return result; + } + + /** + * 取得可以使用的列表 + */ + S &GetProcList() + { + lock.Lock(); + proc_list.Add(join_list); + join_list.ClearData(); + lock.Unlock(); + + return proc_list; + } + + S *operator ->(){return &proc_list;} + operator S &(){return proc_list;} + };//template class SwapColl + + template using SwapList=SwapColl; ///<安全交换列表 + template using SwapSet=SwapColl; ///<安全交换集合 + + /** + * 信号安全交换合集 + */ + template class S> class SemSwapColl + { + protected: + + S join_list; + S proc_list; + + ThreadMutex lock; + Semaphore sem; + + public: + + virtual ~SemSwapColl()=default; + + /** + * 增加一个数据到合集中 + */ + bool Add(T &item) + { + lock.Lock(); + int result=join_list.Add(item); + lock.Unlock(); + + if(result!=-1) + sem.Post(1); + + return(result!=-1); + } + + /** + * 增加一批数据到合集中 + */ + int Add(T *item_list,const int count) + { + lock.Lock(); + int result=join_list.Add(item_list,count); + lock.Unlock(); + + if(result>0) + sem.Post(1); + + return result; + } + + /** + * 等待信号 + */ + bool WaitProc(const double time_out=HGL_TIME_ONE_MINUTE) + { + if(!sem.Acquire(time_out)) + return(false); + + lock.Lock(); + proc_list.Add(join_list); + join_list.ClearData(); + lock.Unlock(); + + return(true); + } + + /** + * 等待信号 + */ + bool TryProc() + { + if(!sem.TryAcquire()) + return(false); + + lock.Lock(); + proc_list.Add(join_list); + join_list.ClearData(); + lock.Unlock(); + + return(true); + } + + S *operator ->(){return &proc_list;} + operator S &(){return proc_list;} + };//template class SemSwapColl + + template using SemSwapList=SemSwapColl; ///<安全信号交换列表 + template using SemSwapSet=SemSwapColl; ///<安全信号交换集合 +}//namespace hgl +#endif//HGL_THREAD_SWAP_LIST_INCLUDE diff --git a/inc/hgl/thread/SwapData.h b/inc/hgl/thread/SwapData.h new file mode 100644 index 00000000..2a788cc5 --- /dev/null +++ b/inc/hgl/thread/SwapData.h @@ -0,0 +1,240 @@ +#ifndef HGL_THREAD_SWAP_DATA_INCLUDE +#define HGL_THREAD_SWAP_DATA_INCLUDE + +#include +#include + +namespace hgl +{ + /** + * 单向多线程数据交换模板
+ * 适用环境为多个线程向其投递数据,一个线程接收数据。接收方在每次处理前交换数据指针,以达到最小线程切换代价 + */ + template class SwapData + { + protected: + + T data[2]; + + int post_index; + int recv_index; + + ThreadMutex lock; + + protected: + + void _Swap() + { + if(recv_index){recv_index=0;post_index=1;} + else{recv_index=1;post_index=0;} + } + + public: + + SwapData() + { + recv_index=0; + post_index=1; + } + + virtual ~SwapData()=default; + + /** + * 获取投递方数据访问权 + */ + T &GetPost() + { + lock.Lock(); + + return data[post_index]; + } + + /** + * 释放多线程投递方数据访问权 + */ + void ReleasePost() + { + lock.Unlock(); + } + + /** + * 取得接收方数据访问权 + */ + T &GetReceive(){return data[recv_index];} + + /** + * 交换双方数据 + */ + void Swap() + { + lock.Lock(); + + this->_Swap(); + + lock.Unlock(); + } + + /** + * 尝试交换双方数据 + */ + bool TrySwap() + { + if(!lock.TryLock()) + return(false); + + this->_Swap(); + + lock.Unlock(); + return(true); + } + +#ifndef __APPLE__ + /** + * 尝试交换双方数据 + */ + bool WaitSwap(const double time_out) + { + if(!lock.WaitLock(time_out)) + return(false); + + this->_Swap(); + + lock.Unlock(); + return(true); + } +#endif//__APPLE__ + };//template class SwapData + + /** + * 信号自动交换数据访问模板 + */ + template class SemSwapData:public SwapData + { + Semaphore sem; + + public: + + using SwapData::SwapData; + ~SemSwapData()=default; + + /** + * 释放接收信号 + * @param count 信号个数 + */ + void PostSem(int count=1) + { + sem.Post(count); + } + + /** + * 等待获取一个信号并交换前后台数据 + * @param time_out 等待时长 + */ + bool WaitSemSwap(const double time_out=5) + { + if(!sem.Acquire(time_out)) + return(false); + + this->Swap(); + return(true); + } + + /** + * 尝试获取一个信号并交换前后台数据 + */ + bool TrySemSwap() + { + if(!sem.TryAcquire()) + return(false); + + this->Swap(); + return(true); + } + };//template class SemSwapData:public SwapData + + /** + * SwapData模板自动释放Post工具模板 + */ + template class PostToSwapData + { + SwapData *swap_data; + T *post; + + public: + + PostToSwapData(SwapData *sd) + { + swap_data=sd; + + if(swap_data) + post=&(swap_data->GetPost()); + else + post=nullptr; + } + + ~PostToSwapData() + { + if(swap_data) + swap_data->ReleasePost(); + } + + T *operator ->(){return post;} + };//template class PostToSwapData + + /** + * SemSwapData模板自动释放Post工具模板 + */ + template class PostToSemSwapData + { + SemSwapData *swap_data; + T *post; + + public: + + PostToSemSwapData(SemSwapData *sd) + { + swap_data=sd; + + if(swap_data) + post=&(swap_data->GetPost()); + else + post=nullptr; + } + + ~PostToSemSwapData() + { + if(swap_data) + { + swap_data->ReleasePost(); + swap_data->PostSem(); + } + } + + T *operator ->(){return post;} + };//template class PostToSemSwapData + + /** + * 使用范例 + * + * using EventQueue=Queue; + * using MTEventQueue=SemSwapData; + * using MTEventPost=PostToSemSwapData; + * + * MTEventQueue mt_event_queue; + * + * 新方式: + * MTEventPost post(mt_event_queue); + * + * post.Push(1); + * + * 直接模式: + * EventQueue &eq=mt_event_queue.GetPost(); + * + * eq->Push(1); + * + * mt_event_queue.ReleasePost(); + * mt_event_queue.PostSem(); + * + */ +}//namespace hgl +#endif//HGL_THREAD_SWAP_DATA_INCLUDE diff --git a/inc/hgl/thread/Thread.h b/inc/hgl/thread/Thread.h new file mode 100644 index 00000000..15002820 --- /dev/null +++ b/inc/hgl/thread/Thread.h @@ -0,0 +1,230 @@ +#ifndef HGL_THREAD_INCLUDE +#define HGL_THREAD_INCLUDE + +#include +#include +#include +#include +#include + +namespace hgl +{ + void WaitThreadExit(thread_ptr tp,const double &time_out); + + /** + * 线程类.本类用于建立一个线程并管理它。
+ * Sleep和Exit函数是给线程内的程序使用的;而Start,Close,Pause,Rewind是给线程外的程序使用的。
+ * 使用本类只需要重载本类,并将代码写在Execute函数内即可。
+ * 执行大概为:
+ * if(ProcStartThread())
+ * while(Execute());
+ * else
+ * return(0); + *
+ * ProcEndThread(); + */ + class Thread ///线程类 + { + friend void WaitThread(Thread **,int,double); + + private: + + thread_ptr tp=0; + + ThreadMutex live_lock; + ThreadMutex exit_lock; + + friend THREAD_FUNC ThreadFunc(Thread *tc); + +#ifdef _DEBUG + UTF8String thread_addr_string; ///<线程地址用字符串,调试使用 +#endif//_DEBUG + + public: + + virtual ~Thread()=default; + +#ifdef _DEBUG + const UTF8String &GetThreadAddressString()const{return thread_addr_string;} ///<取得线程地址字符串 +#endif//_DEBUG + + /** + * 线程执行函数,会被反复调用 + * @return true 继续执行 + * @return false 退出执行 + */ + virtual bool Execute()=0; ///<线程的运行函数 + + virtual bool ProcStartThread() ///<线程启动运行函数,在Execute前被调用 + { +#ifdef _DEBUG + char thread_addr[(sizeof(thread_ptr)<<1)+1]; + + DataToUpperHexStr(thread_addr,(uint8 *)&tp,sizeof(thread_ptr)); + + thread_addr_string=thread_addr; +#endif//_DEBUG + + return(true); + } + + virtual void ProcEndThread(){} ///<结程结束运行函数,在Execute后被调用 + + virtual bool IsExitDelete()const{return true;} ///<返回在退出线程时,是否删除本对象(注:此函数不可动态变动值) + + bool IsLive() ///<当前线程是否还活着 + { + if(live_lock.TryLock()) + { + //成功了,证明这个线程已经关闭了 + live_lock.Unlock(); + return(false); + } + + return(true); + } + + public: //线程运行控制 + + virtual bool Start(); ///<开始运行当前线程 + + virtual bool IsCurThread(); ///<是否是当前线程 + + virtual void Exit() ///<退出当前线程(其它线程调用) + { + exit_lock.Unlock(); + } + + /** + * (线程外部调用)退出当前线程,并等待其完成退出
+ * @param time_out 等待的时间,如果为0表示等到线程运行结束为止。默认为0 + */ + virtual void WaitExit(const double &time_out=0) + { + if(!tp) + return; + + thread_ptr self_tp=tp; + + Exit(); + + WaitThreadExit(self_tp,time_out); + } + };//class Thread + + void WaitThread(Thread **,int,double time=0); ///<等待多个线程中的一个完成 + + bool CreateThread(Thread *); ///<创建一个线程 + + /** + * 简单的多线程管理 + */ + template class MultiThreadManage + { + protected: + + Set thread_set; + + public: + + virtual ~MultiThreadManage() + { + Close(); + } + + THREAD *GetThread(int index) + { + THREAD *result; + + if(thread_set.Get(index,result)) + return result; + + return nullptr; + } + + /** + * 增加一个线程到合集中 + * @return 是否增加成功 + */ + bool Add(THREAD *p) + { + if(!p)return(false); + + return(thread_set.Add(p)!=-1); + } + + /** + * 删除一个线程 + */ + void Delete(THREAD *p) + { + if(!p)return; + + thread_set.Delete(p); + } + + /** + * 关闭所有线程 + */ + void Close() + { + const int count=thread_set.GetCount(); + + THREAD **p=thread_set.GetData(); + + for(int i=0;iWaitExit(); + ++p; + } + + thread_set.ClearData(); + } + + /** + * 启动所有线程 + * @return 成功启动的线程数量 + */ + int Start() + { + const int count=thread_set.GetCount(); + + THREAD **p=thread_set.GetData(); + + int total=0; + + for(int i=0;iStart()) + ++total; + + ++p; + } + + return total; + } + + /** + * 检查还有几个线程活着 + */ + int IsLive() + { + const int count=thread_set.GetCount(); + + THREAD **p=thread_set.GetData(); + + int total=0; + + for(int i=0;iIsLive()) + ++total; + + ++p; + } + + return total; + } + };//class MultiThreadManage +}//namespace hgl +#endif//HGL_THREAD_INCLUDE diff --git a/inc/hgl/thread/ThreadMutex.h b/inc/hgl/thread/ThreadMutex.h new file mode 100644 index 00000000..47d6dd35 --- /dev/null +++ b/inc/hgl/thread/ThreadMutex.h @@ -0,0 +1,163 @@ +#ifndef HGL_THREAD_MUTEX_INCLUDE +#define HGL_THREAD_MUTEX_INCLUDE + +#include +#include +namespace hgl +{ + /** + * 排斥(线程)访问类可以判断数据在被一个代码段访问时,不能被另一代码段访问
+ * 注:此排斥仅在当前进程内有效 + */ + class ThreadMutex ///排斥访问类(仅当前进程) + { + cm_thread_mutex ptr; + + public: + + ThreadMutex(); ///<本类构造函数 + virtual ~ThreadMutex(); ///<本类析构函数 + + cm_thread_mutex *GetThreadMutex(){return &ptr;} + + virtual void Lock(); ///<取得的控制权(如果对象处于排斥状态,则等待) + virtual bool TryLock(); ///<尝试取得控制权 +#if !defined(__APPLE__)&&!defined(__ANDROID__) + virtual bool WaitLock(const double=0); ///<等待并取得控制权 +#endif//__APPLE__ + virtual void Unlock(); ///<放弃控制权 + };//class Mutex + + /** + * 线程排斥对象 + */ + template class ThreadMutexObject:public ThreadMutex + { + T *data; + + public: + + ThreadMutexObject() + { + data=new T; + } + + ThreadMutexObject(T *t) + { + data=t; + } + + virtual ~ThreadMutexObject() + { + SAFE_CLEAR(data); + } + + void operator = (T *t) + { + if(data) + delete data; + + data=t; + } + + T *operator ->() + { + return data; + } + + bool valid()const + { + return data; + } + + bool operator !() + { + return !data; + } + };//class ThreadMutexObject + + /** + * 线程排斥对像阵列 + */ + template class ThreadMutexObjectArray + { + protected: + + ThreadMutexObject *items; + + public: + + ThreadMutexObjectArray() + { + items=nullptr; + } + + ThreadMutexObjectArray(int count) + { + if(count<=0) + { + items=nullptr; + } + else + { + items=new ThreadMutexObject[count]; + } + } + + virtual ~ThreadMutexObjectArray() + { + delete[] items; //delete nullptr不是个错误 + } + + ThreadMutexObject &operator [](int index) + { + return items[index]; + } + };//class ThreadMutexObjectArray + + /** + * 智能自释放线程排斥锁 + */ + class ThreadMutexLock + { + ThreadMutex *tm; + + public: + + ThreadMutexLock(ThreadMutex *tm_lock) + { + tm=tm_lock; + + if(tm) + tm->Lock(); + } + + ~ThreadMutexLock() + { + if(tm) + tm->Unlock(); + } + + void Lock() + { + if(tm) + tm->Lock(); + } + + void Unlock() + { + if(tm) + tm->Unlock(); + } + + void Clear() + { + if(tm) + { + tm->Unlock(); + tm=nullptr; + } + } + };//class ThreadMutexLock +}//namespace hgl +#endif//HGL_THREAD_MUTEX_INCLUDE diff --git a/inc/hgl/thread/Workflow.h b/inc/hgl/thread/Workflow.h new file mode 100644 index 00000000..b233eb31 --- /dev/null +++ b/inc/hgl/thread/Workflow.h @@ -0,0 +1,371 @@ +#ifndef HGL_WORKFLOW_INCLUDE +#define HGL_WORKFLOW_INCLUDE + +#include +#include +#include +#include +#include +namespace hgl +{ + /** + * 工作流名字空间
+ * 工作流是一种对工作的多线安排管理机制,它适用于按业务分配多线程的工作环境
+ * 开发者需要为每一种工作指定一定的线程数量,但每一种工作确只有一个工作分配入口和分发出口。
+ * 由其它程序提交工作任务到入口,开发者可以自行重载分配入口的分配函数。 + */ + namespace workflow + { + /** + * 工作处理基类模板 + * @param W 工作对象 + */ + template class WorkProc + { + public: + + virtual ~WorkProc()=default; + + public: //投递工作线程所需调用的方法 + + virtual void Post(W *w)=0; ///<投递一个工作 + virtual void Post(W **w,int count)=0; ///<投递一批工作 + + public: //需用户重载实现的真正执行工作的方法 + + /** + * 单个工作执行事件函数,此函数需用户重载实现 + */ + virtual void OnWork(const uint,W *)=0; + + public: //由工作线程调用的执行工作事件函数 + + /** + * 工作执行处理函数 + */ + virtual bool OnExecuteWork(const uint)=0; + };//template class WorkProc + + /** + * 单体工作处理
+ * 该类可以由多个线程投递工作,但只能被一个工作线程获取工作 + */ + template class SingleWorkProc:public WorkProc + { + public: + + using WorkList=List; + + private: + + SemSwapData work_list; ///<工程列表 + + protected: + + double time_out; + + public: + + SingleWorkProc() + { + time_out=5; + } + + virtual ~SingleWorkProc()=default; + + void SetTimeOut(const double to) ///<设置超时时间 + { + if(to<=0)time_out=0; + else time_out=to; + } + + virtual void Post(W *w) override ///<投递一个工作 + { + WorkList &wl=work_list.GetPost(); + wl.Add(w); + work_list.ReleasePost(); + } + + virtual void Post(W **w,int count) override ///<投递一批工作 + { + WorkList &wl=work_list.GetPost(); + wl.Add(w,count); + work_list.ReleasePost(); + } + + virtual void ToWork() ///<将堆积的工作列表发送给工作线程 + { + work_list.PostSem(1); + } + + public: + + /** + * 当前工作序列完成事件函数,如需使用请重载此函数 + */ + virtual void OnFinish(const uint wt_index) + { + } + + /** + * 开始执行工作函数 + */ + virtual bool OnExecuteWork(const uint wt_index) override + { + //为什么不使用TrySemSwap,使用TrySemSwap固然会立即返回结果,但会引起线程频繁刷新造成CPU的流费。 + //使用WaitSemSwap目前唯一坏处是在退出时,需要等待超时时间。 + + if(!work_list.WaitSemSwap(time_out)) + return(false); + + WorkList &wl=work_list.GetReceive(); + + const int count=wl.GetCount(); + + if(count>0) + { + W **p=wl.GetData(); + + for(int i=0;iOnWork(wt_index,*p); + ++p; + } + + this->OnFinish(wt_index); + + wl.ClearData(); + } + + return(true); + } + };//template class SingleWorkProc:public WorkProc + + /** + * 多体工作处理
+ * 该类可以由多个线程投递工作,也可以同时被多个工作线程获取工作 + */ + template class MultiWorkProc:public WorkProc + { + protected: + + SemDataPost work_list; ///<工程列表 + + protected: + + double time_out; + + public: + + MultiWorkProc() + { + time_out=5; + } + + virtual ~MultiWorkProc()=default; + + void SetTimeOut(const double to) ///<设置超时时间 + { + if(to<=0)time_out=0; + else time_out=to; + } + + virtual void Post(W *w) override ///<投递一个工作 + { + if(!w)return; + + work_list.Post(w); + work_list.PostSem(1); + } + + virtual void Post(W **w,int count) override ///<投递一批工作 + { + if(!w||count<=0)return; + + work_list.Post(w,count); + work_list.PostSem(count); + } + + public: + + /** + * 开始执行工作函数 + */ + virtual bool OnExecuteWork(const uint wt_index) override + { + //为什么不使用TrySemReceive,使用TrySemReceive固然会立即返回结果,但会引起线程频繁刷新造成CPU的流费。 + //使用WaitSemReceive目前唯一坏处是在退出时,需要等待超时时间。 + + W *obj=work_list.WaitSemReceive(time_out); + + if(!obj) + return(false); + + this->OnWork(wt_index,obj); + + return(true); + } + };//template class MultiWorkProc:public WorkProc + + /** + * 工作线程,用于真正处理事务 + */ + template class WorkThread:public Thread + { + protected: + + using WorkList=List; + + WorkProc *work_proc; + + uint work_thread_index; + + bool force_close; + + public: + + WorkThread(WorkProc *wp) + { + work_proc=wp; + work_thread_index=0; + force_close=false; + } + +#ifndef _DEBUG + virtual ~WorkThread()=default; +#else + virtual ~WorkThread() + { + LOG_INFO(U8_TEXT("WorkThread Destruct [")+thread_addr_string+U8_TEXT("]")); + } + +#endif//_DEBUG + + bool IsExitDelete()const override{return false;} ///<返回在退出线程时,不删除本对象 + + void SetWorkThreadIndex(const uint index) + { + work_thread_index=index; + } + + void ExitWork(const bool fc) + { + force_close=fc; + Thread::WaitExit(); + } + + virtual void ProcEndThread() override + { + if(!force_close) //不是强退 + while(work_proc->OnExecuteWork(work_thread_index)); //把工作全部做完 + + #ifdef _DEBUG + { + LOG_INFO(U8_TEXT("WorkThread Finish [")+thread_addr_string+U8_TEXT("]")); + } + #endif//_DEBUG + } + + virtual bool Execute() override + { + if(!work_proc) + RETURN_FALSE; + + work_proc->OnExecuteWork(work_thread_index); + + return(true); + } + };//template class WorkThread:public Thread + + /** + * 工作组
+ * 用于管理一组的工作线程以及投递器
+ * 注:可以一组工作线程共用一个投递器,也可以每个工作线程配一个投递器。工作组管理只为方便统一清理 + */ + template class WorkGroup + { + ObjectList wp_list; ///<投递器列表 + ObjectList wt_list; ///<工作线程列表 + + bool run=false; + + public: + + virtual ~WorkGroup() + { + Close(); + } + + virtual bool Add(WP *wp) + { + if(!wp)return(false); + + wp_list.Add(wp); + return(true); + } + + virtual bool Add(WP **wp,const int count) + { + if(!wp)return(false); + + wp_list.Add(wp,count); + return(true); + } + + virtual bool Add(WT *wt) + { + if(!wt)return(false); + + int index=wt_list.Add(wt); + wt->SetWorkThreadIndex(index); + return(true); + } + + virtual bool Add(WT **wt,const int count) + { + if(!wt)return(false); + + int index=wt_list.Add(wt,count); + for(int i=0;iSetWorkThreadIndex(index); + ++index; + ++wt; + } + + return(true); + } + + virtual bool Start() + { + int count=wt_list.GetCount(); + + if(count<=0) + RETURN_FALSE; + + WT **wt=wt_list.GetData(); + + for(int i=0;iStart(); + + run=true; + return(true); + } + + virtual void Close(bool force_close=false) + { + if(!run)return; + + int count=wt_list.GetCount(); + + WT **wt=wt_list.GetData(); + + for(int i=0;iExitWork(force_close); + + run=false; + } + };//template class WorkGroup + }//namespace workflow +}//namespace hgl +#endif//HGL_WORKFLOW_INCLUDE diff --git a/inc/hgl/thread/atomic/AtomicGNU.h b/inc/hgl/thread/atomic/AtomicGNU.h new file mode 100644 index 00000000..161bac20 --- /dev/null +++ b/inc/hgl/thread/atomic/AtomicGNU.h @@ -0,0 +1,48 @@ +#ifndef HGL_THREAD_ATOMIC_GNU_INCLUDE +#define HGL_THREAD_ATOMIC_GNU_INCLUDE + +namespace hgl +{ + template class atom + { + volatile T value; + + public: + + atom(){value=0;} + atom(const volatile T new_value){operator=(new_value);} + + inline T operator ->(){return value;} + + inline T operator *= (const volatile T v) {return operator=(value *=v);} + inline T operator /= (const volatile T v) {return operator=(value /=v);} + inline T operator %= (const volatile T v) {return operator=(value %=v);} + inline T operator >>= (const volatile T v) {return operator=(value>>=v);} + inline T operator <<= (const volatile T v) {return operator=(value<<=v);} + + inline T operator ! ()const {return !value;} + inline T operator ~ ()const {return ~value;} + + inline operator T () {return value;} + inline operator const T ()const {return value;} + inline bool operator ! () {return !value;} + + inline bool operator == (const volatile T v)const {return value==v;} + inline bool operator != (const volatile T v)const {return value!=v;} + + inline T operator = (const volatile T new_value) {__sync_lock_test_and_set(&value,new_value); return value;} + + inline T operator += (const volatile T add_value) {return __sync_add_and_fetch(&value,add_value);} + inline T operator -= (const volatile T sub_value) {return __sync_sub_and_fetch(&value,sub_value);} + + inline T operator &= (const volatile T v) {return __sync_and_and_fetch(&value,v);} + inline T operator |= (const volatile T v) {return __sync_or_and_fetch (&value,v);} + inline T operator ^= (const volatile T v) {return __sync_xor_and_fetch(&value,v);} + + inline T operator ++ () {return __sync_add_and_fetch(&value,1);} //前置++ + inline T operator ++ (int) {return __sync_fetch_and_add(&value,1);} //后置++ + inline T operator -- () {return __sync_sub_and_fetch(&value,1);} + inline T operator -- (int) {return __sync_fetch_and_sub(&value,1);} + };//template class atom +}//namespace hgl +#endif//HGL_THREAD_ATOMIC_GNU_INCLUDE diff --git a/inc/hgl/thread/atomic/AtomicOSX.h b/inc/hgl/thread/atomic/AtomicOSX.h new file mode 100644 index 00000000..5fca01d3 --- /dev/null +++ b/inc/hgl/thread/atomic/AtomicOSX.h @@ -0,0 +1,50 @@ +#ifndef HGL_THREAD_ATOMIC_OSX_INCLUDE +#define HGL_THREAD_ATOMIC_OSX_INCLUDE + +#include + +namespace hgl +{ + typedef int aint; + + typedef volatile aint avint; + typedef const avint cavint; + + template class atom ///原子数据 + { + avint value; + + public: + + atom(){value=0;} + atom(cavint new_value){operator=(new_value);} + + inline aint operator *= (cavint v) {return operator=(value *=v);} + inline aint operator /= (cavint v) {return operator=(value /=v);} + inline aint operator %= (cavint v) {return operator=(value %=v);} + inline aint operator >>= (cavint v) {return operator=(value>>=v);} + inline aint operator <<= (cavint v) {return operator=(value<<=v);} + + inline aint operator ! ()const {return !value;} + inline aint operator ~ ()const {return ~value;} + + inline operator const aint ()const {return value;} + inline bool operator ! () {return !value;} + + inline bool operator == (cavint v)const {return value==v;} + inline bool operator != (cavint v)const {return value!=v;} + inline aint operator = (cavint new_value) {value=new_value;return value;} + inline aint operator ++ () {return OSAtomicIncrement32(&value);} + inline aint operator -- () {return OSAtomicDecrement32(&value);} + inline aint operator += (cavint add_value) {return;} + inline aint operator -= (cavint sub_value) {return;} + + inline aint operator &= (cavint v) {return operator=(value &=v);} + inline aint operator |= (cavint v) {return operator=(value |=v);} + inline aint operator ^= (cavint v) {return operator=(value ^=v);} + + inline aint operator ++ (int) {aint ret=value;operator++();return ret;}//后置++ + inline aint operator -- (int) {volatile T ret=value;operator--();return ret;}//后置-- + };//class atom +}//namespace hgl +#endif//HGL_THREAD_ATOMIC_OSX_INCLUDE diff --git a/inc/hgl/thread/atomic/AtomicWin.h b/inc/hgl/thread/atomic/AtomicWin.h new file mode 100644 index 00000000..94c3b67f --- /dev/null +++ b/inc/hgl/thread/atomic/AtomicWin.h @@ -0,0 +1,91 @@ +#ifndef HGL_THREAD_ATOMIC_WINDOWS_INCLUDE +#define HGL_THREAD_ATOMIC_WINDOWS_INCLUDE + +#include +namespace hgl +{ + //开发日志 2013-06-19 + //1.原本是一个模板,但将32/64中不一样的部分各自特例化,但不知为何VC2012中无法认出对应的操作符,所以改成2个模板 + //2.部分原子函数没有8/16位版本 + + //32位版 + template class atom_win32 + { + volatile T value; + + public: + + atom_win32(){value=0;} + atom_win32(const volatile T new_value){operator=(new_value);} + + T operator *= (const volatile T v) {return operator=(value *=v);} + T operator /= (const volatile T v) {return operator=(value /=v);} + T operator %= (const volatile T v) {return operator=(value %=v);} + T operator >>= (const volatile T v) {return operator=(value>>=v);} + T operator <<= (const volatile T v) {return operator=(value<<=v);} + + T operator ! ()const {return !value;} + T operator ~ ()const {return ~value;} + + operator T () {return value;} + operator const T ()const {return value;} + bool operator ! () {return !value;} + + bool operator == (const volatile T v)const {return value==v;} + bool operator != (const volatile T v)const {return value!=v;} + + T operator = (const volatile T nv) {return InterlockedExchange((unsigned long *)&value,(unsigned long)nv);} + T operator ++ () {return InterlockedIncrement((unsigned long *)&value);} + T operator -- () {return InterlockedDecrement((unsigned long *)&value);} + T operator += (const volatile T av) {return InterlockedExchangeAdd((unsigned long *)&value, av); } + T operator -= (const volatile T av) {return InterlockedExchangeAdd((unsigned long *)&value, -av); } + + volatile T operator &= (const volatile T v) {return InterlockedAnd((unsigned long *)&value,v);} + volatile T operator |= (const volatile T v) {return InterlockedOr((unsigned long *)&value, v); } + volatile T operator ^= (const volatile T v) {return InterlockedXor((unsigned long *)&value, v); } + + volatile T operator ++ (int) {volatile T ret=value;operator++();return ret;}//后置++ + volatile T operator -- (int) {volatile T ret=value;operator--();return ret;}//后置-- + };//template class atom_win32 + + //64位版 + template class atom_win64 + { + volatile T value; + + public: + + atom_win64(){value=0;} + atom_win64(const volatile T new_value){operator=(new_value);} + + T operator *= (const volatile T v) {return operator=(value *=v);} + T operator /= (const volatile T v) {return operator=(value /=v);} + T operator %= (const volatile T v) {return operator=(value %=v);} + T operator >>= (const volatile T v) {return operator=(value>>=v);} + T operator <<= (const volatile T v) {return operator=(value<<=v);} + + T operator ! ()const {return !value;} + T operator ~ ()const {return ~value;} + + operator T () {return value;} + operator const T ()const {return value;} + bool operator ! () {return !value;} + + bool operator == (const volatile T v)const {return value==v;} + bool operator != (const volatile T v)const {return value!=v;} + + T operator = (const volatile T nv) {return InterlockedExchange64((LONG64 *)&value, (LONG64)nv); } + T operator ++ () {return InterlockedIncrement64((LONG64 *)&value); } + T operator -- () {return InterlockedDecrement64((LONG64 *)&value); } + T operator += (const volatile T av) {return InterlockedExchangeAdd64((LONG64 *)&value, av); } + T operator -= (const volatile T av) {return InterlockedExchangeAdd64((LONG64 *)&value, -av); } + + volatile T operator &= (const volatile T v) {return InterlockedAnd64((LONG64 *)&value, v); } + volatile T operator |= (const volatile T v) {return InterlockedOr64((LONG64 *)&value, v); } + volatile T operator ^= (const volatile T v) {return InterlockedXor64((LONG64 *)&value, v); } + + volatile T operator ++ (int) {volatile T ret=value;operator++();return ret;}//后置++ + volatile T operator -- (int) {volatile T ret=value;operator--();return ret;}//后置-- + };//template class atom_win64 +}//namespace hgl +#endif//HGL_THREAD_ATOMIC_WINDOWS_INCLUDE diff --git a/inc/hgl/type/BaseString.h b/inc/hgl/type/BaseString.h new file mode 100644 index 00000000..de893056 --- /dev/null +++ b/inc/hgl/type/BaseString.h @@ -0,0 +1,1208 @@ +#ifndef HGL_TYPE_BASE_STRING_INCLUDE +#define HGL_TYPE_BASE_STRING_INCLUDE + +#include +#include +#include +#include + +namespace hgl +{ + /** + * 字符串基类 + */ + template class BaseString ///字符串基类 + { + protected: + + using SelfClass =BaseString; + using InstClass =StringInstance; + using SharedClass =SharedPtr; + + SharedClass data; ///<字符串数据实例 + + public: + + BaseString()=default; + + BaseString(const T *str) + { + Set(str); + } + + explicit BaseString(const T); + + static BaseString charOf(const T &ch) + { + T *str=new T[2]; + + str[0]=ch; + str[1]=0; + + return BaseString(str,1,true); + } + + /** + * 根据一个C指针风格字符串设置当前字符串内容 + * @param str 字符串内容,在len<0的情况下,需以0为结尾 + * @param len 字符串长度,如果str以0为结尾,可以为负值,将启用自动计算长度 + * @param one_instance 是否仅有这一份实例,如果是将不会产生复岓是而是直接使用此值,最终delete[]释放 + */ + BaseString(const T *str,int len,bool one_instance=false) + { + Set(str,len,one_instance); + } + + BaseString(const InstClass &si) + { + if((&si)==nullptr)return; + + data=si; + } + + BaseString(const SelfClass &bs) + { + if((&bs)==nullptr)return; + + Set(bs); + } + + #define BASE_STRING_NUMBER_CONSTRUCT(type,func) \ + BaseString(const type num) \ + { \ + Set(func(new T[8*sizeof(type)],8*sizeof(type),num),-1,true); \ + } + + BASE_STRING_NUMBER_CONSTRUCT(int, itos); + BASE_STRING_NUMBER_CONSTRUCT(uint, utos); + BASE_STRING_NUMBER_CONSTRUCT(int64, itos); + BASE_STRING_NUMBER_CONSTRUCT(uint64,utos); + + BASE_STRING_NUMBER_CONSTRUCT(float, ftos); + BASE_STRING_NUMBER_CONSTRUCT(double,ftos); + + #undef BASE_STRING_NUMBER_CONSTRUCT + + BaseString(const int *value,int N) + { + const int size=N*sizeof(int)*8; + int len; + + T tmp_str[size]; + + itos(tmp_str,size,*value); + ++value; + + for(int i=1;iGetBeginChar():0); + } + + const T GetEndChar()const ///<取得当前字符串最后一个字符 + { + // if(!this)return(0); + return(data.valid()?data->GetEndChar():0); + } + + const int Length()const ///<当前字符串长度 + { + // if(!this)return(0); + return(data.valid()?data->GetLength():0); + } + + const bool IsEmpty()const ///<当前字符串是否空的 + { + // if(!this)return(true); + return(data.valid()?data->GetLength()<=0:true); + } + + /** + * 取得一个C风格的字符串指针,失败返回NULL + */ + T *c_str()const + { + // if(!this)return(nullptr); + return(data.valid()?data->c_str():nullptr); + } + + /** + * 找到指定字符,并返回一个C风格的字符串指针 + */ + T *strchr(T ch)const + { + // if(!this)return(nullptr); + if(!data.valid())return(nullptr); + + const int result=FindChar(ch); + + if(result<0)return(nullptr); + + return data->c_str()+result; + } + + /** + * 从末尾查找字符,并返回一个C风格的字符串指针 + */ + T *strrchr(T ch)const + { + // if(!this)return(nullptr); + if(!data.valid())return(nullptr); + + const int result=FindRightChar(ch); + + if(result<0)return(nullptr); + + return data->c_str()+result; + } + + /** + * 根据一个C指针风格字符串设置当前字符串内容 + * @param str 字符串内容,在len<0的情况下,需以0为结尾 + * @param len 字符串长度,如果str以0为结尾,可以为负值,将启用自动计算长度 + * @param one_instance 是否仅有这一份实例,如果是将不会产生复岓是而是直接使用此值,最终delete[]释放 + */ + void Set(const T *str,int len=-1,bool one_instance=false) + { + if(!str||!*str||!len) //len=-1为自检测,为0不处理 + { + Clear(); + return; + } + + data=new InstClass(str,len,one_instance); + } + + void Strcpy(const T *str,int len=-1,bool one=false) + { + Set(str,len,one); + } + + /** + * 设置当前字符串的内容 + * @param bs 内容来源字符串 + */ + void Set(const SelfClass &bs) + { + if((&bs)==nullptr) + { + Clear(); + return; + } + + data=bs.data; + } + + /** + * 设置当前字符中的内容 + */ + void Set(const InstClass &si) + { + if((&si)==nullptr) + { + Clear(); + return; + } + + data=si; + } + + /** + * 设置当前字符串中的内容 + */ + void Set(const SharedClass &spsi) + { + if((&spsi)==nullptr) + { + Clear(); + return; + } + + data=spsi; + } + + /** + * 设置字符串的内容 + */ + bool Set(const SelfClass &bs,int start,int count) + { + if(count<=0)return(false); + + if((&bs)==nullptr) + return(false); + + data=bs.data->CreateCopy(start,count); + return(true); + } + + /** + * 复制一个字符串 + */ + bool Copy(const SelfClass &bs) + { + if(bs.IsEmpty()) + return(false); + + data=bs.data->CreateCopy(); + return(true); + } + + /** + * 断开与其它BaseString共用的情况,创建一个独有的实例 + */ + bool Unlink() + { + if(!data.valid()) + return(false); + + if(data.only()) //自己独有 + return(true); + + data=data->CreateCopy(); + return(true); + } + + /** + * 放弃当前数据,将当前字符串清空 + */ + T *Discard() + { + if(!data.valid()) + return(nullptr); + + if(data.only()) + return data->Discard(); + + return(nullptr); + } + + /** + * 取指定索引处的字符 + * @param n 索引偏移 + * @param ch 字符存放变量 + * @return 是否获取成功 + */ + bool GetChar(int n,T &ch)const + { + if(n<0)return(false); + + if(!data.valid()) + return(false); + + return data->GetChar(n,ch); + } + + /** + * 设定指定索引处的字符 + * @param n 索引偏移 + * @param ch 字符 + * @return 是否设置成功 + */ + bool SetChar(int n,const T ch) + { + if(n<0)return(false); + + if(!Unlink()) + return(false); + + return data->SetChar(n,ch); + } + + /** + * 在指定偏移处插入指定长度的字符串 + * @param pos 要插入的位置 + * @param str 要插入的字符串 + * @param len 要插入的字符个数,如果为-1则自动检测字符串长度 + */ + bool Insert(int pos,const T *str,int len=-1) + { + if(len==0)return(false); + + if(data.valid()&&Unlink()) + { + if(len<0) + len=strlen(str); + + return data->Insert(pos,str,len); + } + else + { + Set(str,len); + return(true); + } + } + + /** + * 在指定偏移处插入字符串 + * @param pos 要插入的位置 + * @param str 要插入的字符串 + */ + bool Insert(int pos,const SelfClass &str) + { + if((&str)==nullptr) + return(false); + + return Insert(pos,str.c_str(),str.Length()); + } + + bool Strcat(const T *str,int len) + { + if(!str||!*str||len==0)return(false); + + return Insert(Length(),str,len); + } + + /** + * 追加一个字符串到当前字符串后面 + */ + bool Strcat(const SelfClass &bs) + { + if((&bs)==nullptr) + return(false); + + return Insert(Length(),bs); + } + + /** + * 从指定位置删除指定个字符 + * @param pos 要删除的起始位置 + * @param num 要删除的字符个数 + * @return 是否成功 + */ + bool Delete(int pos,int num) + { + if(pos<0||num<=0)return(false); + + if(data.valid()&&Unlink()) + return data->Delete(pos,num); + + return(false); + } + + /** + * 清除类中的字符串数据 + */ + void Clear() + { + data.unref(); + } + + /** + * 和一个字符串进行比较 + * @param bs 比较字符串 + * @return <0 自身小 + * @return 0 等同 + * @return >0 自身大 + */ + int Comp(const SelfClass &bs)const + { + if(!data.valid()) + return(bs.Length()); + + if(bs.Length()<=0) + return Length(); + + return data->Comp(bs.data.get()); + } + + /** + * 和一个字符串进行比较 + * @param str 比较字符串 + * @return <0 自身小 + * @return 0 等同 + * @return >0 自身大 + */ + int Comp(const T *str)const + { + if(!data.valid()) + { + if(!str) + return 0; + else + return *str; + } + + return data->Comp(str); + } + + /** + * 和一个字符串进行比较 + * @param pos 起始位置 + * @param bs 比较字符串 + * @return <0 自身小 + * @return 0 等同 + * @return >0 自身大 + */ + int Comp(const int pos,const SelfClass &bs)const + { + if(!data.valid()) + return(bs.Length()); + + if(bs.Length()<=0) + return Length(); + + return data->Comp(pos,bs.data.get()); + } + + /** + * 和一个字符串进行比较 + * @param str 比较字符串 + * @return <0 自身小 + * @return 0 等同 + * @return >0 自身大 + */ + int Comp(const int pos,const T *str)const + { + if(!data.valid()) + { + if(!str) + return 0; + else + return *str; + } + + return data->Comp(pos,str); + } + + /** + * 和那一个字符串进行比较,英文不区分大小写 + * @param bs 比较字符串 + * @return <0 自身小 + * @return 0 等同 + * @return >0 自身大 + */ + int CaseComp(const SelfClass &bs)const + { + if(!data.valid()) + return(bs.Length()); + + if(bs.Length()<=0) + return 1; + + return data->CaseComp(bs.data->c_str()); + } + + /** + * 和那一个字符串进行比较,英文不区分大小写 + * @param str 比较字符串 + * @return <0 自身小 + * @return 0 等同 + * @return >0 自身大 + */ + int CaseComp(const T *str)const + { + if(!data.valid()) + { + if(!str) + return 0; + + return *str; + } + + return data->CaseComp(str); + } + + /** + * 和那一个字符串比较指字长度的字符 + * @param bs 比较字符串 + * @param num 比较字数 + * @return <0 自身小 + * @return 0 等同 + * @return >0 自身大 + */ + int Comp(const SelfClass &bs,const int num)const + { + if(!data.valid()) + { + if(num<=0)return 0; + + return bs.Length(); + } + + if(bs.Length()<=0) + return 1; + + return data->Comp(bs.data->c_str(),num); + } + + /** + * 和那一个字符串比较指字长度的字符 + * @param str 比较字符串 + * @param num 比较字数 + * @return <0 自身小 + * @return 0 等同 + * @return >0 自身大 + */ + int Comp(const T *str,const int num)const + { + if(!data.valid()) + { + if(!str||num<=0) + return 0; + + return *str; + } + + return data->Comp(str,num); + } + + /** + * 和那一个字符串比较指字长度的字符,英文不区分大小写 + * @param bs 比较字符串 + * @param num 比较字数 + * @return <0 自身小 + * @return 0 等同 + * @return >0 自身大 + */ + int CaseComp(const SelfClass &bs,const int num)const + { + if(!data.valid()) + { + if(num<=0)return 0; + + return bs.Length(); + } + + if(bs.Length<=0) + return 1; + + return data->CaseComp(bs.data->c_str(),num); + } + + /** + * 和那一个字符串比较指字长度的字符,英文不区分大小写 + * @param str 比较字符串 + * @param num 比较字数 + * @return <0 自身小 + * @return 0 等同 + * @return >0 自身大 + */ + int CaseComp(const T *str,const int num)const + { + if(!data.valid()) + { + if(!str||num<=0) + return 0; + + return *str; + } + + return data->CaseComp(str,num); + } + public: + + bool ToBool(bool &result)const ///<将本类中的字符串转换成布尔数值并返回 + { + return data.valid()?stob(data->c_str(),result):false; + } + + template + bool ToInt(I &result)const ///<将本类中的字符串转换成整型数值并返回 + { + return data.valid()?etof(data->c_str(),result):false; + } + + template + bool ToUint(U &result)const ///<将本类中的字符串转换成整型数值并返回 + { + return data.valid()?etof(data->c_str(),result):false; + } + + template + bool ToFloat(F &result)const ///<将本类中的字符串转换成浮点数值并返回 + { + return data.valid()?etof(data->c_str(),result):false; + } + + /** + * 将当前字符串全部转为小写 + * @return 转换后的当前字符串 + */ + SelfClass &LowerCase() ///<将本类中的字母全部转为小写 + { + if(data.valid()&&Unlink()) + tolower(data->c_str()); + + return(*this); + } + + /** + * 将当前字符串全部转为小写 + * @return 转换后的字符串 + */ + SelfClass ToLowerCase()const ///<将本类中的字母全部转为小写 + { + if(!data.valid()) + return SelfClass(); + + return SelfClass(data->c_str()).LowerCase(); + } + + /** + * 将当前字符串全部转为大写 + * @return 转换后的当前字符串 + */ + SelfClass &UpperCase() ///<将本类中的字母全部转为大写 + { + if(data.valid()&&Unlink()) + toupper(data->c_str()); + + return(*this); + } + + /** + * 将当前字符串全部转换为大写 + * @return 转换后的字符串 + */ + SelfClass ToUpperCase()const ///<将本类中的字母全部转为大写 + { + if(!data.valid()) + return SelfClass(); + + return SelfClass(data->c_str()).UpperCase(); + } + + /** + * 填充当前字符串的部分内容为指定字符 + * @param ch 要填充的字符 + * @param start 填充的起始位置 + * @param len 填充的个数 + * @return 是否成功 + */ + bool FillChar(const T ch,int start=0,int len=-1) + { + if(!data.valid()) + return(false); + + if(start<0||data->GetLength()c_str()+start,ch,len); + return(true); + } + + return(false); + } + + protected: + + typedef T *(*ConvFunc)(const T *,int &); + + bool StrConv(ConvFunc conv) + { + if(!data.valid()||data->GetLength()<=0) + return(false); + + int new_len=data->GetLength(); + + T *new_str=conv(data->c_str(),new_len); + + if(new_len>0) + { + Set(new_str,new_len,true); + return(true); + } + else + { + Clear(); + return(false); + } + } + + public: + + bool TrimLeft(){return StrConv(trimleft);} ///<删除字符串前端的空格、换行等不可视字符串 + bool TrimRight(){return StrConv(trimright);} ///<删除字符串后端的空格、换行等不可视字符串 + bool Trim(){return StrConv(trim);} ///<删除字符串两端的空格、换行等不可视字符串 + + bool TrimLeft(int n){return Delete(0,n);} ///<删除字符串前端的指定个字符 + bool TrimRight(int n){return Unlink()?data->TrimRight(n):false;} ///<删除字符串后端的指定个字符 + + bool ClipLeft(int n){return Unlink()?data->ClipLeft(n):false;} ///<截取字符串前端的指定个字符,等同TrimRight(lengths-n)) + bool ClipRight(int n){return Delete(0,Length()-n);} ///<截取字符串后端的指定个字符,等同TrimLeft(length-n) + bool Clip(int pos,int num) ///<从指定位置删除指定个字符 + { + if(!Unlink()) + return(false); + + return data->Clip(pos,num); + } + + /** + * 从字符串中取指定子串为新的内容 + * @param start 起始字符索引 + * @param n 字符数量,-1表示全部 + * @return 截取后的字符串 + */ + SelfClass SubString(int start,int n=-1) const ///<取字符串指定段的字符 + { + if(n==0) + return SelfClass(); + + int len=Length(); + + if(start>=len) + return SelfClass(); + + return SelfClass(data->c_str()+start,n); + } + + /** + * 从字符串中取指定子串为新的内容 + * @param sc 新的字符串 + * @param start 起始字符索引 + * @param n 字符数量 + * @return 成否成功 + */ + bool SubString(SelfClass &sc,int start,int n) const ///<取字符串指定段的字符 + { + if(Length()c_str()+start,n); + return(true); + } + + bool Resize(int n) + { + if(!data.valid()) + return(false); + + if(n==0) + { + Clear(); + return(true); + } + + return data->Resize(n); + } + + int StatChar(const T ch)const{return data.valid()?StatChar(data->c_str(),ch):-1;} ///<统计字符串中某个字符的个数 + int StatLine()const{return data.valid()?StatLine(data->c_str()):-1;} ///<统计字符串行数 + + int FindChar(int pos,const T ch)const ///<返回当前字符串中指定字符开始的索引(从左至右) + { + if(!data.valid()) + return(-1); + + const T *result=hgl::strchr(data->c_str()+pos,ch); + + if(result) + return result-(data->c_str()+pos); + + return(-1); + } + + /** + * 在当前字符串中查找字符 + * @param pos 起始查找位置 + * @param ch 要查找的字符,可以是多个,找到任意一个就算 + */ + int FindChar(int pos,const BaseString &ch)const ///<返回当前字符串中指定字符中的任意一个开始的索引(从左至右) + { + if(!data.valid()) + return(-1); + + const T *result=hgl::strchr(data->c_str()+pos,ch.c_str(),ch.Length()); + + if(result) + return result-(data->c_str()+pos); + + return(-1); + } + + int FindChar(const T ch)const{return FindChar(0,ch);} ///<返回当前字符串中指定字符开始的索引(从左至右) + + int FindRightChar(const T ch)const ///<返回当前字符串中指定字符开始的索引(从右至左) + { + if(!data.valid()) + return(-1); + + const T *result=hgl::strrchr(data->c_str(),data->GetLength(),ch); + + if(result) + return result-(data->c_str()); + + return(-1); + } + + int FindRightChar(const BaseString &ch)const ///<返回当前字符串中指定字符开始的索引(从右至左) + { + if(!data.valid()) + return(-1); + + const T *result=hgl::strrchr(data->c_str(),data->GetLength(),ch.c_str(),ch.Length()); + + if(result) + return result-(data->c_str()); + + return(-1); + } + + /** + * 返回当前字符串中指定字符开始的索引(从右至左) + * @param off 从右至左跳过不查的字符个数 + * @param ch 要查找的字符 + */ + int FindRightChar(const int off,const T ch)const + { + if(!data.valid()) + return(-1); + + const T *result=hgl::strrchr(data->c_str(),data->GetLength(),off,ch); + + if(result) + return result-(data->c_str()); + + return(-1); + } + + /** + * 返回当前字符串中指定字符开始的索引(从右至左) + * @param off 从右至左跳过不查的字符个数 + * @param ch 要查找的字符 + */ + int FindRightChar(const int off,const BaseString &ch)const + { + if(!data.valid()) + return(-1); + + const T *result=hgl::strrchr(data->c_str(),data->GetLength(),off,ch.c_str(),ch.Length()); + + if(result) + return result-(data->c_str()); + + return(-1); + } + + /** + * 在整个字符串内,查找指定字符串 + * @param str 要查找的字符串 + * @param start 从第几个字符开始查找,默认0 + * @return 指定子串所在的偏移 + * @return -1 出错 + */ + int FindString(const SelfClass &str,int start=0)const ///<返回当前字符串中指定子串开始的索引 + { + if(!data.valid()) + return(-1); + + if(str.Length()<=0) + return(-1); + + if(start<0||start>data->GetLength()-str.Length()) + return(-1); + + const T *result=strstr(data->c_str()+start,str.c_str()); + + if(result) + return result-(data->c_str()); + + return(-1); + } + + /** + * 在整个字符串内,清除指定字符串 + * @param sub 要清除的字符串 + * @return 总计清除的个数 + * @return -1 出错 + */ + int ClearString(const SelfClass &sub) ///<清除当前字符串中指定子串 + { + if(!Unlink()) + return(-1); + + if(sub.Length()<=0) + return(false); + + T *sp=data->c_str(); + T *tp=sub.c_str(); + T *p; + int len=data->GetLength(); + int sub_len=sub.Length; + int count=0; + + while((p=strstr(sp,tp))) + { + len-=(p-sp)+sub_len; + sp=p; + memcpy(p,p+sub_len,len*sizeof(T)); + count++; + } + + return(count); + } + + /** + * 在指定位置写入字符串 + * @param pos 开始写入的位置 + * @param str 要写入的字符串 + * @return 是否成功 + */ + bool WriteString(int pos,const SelfClass &str) + { + if(!Unlink()) + return(false); + + if(str.Length()<=0) + return(false); + + return data->Write(pos,str); + } + + /** + * 替换当前字符串中指定字符到另一个字符 + * @param sch 要替换的字符 + * @param tch 替换后的字符 + * @return 总计替换个数 + * @return <0 出错 + */ + int Replace(const T tch,const T sch) ///<替换字符 + { + if(!Unlink()) + return(-1); + + return replace(data->c_str(),tch,sch); + } + + public: //操作符重载 + + operator const InstClass &() + { + return data; + } + + const T &operator [](int index) + { + if(data.valid()) + if(index>=0&&indexGetLength()) + return *(data->c_str()+index); + + const static T zero_char=0; + + return zero_char; //this is error + } + + operator T *() {return c_str();} + operator const T *()const {return c_str();} + + SelfClass &operator = (const T *str ){Set(str);return(*this);} + SelfClass &operator = (const SelfClass &str){Set(str);return(*this);} + SelfClass &operator += (const SelfClass &str){Strcat(str);return(*this);} + SelfClass &operator << (const SelfClass &str){return(operator+=(str));} + + static SelfClass ComboString(const T *str1,int len1,const T *str2,int len2) + { + if(!str1||len1<=0) + { + if(!str2||len2<=0) + return(SelfClass()); + + return SelfClass(str2,len2); + } + else + { + if(!str2||len2<=0) + return(SelfClass(str1,len1)); + } + + const int new_len=len1+len2; + + T *ms=new T[new_len+1]; + + memcpy(ms, str1,len1*sizeof(T)); + memcpy(ms+len1, str2,len2*sizeof(T)); + + ms[new_len]=0; + + return(SelfClass(ms,new_len,true)); + } + + SelfClass operator + (const SelfClass &str) const + { + if(str.Length()<=0) //如果对方为空 + return(*this); + + if(!data.valid()) //如果我方为空 + return(str); + + return ComboString(data->c_str(),data->GetLength(),str.c_str(),str.Length()); + } + + SelfClass operator + (const T ch) const + { + if(!data.valid()) + return(SelfClass(ch)); + + return ComboString(data->c_str(),data->GetLength(),&ch,1); + } + + SelfClass operator + (const T *str) const + { + if(!data.valid()) + return(SelfClass(str)); + + return ComboString(data->c_str(),data->GetLength(),str,strlen(str)); + } + + #define BASE_STRING_NUMBER_OPERATOR_ADD(type,func) SelfClass operator + (const type &num) const \ + { \ + SharedPtr vstr=func(new T[8*sizeof(type)],8*sizeof(type),num); \ + \ + return operator+(vstr->data); \ + } + + BASE_STRING_NUMBER_OPERATOR_ADD(int, itos); + BASE_STRING_NUMBER_OPERATOR_ADD(uint, utos); + BASE_STRING_NUMBER_OPERATOR_ADD(int64, itos); + BASE_STRING_NUMBER_OPERATOR_ADD(uint64, utos); + + BASE_STRING_NUMBER_OPERATOR_ADD(float, ftos); + BASE_STRING_NUMBER_OPERATOR_ADD(double, dtos); + + #undef BASE_STRING_NUMBER_OPERATOR_ADD + + CompOperator(const T *,Comp); + CompOperator(const SelfClass &,Comp); + };//template class BaseString + + //这种重载用于value+str的情况 + //而类中的的重载用于str+value的情况 + + template BaseString operator + (const V &value,const BaseString &str) + { + if(str.Length()<=0) + return BaseString(value); + + return BaseString(value)+str; + } + + using UTF8String =BaseString; + using AnsiString =BaseString; + using UTF16String =BaseString; + using OSString =BaseString; + using UTF32String =BaseString; + using WideString =BaseString; + + template bool ToNumber(const BaseString &str,int &value){return str.ToInt(value);} + template bool ToNumber(const BaseString &str,uint &value){return str.ToUint(value);} + template bool ToNumber(const BaseString &str,float &value){return str.ToFloat(value);} + template bool ToNumber(const BaseString &str,double &value){return str.ToFloat(value);} + + /** + * 以累加的方式为一个字符串计算出一个hash码 + */ + template uint StringFastHash(const BaseString &str) + { + const T *p=str.c_str(); + int c=str.Length(); + + uint result=0; + + while(c-->0) + result+=*p++; + + return(result%HASH_MAX); + } + + /** + * 将一串原始数据,转换成一个16进制数值组成的字符串 + * @param value 要转换的原始数据 + * @return 转换好的字符串 + * @see HexToString + */ + template BaseString ToHexString(const I &value) + { + T str[(sizeof(I)<<1)+1]; + + ToUpperHexStr(str,value); + + return BaseString(str); + } + + /** + * 将一个数值转换为一个用16进制表示的字符串
+ * 同ToHexString区别在于,HexToString按数值大小处理 + * @param value 要转换的数值 + * @see ToHexString + */ + template BaseString HexToString(const I &value) + { + T str[(sizeof(I)<<1)+1]; + + htos(str,sizeof(I)<<1,value); + + return BaseString(str); + } + + /** + * 将一个指针转换成一个16进制字符串 + */ + template BaseString PointerToHexString(const void *ptr) + { + return HexToString(reinterpret_cast(ptr)); + } + + inline BaseString PointerToHexOSString(const void *value) + { + return PointerToHexString(value); + } + + inline BaseString PointerToHexUTF8String(const void *value) + { + return PointerToHexString(value); + } + + inline BaseString PointerToHexUTF16String(const void *value) + { + return PointerToHexString(value); + } + + template + inline void strcpy(T *dst,int max_count,const BaseString &src) + { + hgl::strcpy(dst,max_count,src.c_str(),src.Length()); + } + + template + inline void strcat(T *dst,int max_count,const BaseString &src) + { + hgl::strcat(dst,max_count,src.c_str(),src.Length()); + } +}//namespace hgl +#endif//HGL_TYPE_BASE_STRING_INCLUDE diff --git a/inc/hgl/type/DataType.h b/inc/hgl/type/DataType.h new file mode 100644 index 00000000..1ab7dc17 --- /dev/null +++ b/inc/hgl/type/DataType.h @@ -0,0 +1,11 @@ +#ifndef HGL_DATATYPE_INCLUDE +#define HGL_DATATYPE_INCLUDE + +#include // 平台定义 +#include // 常用宏定义 +#include // 智能指针 +#include // 常用数值宏及内联函数 +#include // 编码序定义 +#include // 比较操作符实现定义 + +#endif//HGL_DATATYPE_INCLUDE diff --git a/inc/hgl/type/Smart.h b/inc/hgl/type/Smart.h new file mode 100644 index 00000000..a7605cc8 --- /dev/null +++ b/inc/hgl/type/Smart.h @@ -0,0 +1,460 @@ +#ifndef HGL_SMART_INCLUDE +#define HGL_SMART_INCLUDE + +#include +#include +#include +namespace hgl +{ + struct RefCount + { + atom_int count; + atom_int weak; + + public: + + RefCount() + { + count=1; + weak=0; + } + + virtual ~RefCount()=default; + + virtual void Delete()=0; + + int inc_ref() + { + return ++count; + } + + virtual int unref() + { + count--; + + if(count<=0) + { + Delete(); + + if(weak<=0) + delete this; + + return 0; + } + + return count; + } + + int inc_ref_weak() + { + return ++weak; + } + + int unref_weak() + { + weak--; + + if(weak<=0) + { + if(count<=0) + { + delete this; + return 0; + } + } + + return weak; + } + };//struct RefCount + + template struct SmartData:public RefCount + { + T *data; + + public: + + SmartData(T *ptr) + { + data=ptr; + } + + ~SmartData() + { + Delete(); + } + + void Delete() + { + SAFE_CLEAR(data); + } + };//struct template struct SmartData + + template struct SmartArrayData:public RefCount + { + T *data; + + public: + + SmartArrayData(T *ptr) + { + data=ptr; + } + + ~SmartArrayData() + { + Delete(); + } + + void Delete() + { + SAFE_CLEAR_ARRAY(data); + } + + const T &operator *() const {return data;} + const bool operator!() const{return !data;} + };//struct template struct SmartArrayData + + template class _Smart + { + protected: + + typedef _Smart SelfClass; + + SD *sd; + + public: + + _Smart() + { + sd=0; + } + + _Smart(T *ptr) + { + if(ptr) + sd=new SD(ptr); + else + sd=0; + } + + _Smart(const SelfClass &st) + { + sd=0; + + set(st); + } + + virtual ~_Smart()=default; + + T *set(T *ptr) + { + if(sd) + sd->unref(); + + if(!ptr) + { + sd=0; + return(0); + } + + sd=new SD(ptr); + + return ptr; + } + + void inc_ref(const SelfClass &sc) + { + if(sd==sc.sd)return; + + unref(); + + sd=sc.sd; + + if(sd) + sd->inc_ref(); + } + + void unref() + { + if(sd) + { + sd->unref(); + sd=0; + } + } + + void inc_ref_weak(const SelfClass &sc) + { + if(sd==sc.sd)return; + + unref(); + + sd=sc.sd; + + if(sd) + sd->inc_ref_weak(); + } + + void unref_weak() + { + if(sd) + { + sd->unref_weak(); + sd=0; + } + } + + T *get()const{return sd?sd->data:0;} + virtual bool valid()const{return sd;} + int use_count()const{return sd?sd->count:-1;} + bool only()const{return sd?sd->count==1:true;} + + public: + + const T &operator *() const {return *(sd->data);} + const bool operator!() const{return sd?!(sd->data):true;} + + operator T *()const{return(sd?sd->data:0);} + T *operator ->()const{return(sd?sd->data:0);} + + bool operator == (const SelfClass & rp)const{return(get()==rp.get()); } + bool operator == (const T * rp)const{return(get()==rp); } + + bool operator != (const SelfClass & rp)const{return !(operator==(rp)); } + bool operator != (const T * rp)const{return !(operator==(rp)); } + };//template class _Smart + + template class WeakPtr; + + /** + * 共享指针数据类
+ * 用于自动释放超出作用域的指针 + */ + template class SharedPtr:public _Smart,T> ///共享指针数据类 + { + friend class WeakPtr; + + public: + + typedef _Smart,T> SuperClass; + typedef SharedPtr SelfClass; + + public: + + SharedPtr():SuperClass(){} + SharedPtr(T *ptr):SuperClass(ptr){} + SharedPtr(const SelfClass &sp):SuperClass() + { + operator=(sp); + } + + SharedPtr(const WeakPtr &wp):SuperClass() + { + operator=(wp); + } + + ~SharedPtr() + { + SuperClass::unref(); + } + + operator T *() + { + return SuperClass::get(); + } + + operator const T *()const + { + return SuperClass::get(); + } + + T *operator =(T *ptr) + { + return SuperClass::set(ptr); + } + + SelfClass &operator =(const SelfClass &sp) + { + SuperClass::inc_ref(sp); + + return(*this); + } + + SelfClass &operator =(const WeakPtr &wp) + { + SuperClass::inc_ref(wp); + + return(*this); + } + + bool valid()const override{return this->sd?(this->sd->data?true:false):false;} + };//template class SharedPtr + + template class WeakArray; + + /** + * 共享阵列数据类,它在SharedPtr的基础上增加了[]操作符访问,以及在删除时使用delete[] + */ + template class SharedArray:public _Smart,T> ///共享阵列数据类 + { + friend class WeakArray; + + public: + + typedef _Smart,T> SuperClass; + typedef SharedArray SelfClass; + + public: + + SharedArray():SuperClass(){} + SharedArray(T *ptr):SuperClass(ptr){} + SharedArray(const SelfClass &sa):SuperClass() + { + operator=(sa); + } + + SharedArray(const WeakArray &wa):SuperClass() + { + operator=(wa); + } + + ~SharedArray() + { + SuperClass::unref(); + } + + operator T *() + { + return SuperClass::get(); + } + + operator const T *()const + { + return SuperClass::get(); + } + + T &operator [](int n) + { + return SuperClass::sd->data[n]; + } + + SelfClass &operator =(const SelfClass &sap) + { + SuperClass::inc_ref(sap); + + return(*this); + } + + SelfClass &operator =(const WeakPtr &wp) + { + SuperClass::inc_ref(wp); + + return(*this); + } + };//template class SharedArray + + template class WeakPtr:public _Smart,T> + { + friend class SharedPtr; + + public: + + typedef _Smart,T> SuperClass; + typedef WeakPtr SelfClass; + + public: + + WeakPtr():SuperClass(){} + WeakPtr(const SharedPtr &sp):SuperClass() + { + operator=(sp); + } + + WeakPtr(const SelfClass &wp):SuperClass() + { + operator=(wp); + } + + ~WeakPtr() + { + SuperClass::unref_weak(); + } + + operator T *() + { + return SuperClass::get(); + } + + operator const T *()const + { + return SuperClass::get(); + } + + virtual SuperClass &operator =(const SharedPtr &sp) + { + SuperClass::inc_ref_weak(sp); + + return(*this); + } + + virtual SelfClass &operator =(const SelfClass &wp) + { + SuperClass::inc_ref_weak(wp); + + return(*this); + } + };//template class WeakPtr + + template class WeakArray:public _Smart,T> + { + friend class SharedArray; + + public: + + typedef _Smart,T> SuperClass; + typedef WeakArray SelfClass; + + public: + + WeakArray():SuperClass(){} + WeakArray(const SharedArray &sap):SuperClass() + { + operator=(sap); + } + + WeakArray(const WeakArray &wap):SuperClass() + { + operator=(wap); + } + + ~WeakArray() + { + SuperClass::unref_weak(); + } + + operator T *() + { + return SuperClass::get(); + } + + operator const T *()const + { + return SuperClass::get(); + } + + virtual SuperClass &operator =(const SharedArray &sap) + { + SuperClass::inc_ref_weak(sap); + + return(*this); + } + + virtual SelfClass &operator =(const SelfClass &wap) + { + SuperClass::inc_ref_weak(wap); + + return(*this); + } + };//template class WeakArray +}//namespace hgl +#endif//HGL_SMART_INCLUDE diff --git a/inc/hgl/type/StdString.h b/inc/hgl/type/StdString.h new file mode 100644 index 00000000..a6f1128c --- /dev/null +++ b/inc/hgl/type/StdString.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include + +#if HGL_OS == HGL_OS_Windows +inline hgl::OSString ToOSString(const std::string &str) +{ + return hgl::to_u16(str.c_str(),(int)(str.length())); +} + +inline std::string ToStdString(const hgl::OSString &str) +{ + UTF8String u8_str=hgl::to_u8(str); + + return std::string(u8_str.c_str()); +} +#else +inline hgl::OSString ToOSString(const std::string &str) +{ + return hgl::OSString(str.c_str(),str.size()); +} + +inline std::string ToStdString(const hgl::OSString &str) +{ + return std::string(str.c_str()); +} +#endif// + +inline hgl::UTF8String ToUTF8String(const std::string &str) +{ + return hgl::UTF8String(str.c_str(),str.size()); +} + diff --git a/inc/hgl/type/StringInstance.h b/inc/hgl/type/StringInstance.h new file mode 100644 index 00000000..74dbfcdc --- /dev/null +++ b/inc/hgl/type/StringInstance.h @@ -0,0 +1,501 @@ +#ifndef HGL_TYPE_STRING_INSTANCE_INCLUDE +#define HGL_TYPE_STRING_INSTANCE_INCLUDE + +#include +#include +#include +namespace hgl +{ + /** + * 字符串实例类 + */ + template class StringInstance ///字符串实例类 + { + protected: + + typedef StringInstance SelfClass; + + int length; ///<字符串长度 + int malloc_length; ///<空间实际分配长度 + + T *buffer; + + protected: + + virtual void InitPrivate() + { + malloc_length=0; + length=0; + buffer=0; + } + + public: + + StringInstance() + { + InitPrivate(); + } + + StringInstance(const T *str,int len=-1,bool one_instance=false) + { + if(!str) + { + InitPrivate(); + return; + } + + if(len<0) + length=hgl::strlen(str); + else + { + length=hgl::strlen(str,len); + + while(length&&!str[length-1]) //清除后面的0 + length--; + } + + if(length<=0) + { + InitPrivate(); + + if(one_instance) + delete[] str; + + return; + } + + if(one_instance&&str[length]==0) //如果最后不是0,则需要重新分配内存创建带0结尾的字串 + { + malloc_length=len; + buffer=(T *)str; + + return; + } + + malloc_length=power_to_2(length+1); + + buffer=new T[malloc_length]; + memcpy(buffer,str,length*sizeof(T)); + buffer[length]=0; + + if(one_instance) + delete[] str; + } + + StringInstance(const SelfClass &bs) + { + if(bs.Length<=0) + { + InitPrivate(); + return; + } + + length=bs.length; + + if(length<=0) + return; + + malloc_length=bs.malloc_length; + + buffer=new T[malloc_length]; + memcpy(buffer,bs.buffer,length*sizeof(T)); + } + + virtual ~StringInstance() + { + delete[] buffer; //delete[] NULL; don't is error + } + + const bool isEmpty()const ///<是否为空 + { + return !buffer; + } + + SelfClass *CreateCopy() ///<创建一份自身的拷贝 + { + if(!buffer)return(0); + + return(new SelfClass(buffer,length)); + } + + SelfClass *CreateCopy(int start,int count=-1) + { + if(!buffer)return(nullptr); + if(start<0||count==0)return(nullptr); + if(count>0&&start+count>=length)return(nullptr); + + return(new SelfClass(buffer+start,count)); + } + + T *Discard() + { + T *result=buffer; + + buffer=nullptr; + + return result; + } + + T * c_str() ///<取得字符串C指针 + { + return buffer; + } + + const int GetLength()const ///<取得字符串长度 + { + return length; + } + + bool GetChar(int n,T &ch)const + { + if(n>=length) + return(false); + + ch=buffer[n]; + + return(true); + } + + bool SetChar(int n,const T &ch) + { + if(n>=length) + return(false); + + buffer[n]=ch; + + return(true); + } + + const T GetBeginChar()const + { + return buffer?*buffer:0; + } + + const T GetEndChar()const + { + return buffer?*(buffer+length-1):0; + } + + /** + * 和一个字符串进行比较 + * @param sc 比较字符串 + * @return <0 我方小 + * @return 0 等同 + * @return >0 我方大 + */ + const int Comp(const SelfClass *sc)const + { + if(!sc) + return length; + + return hgl::strcmp(buffer,length,sc->buffer,sc->length); + } + + /** + * 和一个字符串进行比较 + * @param pos 起始位置 + * @param sc 比较字符串 + * @return <0 我方小 + * @return 0 等同 + * @return >0 我方大 + */ + const int Comp(const int pos,const SelfClass *sc)const + { + if(!sc) + return length; + + if(lengthbuffer,sc->length); + } + + /** + * 和一个字符串进行比较 + * @param str 比较字符串 + * @return <0 我方小 + * @return 0 等同 + * @return >0 我方大 + */ + const int Comp(const T *str)const + { + return hgl::strcmp(buffer,length,str,hgl::strlen(str)); + } + + /** + * 和一个字符串进行比较 + * @param pos 起始位置 + * @param str 比较字符串 + * @return <0 我方小 + * @return 0 等同 + * @return >0 我方大 + */ + const int Comp(const int pos,const T *str)const + { + if(!str) + return length; + + if(length0 我方大 + */ + const int Comp(const T *str,const int num)const + { + if(!str) + return length-num; + + return hgl::strcmp(buffer,str,num); + } + + /** + * 和一个字符串比较指字长度的字符 + * @param str 比较字符串 + * @param num 比较字数 + * @return <0 我方小 + * @return 0 等同 + * @return >0 我方大 + */ + const int Comp(const int pos,const T *str,const int num)const + { + if(!str) + return(length-pos); + + if(length0 我方大 + */ + const int CaseComp(const SelfClass &sc)const + { + return hgl::stricmp(buffer,length,sc.buffer,sc.length); + } + + /** + * 和那一个字符串进行比较,英文不区分大小写 + * @param str 比较字符串 + * @return <0 我方小 + * @return 0 等同 + * @return >0 我方大 + */ + const int CaseComp(const T &str)const + { + return hgl::stricmp(buffer,length,str,hgl::strlen(str)); + } + + /** + * 和一个字符串进行比较指字长度的字符,英文不区分大小写 + * @param sc 比较字符串 + * @return <0 我方小 + * @return 0 等同 + * @return >0 我方大 + */ + const int CaseComp(const SelfClass &sc,const int num)const + { + return hgl::stricmp(buffer,length,sc.buffer,num); + } + + /** + * 和那一个字符串进行比较指字长度的字符,英文不区分大小写 + * @param str 比较字符串 + * @return <0 我方小 + * @return 0 等同 + * @return >0 我方大 + */ + const int CaseComp(const T &str,const int num)const + { + return hgl::stricmp(buffer,length,str,num); + } + + bool Insert(int pos,const T *istr,int len) ///<插入一个字符串 + { + if(!istr||!*istr) + return(false); + + if(len==-1) + len=hgl::strlen(istr); + else + len=hgl::strlen(istr,len); + + if(pos<0||pos>length||len<=0)return(false); + + const int need_length=length+len+1; + + if(need_length>malloc_length) + { + malloc_length=power_to_2(need_length); + + T *new_str=new T[malloc_length]; + + if(pos) + hgl_typecpy(new_str,buffer,pos); + + hgl_typecpy(new_str+pos,istr,len); + + if(pos=length||num<0)return(false); + + if(num==0)return(true); + + if(pos+num>length) //超出长度 + { + buffer[pos]=0; + + length=pos; + } + else + { + hgl_typemove(buffer+pos,buffer+pos+num,length-pos-num); + + length-=num; + + buffer[length]=0; + } + + return(true); + } + + bool ClipLeft(int num) + { + if(num<0||num>length) + return(false); + + buffer[num]=0; + length=num; + return(true); + } + + bool TrimRight(int num) + { + return ClipLeft(length-num); + } + + bool Clip(int pos,int num) + { + if(pos<0||pos>length + ||num<0||pos+num>length) + return(false); + + hgl_typemove(buffer,buffer+pos,num); + buffer[num]=0; + length=num; + return(true); + } + + bool SubString(const int start,int n=-1) + { + if(start<0||n==0)return(false); + if(n>0&&start+n>length)return(false); + + if(n<0) + n=length-start; + + hgl_typemove(buffer,buffer+start,n); + buffer[n]=0; + + return(true); + } + + bool Resize(int num) + { + if(num<=0) + return(false); + + if(num=malloc_length) + { + malloc_length=power_to_2(length+1); + T *new_str=new T[malloc_length]; + hgl_typecpy(new_str,buffer,length); + delete[] buffer; + buffer=new_str; + } + + hgl_set(buffer+length,' ',num-length); + length=num; + buffer[length]=0; + } + + return(true); + } + + bool Write(int pos,const SelfClass &str) + { + if(pos<0||pos>length) + return(false); + + int end_pos=pos+str.length; + + if(end_pos>malloc_length) + { + malloc_length=power_to_2(end_pos+1); + + T *new_str=new T[malloc_length]; + + hgl_typecpy(new_str,buffer,length); + delete[] buffer; + buffer=new_str; + } + + hgl_typecpy(buffer+pos,str.buffer,str.length); + buffer[end_pos]=0; + length=end_pos; + return(true); + } + };//class StringInstance +}//namespace hgl +#endif//HGL_TYPE_STRING_INSTANCE_INCLUDE diff --git a/inc/hgl/type/_Object.h b/inc/hgl/type/_Object.h new file mode 100644 index 00000000..4ff67ec4 --- /dev/null +++ b/inc/hgl/type/_Object.h @@ -0,0 +1,42 @@ +#ifndef HGL__OBJECT_INCLUDE +#define HGL__OBJECT_INCLUDE + +#include + +namespace hgl +{ + /** + * 最终基类 + */ + class _Object ///最终基类 + { + public: + + virtual ~_Object()=default; ///<本类析构函数 + + public: //调试用 + + virtual UTF8String ToDebugString(){} ///<输出调试用字符串 + };//class _Object + + typedef void (_Object::*ObjectMemberFunc)(); + + //此代码取自AngelScript,感谢 + #define GetMemberFuncPointer(c,m) MethodPtr::Convert((void (c::*)())(&c::m)) + + template struct MethodPtr + { + template + static void *Convert(M Mthd) + { + union u + { + M m; + void *v; + }; + + return ((u *)(&Mthd))->v; + } + };//struct MethodPtr +}//namespace hgl +#endif//HGL__OBJECT_INCLUDE