diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ccef777 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.0) + +project(CMCore) + +set(CMCORE_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) +set(CMCORE_ROOT_INCLUDE_PATH ${CMCORE_ROOT_PATH}/inc) +set(CMCORE_ROOT_SOURCE_PATH ${CMCORE_ROOT_PATH}/src) + +set(CMAKE_MODULE_PATH ${CMCORE_ROOT_PATH}/cmake) + +include(CMCoreCheck) + +include_directories(${CMCORE_ROOT_INCLUDE_PATH}) +add_subdirectory(${CMCORE_ROOT_SOURCE_PATH}) diff --git a/cmake/CMCoreCheck.cmake b/cmake/CMCoreCheck.cmake new file mode 100644 index 0000000..f098c2c --- /dev/null +++ b/cmake/CMCoreCheck.cmake @@ -0,0 +1,11 @@ +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +include(system_bit) +include(version) +include(compiler) +include(output_path) + +check_system_bits() +check_system_version() +set_compiler_param() +set_output_directory() diff --git a/cmake/compiler.cmake b/cmake/compiler.cmake new file mode 100644 index 0000000..d7f5bca --- /dev/null +++ b/cmake/compiler.cmake @@ -0,0 +1,47 @@ +macro(set_compiler_param) + + IF(WIN32) + + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MDd") + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd") + + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MD") + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD") + + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++14") + + add_compile_options(/arch:AVX2) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) + + ELSE() + IF(NOT ANDROID) + IF(APPLE) + SET(USE_CLANG ON) + ELSE() + OPTION(USE_CLANG OFF) + ENDIF() + + if(USE_CLANG) + SET(CMAKE_C_COMPILER clang) + SET(CMAKE_CXX_COMPILER clang++) + endif() + ENDIF() + + add_compile_options(-mavx) + + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11") + + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb3") + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb3") + + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast") + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast") + ENDIF() + + MESSAGE("C Compiler: " ${CMAKE_C_COMPILER}) + MESSAGE("C++ Compiler: " ${CMAKE_CXX_COMPILER}) + MESSAGE("C Flag: " ${CMAKE_C_FLAGS}) + MESSAGE("C++ Flag: " ${CMAKE_CXX_FLAGS}) + +endmacro() diff --git a/cmake/output_path.cmake b/cmake/output_path.cmake new file mode 100644 index 0000000..b435b2f --- /dev/null +++ b/cmake/output_path.cmake @@ -0,0 +1,33 @@ +macro(set_output_directory) + + IF(ANDROID) + SET(OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/out/android/${ANDROID_ABI}) + ELSEIF(IOS) + SET(OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/out/iOS/${IOS_PLATFORM}) + ELSE() + IF(WIN32) + SET(USE_GUI ON) + ENDIF() + + SET(OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/out/${CMAKE_SYSTEM_NAME}_${HGL_BITS}) + ENDIF() + + MESSAGE("SYSTEM NAME: " ${CMAKE_SYSTEM_NAME}) + MESSAGE("OUTPUT DIRECTORY: " ${OUTPUT_DIRECTORY}) + + SET(OUTPUT_DIRECTORY_DEBUG ${OUTPUT_DIRECTORY}_Debug) + SET(OUTPUT_DIRECTORY_RELEASE ${OUTPUT_DIRECTORY}_Release) + + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIRECTORY}) + SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${OUTPUT_DIRECTORY}) + SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_DIRECTORY}) + + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${OUTPUT_DIRECTORY_DEBUG}) + SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${OUTPUT_DIRECTORY_DEBUG}) + SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${OUTPUT_DIRECTORY_DEBUG}) + + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${OUTPUT_DIRECTORY_RELEASE}) + SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${OUTPUT_DIRECTORY_RELEASE}) + SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${OUTPUT_DIRECTORY_RELEASE}) + +endmacro() diff --git a/cmake/system_bit.cmake b/cmake/system_bit.cmake new file mode 100644 index 0000000..cf0d8b3 --- /dev/null +++ b/cmake/system_bit.cmake @@ -0,0 +1,31 @@ +macro(check_system_bits) + + IF(APPLE) + SET(HGL_BITS 64) + ELSE() + IF(ANDROID) + if(ANDROID_ABI MATCHES ".*64.*") + SET(HGL_BITS 64) + else() + SET(HGL_BITS 32) + endif() + ELSE() + IF(CMAKE_SIZEOF_VOID_P EQUAL 8) + SET(HGL_BITS 64) + ELSE() + SET(HGL_BITS 32) + ENDIF() + endif() + endif() + + IF(HGL_BITS EQUAL 32) + add_definitions(-DHGL_32_BITS) + add_definitions(-DHGL_POINTER_UINT=uint32) + ELSE() + add_definitions(-DHGL_64_BITS) + add_definitions(-DHGL_POINTER_UINT=uint64) + ENDIF() + + Message("System is ${HGL_BITS} Bit") + +endmacro() diff --git a/cmake/version.cmake b/cmake/version.cmake new file mode 100644 index 0000000..090f70d --- /dev/null +++ b/cmake/version.cmake @@ -0,0 +1,25 @@ +macro(check_system_version) + + message("Host system: " ${CMAKE_HOST_SYSTEM}) + message("Host system name: " ${CMAKE_HOST_SYSTEM_NAME}) + message("Host system version: " ${CMAKE_HOST_SYSTEM_VERSION}) + + message("Compile features: " ${CMAKE_CXX_COMPILE_FEATURES}) + message("Compile Flags: " ${CMAKE_C_FLAGS}) + message("C++ Compile Flags: " ${CMAKE_CXX_FLAGS}) + message("Build type: " ${CMAKE_BUILD_TYPE}) + + add_definitions(-DHGL_HOST_SYSTEM="${CMAKE_HOST_SYSTEM}") + + add_definitions(-DHGL_COMPILE_C_FLAGS="${CMAKE_C_FLAGS}") + add_definitions(-DHGL_COMPILE_CXX_FLAGS="${CMAKE_CXX_FLAGS}") + + add_definitions(-DCMAKE_VERSION="${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}") + + MESSAGE("C Compile Features: " ${CMAKE_C_COMPILE_FEATURES}) + MESSAGE("C++ Compile Features: " ${CMAKE_CXX_COMPILE_FEATURES}) + + # add_definitions(-DHGL_COMPILE_C_FEATURES="${CMAKE_C_COMPILE_FEATURES}") + # add_definitions(-DHGL_COMPILE_CXX_FEATURES="${CMAKE_CXX_COMPILE_FEATURES}") + +endmacro() diff --git a/inc/hgl/CodePage.h b/inc/hgl/CodePage.h new file mode 100644 index 0000000..d647f1c --- /dev/null +++ b/inc/hgl/CodePage.h @@ -0,0 +1,243 @@ +#ifndef HGL_CODE_PAGE_INCLUDE +#define HGL_CODE_PAGE_INCLUDE + +#include +#include +namespace hgl +{ + struct CodePageAndCharSet + { + CharCodePage codepage; + CharSetName charset; + }; + + constexpr struct CodePageAndCharSet CodePage2CharSet[]= + { + {ccpNone, "us-ascii" }, + + {ccpGBK, "gbk" }, + {ccpBig5, "big5" }, + {ccpGB2312, "gb2312" }, + {ccpGB18030, "gb18030" }, + + {ccpShiftJIS, "shift-jis" }, + {ccpJISX, "iso-2022-jp" }, + + {ccpKorean, "ks_c_5601-1987"}, + + {ccpMacJanpan, "x-mac-japanese" }, + {ccpMacTraditionalChinese, "x-mac-chinesetrad" }, + {ccpMacSimplifiedChinese, "x-mac-chinesesimp" }, + + {ccpUTF7, "utf-7" }, + {ccpUTF8, "utf-8" }, + + {ccpUTF16LE, "utf-16le" }, + {ccpUTF16BE, "utf-16be" }, + {ccpUTF32LE, "utf-32le" }, + {ccpUTF32BE, "utf-32be" }, + };//const struct + + constexpr int CharSetCount=sizeof(CodePage2CharSet)/sizeof(CodePageAndCharSet); + + inline const char *FindCharSet(CharCodePage ccp) + { + for(int i=0;i(str)+1,len); + } + + inline u16char *u8_to_u16(const char *str) + { + int len; + return u8_to_u16(str,hgl::strlen(str)+1,len); + } + + inline UTF16String to_u16(const char *u8_str,int length) + { + int wlen; + u16char *ws=u8_to_u16(u8_str,length,wlen); + + return UTF16String(ws,wlen,true); + } + + inline UTF16String to_u16(const UTF8String &u8str) + { + return to_u16(u8str.c_str(),u8str.Length()); + } + + inline UTF16String to_u16(const char *str) + { + int wlen; + + u16char *ws=u8_to_u16(str,strlen(str),wlen); + + return UTF16String(ws,wlen,true); + } + + inline UTF8String to_u8(const u16char *wide_str,int length) + { + int ulen; + + char *us=u16_to_u8(wide_str,length,ulen); + + return UTF8String(us,ulen,true); + } + + inline UTF8String to_u8(const UTF16String &ws) + { + return to_u8(ws.c_str(),ws.Length()); + } + +#if HGL_OS == HGL_OS_Windows + inline OSString ToOSString(const char *str){return to_u16(str);} + inline OSString ToOSString(const UTF8String &str){return to_u16(str.c_str(), (int)(str.Length()));} + + inline UTF8String ToUTF8String(const os_char *str){return to_u8(str,strlen(str));} + inline UTF8String ToUTF8String(const OSString &str){return to_u8(str);} +#else + inline OSString ToOSString(const char *str){return OSString(str);} + inline OSString ToOSString(const UTF8String &str){return str;} + + inline UTF8String ToUTF8String(const os_char *str){return UTF8String(str);} + inline UTF8String ToUTF8String(const OSString &str){return str;} +#endif// + + const BOMFileHeader *ParseBOM(const void *input); + + bool BOM2CharSet(CharSet *cs,const BOMFileHeader *bom); +}//namespace hgl +#endif//HGL_CODE_PAGE_INCLUDE diff --git a/inc/hgl/CompOperator.h b/inc/hgl/CompOperator.h new file mode 100644 index 0000000..474581a --- /dev/null +++ b/inc/hgl/CompOperator.h @@ -0,0 +1,16 @@ +#ifndef HGL_COMP_OPERATOR_INCLUDE +#define HGL_COMP_OPERATOR_INCLUDE + +namespace hgl +{ + #define CompOperator(name,compfunc) 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;}\ + 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/Endian.h b/inc/hgl/Endian.h new file mode 100644 index 0000000..3461e31 --- /dev/null +++ b/inc/hgl/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){hgl_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){hgl_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/LogInfo.h b/inc/hgl/LogInfo.h new file mode 100644 index 0000000..71ac103 --- /dev/null +++ b/inc/hgl/LogInfo.h @@ -0,0 +1,63 @@ +#ifndef HGL_LOGINFO_INCLUDE +#define HGL_LOGINFO_INCLUDE + +#include +#include + +#if (HGL_COMPILER == HGL_COMPILER_GNU)||(HGL_COMPILER == HGL_COMPILER_LLVM) + #define __HGL_FUNC__ __PRETTY_FUNCTION__ +#elif HGL_COMPILER == HGL_COMPILER_Microsoft + #define __HGL_FUNC__ __FUNCSIG__ +#else + #define __HGL_FUNC__ __FUNCTION__ +#endif// + +namespace hgl +{ + namespace logger + { + enum LogLevel + { + llError=0, //错误,肯定出对话框 + llProblem, //问题,默认出对话框 + llHint, //提示,不重要,debug状态默认出对话框 + llLog //记录一下 + };//enum LogLevel + + inline void Log(LogLevel ll,const UTF16String &str) + { + std::wcout<>LogFrom(\"")+to_u16(filename)+U16_TEXT("\", ")+UTF16String(line)+U16_TEXT(" line,func:\"")+to_u16(funcname)+U16_TEXT("\")")); + } + + inline void DebugLog(LogLevel ll,const UTF8String &str,const char *filename,int line,const char *funcname) + { + Log(ll,str+U8_TEXT(">>LogFrom(\"")+UTF8String(filename)+U8_TEXT("\", ")+UTF8String(line)+U8_TEXT(" line,func:\"")+UTF8String(funcname)+U8_TEXT("\")")); + } + + #define LOG_INFO(str) {Log(llLog, str);} + #define LOG_HINT(str) {Log(llHint, str);} + #define LOG_PROBLEM(str) {Log(llProblem, str);} + #define LOG_ERROR(str) {Log(llError, str);} + + #define RETURN_FALSE {DebugLog(llLog,OS_TEXT("return(false)" ),__FILE__,__LINE__,__HGL_FUNC__);return(false);} + #define RETURN_ERROR(v) {DebugLog(llLog,OS_TEXT("return error(")+OSString(v)+OS_TEXT(")"),__FILE__,__LINE__,__HGL_FUNC__);return(v);} + #define RETURN_ERROR_NULL {DebugLog(llLog,OS_TEXT("return error(nullptr)" ),__FILE__,__LINE__,__HGL_FUNC__);return(nullptr);} + + #define RETURN_BOOL(proc) {if(proc)return(true);RETURN_FALSE} + + #define IF_FALSE_RETURN(str) if(!str)RETURN_FALSE; + }//namespace logger + + using namespace logger; +}//namespace hgl +#endif//HGL_LOGINFO_INCLUDE diff --git a/inc/hgl/Logger.h b/inc/hgl/Logger.h new file mode 100644 index 0000000..aa1283d --- /dev/null +++ b/inc/hgl/Logger.h @@ -0,0 +1,133 @@ +#ifndef HGL_LOGGER_INCLUDE +#define HGL_LOGGER_INCLUDE + +#include +namespace hgl +{ + namespace logger + { + enum LogLevel + { + llError=0, //错误,肯定出对话框 + llProblem, //问题,默认出对话框 + llHint, //提示,不重要,debug状态默认出对话框 + llLog //记录一下 + };//enum LogLevel + + /** + * 日志输出基类 + */ + class Logger + { + protected: + + LogLevel min_level; ///<最小输出级别 + UTF16String project_code; + + public: + + Logger(LogLevel l){min_level=l;} + virtual ~Logger()=default; + + const LogLevel GetLevel()const{return min_level;} ///<取得最小输出级别 + + virtual void Close()=0; ///<关闭日志 + + virtual void Write(const u16char *,int)=0; ///<输出一行u16char日志 + virtual void Write(const char *,int)=0; ///<输出一行char(utf8)日志 + };//class Logger + }//namespace logger + + namespace logger + { + /** + * 日志级别枚举 + */ + enum LOG_LEVEL + { + LL_START=0, ///<日志级别起始定义 + + LL_HOTPOT, ///<性能记录热点 + LL_CODE, ///<代码日志(引擎内部记录) + LL_USER, ///<用户日志(开发人员的日志) + LL_RUN, ///<运行日志(实际使用时的日志) + + LL_END ///<日志级别结束定义 + }; + + /** + * 影响级别 + */ + enum AFFECTOR_LEVEL + { + AL_START=0, + + AL_USER, ///<用户级(无关仅要,正常程序逻辑报错) + AL_FUNC, ///<函数级(当前函数报错) + AL_MODULE, ///<模块级 + AL_FULL, ///<整体级(很严重,只能退出) + + AL_MUST_FIXED, ///<必须修正的代码问题 + + AL_END + }; + + /** + * 日志输出基类 + */ + class LoggerBase + { + protected: + + LOG_LEVEL log_level; + AFFECTOR_LEVEL err_level; + + protected: + + uint32 source_file; ///<源代所在文件ID + uint32 source_line; ///<源代码所在行 + uint32 function; ///<函数ID + HGL_POINTER_UINT object_address; ///<对象地址 + HGL_POINTER_UINT thread_id; ///<线程ID + + public: + };//class AdvLogger + + /** + * 线程日志 + */ + class ThreadLogger + { + + public: + + + };//class ThreadLogger + + /** + * 对象日志 + */ + class ObjectLogger + { + }; + + /** + * 时间追踪日志 + * 针对同一数据记录每一次时间下的数值的日志输出模块 + */ + class TimeLogger + { + }; + + /** + * 图形日志
+ * 用于记录碰撞信息,寻路信息,路线跟踪等等 + */ + class GraphicsLogger + { + };// + }//namespace logger + + using namespace logger; +}//namespace hgl +#endif//HGL_LOGGER_INCLUDE diff --git a/inc/hgl/Macro.h b/inc/hgl/Macro.h new file mode 100644 index 0000000..ce84daa --- /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]; \ + \ + hgl_free(name); \ + name=nullptr; \ + } \ + } + + #define SAFE_FREE_OBJECT_ARRAY(name,num) { \ + if(name) \ + FREE_OBJECT_ARRAY(name,num); \ + } + + #define SAFE_FREE(name) { \ + if(name) \ + hgl_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/Time.h b/inc/hgl/Time.h new file mode 100644 index 0000000..b5d3e05 --- /dev/null +++ b/inc/hgl/Time.h @@ -0,0 +1,23 @@ +#ifndef HGL_TIME_INCLUDE +#define HGL_TIME_INCLUDE + +#include + +namespace hgl //时间 +{ + int GetTimeZone(); ///<返回时区的时差(单位:秒) + + uint64 GetMilliStartTime(); ///<取得毫秒程序启动时间(单位:1/1000秒) + uint64 GetMicroStartTime(); ///<取得微秒程序启动时间(单位:1/1000000秒) + double GetDoubleStartTime(); ///<取得秒程序启动时间(单位:秒) + + uint64 GetTime(); ///<取得当前时间(单位:1/1000秒) + uint64 GetMicroTime(); ///<取得当前时间(单位:1/1000000秒) + double GetDoubleTime(); ///<取得当前时间(单位:秒) + + double GetLocalDoubleTime(); ///<取得本地当前时间(单位:秒) + + void WaitTime(double); ///<等待一定时间(单位:秒) +}//namespace hgl + +#endif//HGL_TIME_INCLUDE diff --git a/inc/hgl/TypeFunc.h b/inc/hgl/TypeFunc.h new file mode 100644 index 0000000..aa12ea3 --- /dev/null +++ b/inc/hgl/TypeFunc.h @@ -0,0 +1,655 @@ +#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; + + #define HGL_DEF_ANG2RAD(ang) constexpr double HGL_RAD_##ang=double(ang)*(HGL_PI/180.0f); + + HGL_DEF_ANG2RAD(0) + HGL_DEF_ANG2RAD(45) + HGL_DEF_ANG2RAD(90) + HGL_DEF_ANG2RAD(135) + HGL_DEF_ANG2RAD(180) + HGL_DEF_ANG2RAD(225) + HGL_DEF_ANG2RAD(270) + HGL_DEF_ANG2RAD(315) + + #undef HGL_DEF_ANG2RAD + + 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 T hgl_clamp(const T &cur,const T &min_value,const T &max_value) + { + if(curmax_value)return max_value; + + return cur; + } + + 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 T *hgl_zero_new(const size_t count) + { + if(count<=0)return(nullptr); + + T *data=new T[count]; + memset(data,0,count*sizeof(T)); + return data; + } + + template + inline T *hgl_copy_new(const size_t count,const T *src) + { + if(count<=0)return(nullptr); + + T *data=new T[count]; + memcpy(data,src,count*sizeof(T)); + return data; + } + + /** + * 指定类型数据清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/filesystem/AssetManage.h b/inc/hgl/filesystem/AssetManage.h new file mode 100644 index 0000000..fa6f626 --- /dev/null +++ b/inc/hgl/filesystem/AssetManage.h @@ -0,0 +1,9 @@ +#ifndef HGL_FILESYSTEM_ASSET_MANAGE_INCLUDE +#define HGL_FILESYSTEM_ASSET_MANAGE_INCLUDE + +#include +namespace hgl +{ + +}//namespace hgl +#endif//HGL_FILESYSTEM_ASSET_MANAGE_INCLUDE diff --git a/inc/hgl/filesystem/EnumFile.h b/inc/hgl/filesystem/EnumFile.h new file mode 100644 index 0000000..5108996 --- /dev/null +++ b/inc/hgl/filesystem/EnumFile.h @@ -0,0 +1,75 @@ +#include + +namespace hgl +{ + namespace filesystem + { + struct EnumFileConfig + { + OSString folder_name; ///<要枚举的目录名称 + +#if HGL_OS == HGL_OS_Windows ///<通配符过滤是Windows平台独有 + OSString find_name; ///<要枚举的文件名称 +#endif//HGL_OS == HGL_OS_Windows + + bool proc_folder; ///<是否处理目录 + bool proc_file; ///<是否处理文件 + bool sub_folder; ///<是否查找子目录 + + public: + + EnumFileConfig(const OSString &fn) + { + folder_name=fn; + +#if HGL_OS == HGL_OS_Windows + find_name=OS_TEXT("*.*"); +#endif//HGL_OS == HGL_OS_Windows + + proc_folder=true; + proc_file=true; + sub_folder=false; + } + + EnumFileConfig(const EnumFileConfig *efc,const OSString &sub_folder_name) + { + folder_name =sub_folder_name; + +#if HGL_OS == HGL_OS_Windows + find_name =efc->find_name; +#endif//HGL_OS == HGL_OS_Windows + + proc_folder =efc->proc_folder; + proc_file =efc->proc_file; + sub_folder =efc->sub_folder; + } + + virtual ~EnumFileConfig()=default; + };//struct EnumFileConfig + + /** + * 枚举文件系统内的文件 + */ + class EnumFile + { + protected: + + virtual void ProcFolder(struct EnumFileConfig *parent_efc,struct EnumFileConfig *cur_efc,FileInfo &fi){} + virtual void ProcFile(struct EnumFileConfig *,FileInfo &fi){} + + virtual EnumFileConfig *CreateSubConfig(struct EnumFileConfig *up_efc,const FileInfo &fi) + { + const OSString full_sub_folder_name=MergeFilename(up_efc->folder_name,fi.name); + + return(new EnumFileConfig(up_efc,full_sub_folder_name)); + } + + public: + + EnumFile()=default; + virtual ~EnumFile()=default; + + virtual int Enum(EnumFileConfig *); + };//class EnumFile + }//namespace filesystem +}//namespace hgl diff --git a/inc/hgl/filesystem/EnumVolume.h b/inc/hgl/filesystem/EnumVolume.h new file mode 100644 index 0000000..47e7a10 --- /dev/null +++ b/inc/hgl/filesystem/EnumVolume.h @@ -0,0 +1,99 @@ +#pragma once + +#include + +namespace hgl +{ + namespace filesystem + { + /** + * 卷信息数据结构 + */ + struct VolumeInfo + { + enum DriverType + { + dtNone=0, ///<未知类型 + + dtRemovable, ///<可移动设备 + dtFixed, ///<固定设备 + dtRemote, ///<远程设备 + dtCDROM, ///<光盘驱动器 + dtRamDisk, ///<内存虚拟设备 + + dtEnd ///<结束定义 + }; + + u16char name[HGL_MAX_PATH]; ///<卷名称 + + u16char path[HGL_MAX_PATH]; ///<卷所对应的路径名(注意:不是所有卷都有对应路径) + + DriverType driver_type; ///<驱动器类型(注意:不是所有的卷都对应驱动器) + + uint32 serial; ///<卷序列号 + + u16char volume_label[HGL_MAX_PATH]; ///<卷标名称 + + u16char file_system[HGL_MAX_PATH]; ///<文件系统名称 + + uint32 filename_max_length; ///<文件名最大长度 + + bool unicode; ///<文件名支持UNICODE + + uint64 available_space; ///<有效容量 + uint64 total_space; ///<总空量 + uint64 free_space; ///<自由容量 + };//struct VolumeInfo + +#if HGL_OS == HGL_OS_Windows + + /** + * 卷检测配置 + */ + struct VolumeCheckConfig + { + bool removable =false; + bool fixed =false; + bool remote =false; + bool cdrom =false; + bool ram_disk =false; + bool unknow =false; + + public: + + /** + * 设置为全部检测 + */ + void SetFullCheck() + { + memset(this,0xff,sizeof(VolumeCheckConfig)); + } + + /** + * 是否无效配置 + */ + bool isErrorConfig()const + { + if(removable)return(false); + if(fixed)return(false); + if(remote)return(false); + if(cdrom)return(false); + if(ram_disk)return(false); + if(unknow)return(false); + + return(true); + } + }; + + /** + * 枚举当前计算机所有卷 + * @param vi_list 储存卷信息的列表 + * @param check_removable 检测可移除设备 + * @param check_remote 检测远程驱动器 + * @param check_cd 检测光盘 + * @return 查找到的卷数量,-1表示失败 + */ + int EnumVolume(List &vi_list,const VolumeCheckConfig &); +#endif//HGL_OS == HGL_OS_Windows + }//namespace filesystem +}//namespace hgl \ No newline at end of file diff --git a/inc/hgl/filesystem/FileSystem.h b/inc/hgl/filesystem/FileSystem.h new file mode 100644 index 0000000..c3b831e --- /dev/null +++ b/inc/hgl/filesystem/FileSystem.h @@ -0,0 +1,229 @@ +#ifndef HGL_FILE_SYSTEM_INCLUDE +#define HGL_FILE_SYSTEM_INCLUDE + +#include +#include +namespace hgl +{ + namespace io + { + class InputStream; + }//namespace io + + namespace filesystem + { + template + inline BaseString MergeFilename(const BaseString &pathname,const BaseString &filename,const T directory_separator_char,const T *directory_separator_str) + { + BaseString fullname; + + if(pathname.GetEndChar()==directory_separator_char) //结尾有分隔符 + { + if(filename.GetBeginChar()==directory_separator_char) //开头有分隔符 + { + fullname.Set(pathname.c_str(),pathname.Length()-1); //少取一个字符 + } + else + { + fullname=pathname; + } + } + else //结尾没有分隔符 + { + fullname=pathname; + + if(filename.GetBeginChar()!=directory_separator_char) //开头没有分隔符 + { + fullname.Strcat(directory_separator_str); //添加分隔符 + } + } + + fullname.Strcat(filename); + return fullname; + } + + /** + * 截取完整路径中的文件名 + * @param fullname 完整路径文件名 + */ + template + inline BaseString ClipFilename(const BaseString &fullname) + { + if(fullname.Length()<=1) + return(BaseString()); + + const T spear_char[] = { '/','\\' }; + + const int pos=fullname.FindRightChar(spear_char); + + if(pos==-1) + return BaseString(fullname); + + return fullname.SubString(pos+1); + } + + /** + * 截取一个文件名中的主名称(不能带路径) + * @param filename 文件名 + * @param split_char 扩展名分隔符,一般为'.' + */ + template + inline BaseString ClipFileMainname(const BaseString &filename,const T split_char='.') + { + if(filename.Length()<=1) + return(BaseString()); + + const int pos=filename.FindRightChar(split_char); + + if(pos==-1) + return BaseString(filename); + + return filename.SubString(0,pos); + } + + /** + * 截取完整文件名中的扩展名 + * @param fullname 完整文件名 + * @param include_dot 是否包括点 + */ + template + inline BaseString ClipFileExtName(const BaseString &fullname,bool include_dot=true) + { + int end=fullname.FindChar(T('?')); //url的文件名,以?为结束 + + if(end==-1) + end=fullname.Length(); + + int pos=fullname.FindRightChar(fullname.Length()-end,T('.')); + + if(pos==-1) + return BaseString(); + + return include_dot? fullname.SubString(pos, end- pos ): + fullname.SubString(pos+1, end-(pos+1)); + } + + /** + * 截取路径最后一个名字 + */ + template + inline BaseString ClipLastPathname(const BaseString &fullname) + { + if(fullname.Length()<=1) + return(BaseString()); + + const T gap_char[2]={'\\','/'}; + + T *p=nullptr; + + T *s=fullname.c_str(); + T *e=fullname.c_str()+fullname.Length()-1; + + while(e>s) + { + if(!p) + { + if(*e==gap_char[0]||*e==gap_char[1]) + { + --e; + continue; + } + + p=e; + --e; + } + else + { + if(*e==gap_char[0]||*e==gap_char[1]) + { + return BaseString(e+1,p-e); + } + + --e; + } + } + + return(BaseString()); + } + + inline UTF8String MergeFilename(const UTF8String &pathname,const UTF8String &filename) ///<组合路径名与文件名 + {return MergeFilename(pathname,filename,HGL_DIRECTORY_SEPARATOR,HGL_DIRECTORY_SEPARATOR_U8STR);} + + inline WideString MergeFilename(const WideString &pathname,const WideString &filename) ///<组合路径名与文件名 + {return MergeFilename(pathname,filename,L'\\',L"\\");} + + bool FileCopy(const OSString &,const OSString &); ///<文件复制 + bool FileDelete(const OSString &); ///<文件删除 + bool FileMove(const OSString &,const OSString &); ///<文件移动 + bool FileRename(const OSString &,const OSString &); ///<文件改名 + bool FileExist(const OSString &); ///<文件确认是否存在 + bool FileComp(const OSString &,const OSString &); ///<文件比较 + + bool FileCanRead(const OSString &); ///<检测文件是否可读 + bool FileCanWrite(const OSString &); ///<检测文件是否可写 + bool FileCanExec(const OSString &); ///<检测文件是否可执行 + + int64 LoadFileToMemory(const OSString &,void **); ///<加载一个文件到内存 + int64 SaveMemoryToFile(const OSString &,const void *,const int64 &); ///<保存一块内存成文件 + int64 SaveMemoryToFile(const OSString &,void **,const int64 *,const int &); ///<保存多块内存成一个文件 + + void *LoadFileToMemory(const OSString &,int64,void *buf,int64); ///<加载一个文件的一部分到内存 + bool SaveMemoryToFile(const OSString &,int64,const void *,int64); ///<保存一块内存到一个文件 + + bool IsDirectory(const os_char *); + inline bool IsDirectory(const OSString &str){return IsDirectory(str.c_str());} ///<判断这个名称是否是目录 + +#if HGL_OS != HGL_OS_Windows + bool IsLink(const os_char *); ///<判断这个名称是否是链接 +#endif// + + bool MakePath(const OSString &); ///<创建一个路径 + bool DeletePath(const OSString &); ///<删除一个路径 + void DeleteTree(const OSString &); ///<删除一个路径(包含所有文件) + + bool GetCurrentPath(OSString &); ///<取得当前路径 + bool GetCurrentProgram(OSString &); ///<取得当前程序全路径名称 + bool GetCurrentProgramPath(OSString &); ///<取得当前程序所在路径 + void GetLocalAppdataPath(os_char fn[HGL_MAX_PATH]); ///<取得当前用户应用程序数据存放路径 + + //使用int64而不是__int64是因为不是所有编译器都支持__int64的写法,必须使用DataType.H中引入的定义 + + /** + * 文件信息数据结构 + */ + struct FileInfo ///文件信息 + { + os_char name[HGL_MAX_PATH]; ///<文件名(不包含路径) + os_char fullname[HGL_MAX_PATH]; ///<完整名称(包含路径) + + uint64 size; ///<文件长度 + + union + { + uint32 attrib; ///<文件属性 + + struct + { + bool is_file:1; ///<是文件 + bool is_directory:1; ///<是目录 + + bool is_hiddle:1; ///<是否隐藏文件 + +#if HGL_OS != HGL_OS_Windows + bool is_link:1; ///<是否是链接 +#endif//HGL_OS != HGL_OS_Windows + + bool can_read:1; ///<可以读 + bool can_write:1; ///<可以写 + }; + }; + + uint64 mtime; ///<最后修改日期(这个值在win/unix下不通用) + };//struct FileInfo + + bool GetFileInfo(const os_char *filename,struct FileInfo &); ///<取得文件信息 + + int GetFileInfoList(List &, const OSString &folder_name, bool proc_folder, bool proc_file, bool sub_folder); + }//namespace filesystem +}//namespace hgl +#endif//HGL_FILE_SYSTEM_INCLUDE diff --git a/inc/hgl/io/DataInputStream.h b/inc/hgl/io/DataInputStream.h new file mode 100644 index 0000000..2708438 --- /dev/null +++ b/inc/hgl/io/DataInputStream.h @@ -0,0 +1,231 @@ +#ifndef HGL_IO_DATA_INPUT_STREAM_INCLUDE +#define HGL_IO_DATA_INPUT_STREAM_INCLUDE + +#include +#include +#include +namespace hgl +{ + namespace io + { + class InputStream; + + /** + * 格式数据输入流基类 + */ + class DataInputStream ///格式数据输入流基类 + { + protected: + + InputStream *in; + + public: + + DataInputStream(InputStream *is) + { + in=is; + } + + virtual ~DataInputStream() + { + } + + virtual void Use(InputStream *is) + { + in=is; + } + + virtual int64 Read(void *buf,int64 size) + { + if(!buf||size<0)return(-1); + + return(in?in->Read(buf,size):-1); + } + + virtual int64 Peek(void *buf,int64 size) + { + if(!buf||size<0)return(-1); + + return(in?in->Peek(buf,size):-1); + } + + virtual int64 ReadFully(void *buf,int64 size) + { + if(!buf||size<0)return(-1); + + return(in?in->ReadFully(buf,size):-1); + } + + virtual int64 Seek(int64 offset,SeekOrigin so=SeekOrigin::Begin) + { + return(in?in->Seek(offset,so):-1); + } + + virtual int64 Skip(int64 size) ///<跳过指定字节不访问 + { + return(in?in->Skip(size):-1); + } + + virtual bool CanRestart ()const{return in?in->CanRestart():false;} ///<是否可以复位 + virtual bool CanSeek ()const{return in?in->CanSeek ():false;} ///<是否可以定位 + virtual bool CanSize ()const{return in?in->CanSize ():false;} ///<是否可以取得尺寸 + virtual bool CanPeek ()const{return in?in->CanPeek ():false;} ///<是否可以预览数据 + + virtual bool Restart ()const{return in?in->Restart ():false;} ///<复位访问指针 + virtual int64 Tell ()const{return in?in->Tell ():-1;} ///<返回当前访问位置 + virtual int64 GetSize ()const{return in?in->GetSize ():-1;} ///<取得流长度 + virtual int64 Available ()const{return in?in->Available ():-1;} ///<剩下的可以不受阻塞读取的字节数 + + template bool ReadNumber(T &value); + + #define STREAM_READ(type,name) virtual bool Read##name(type &value) \ + { \ + return Read(value); \ + } \ + \ + virtual int64 Read##name(type *data,const int64 count) \ + { \ + if(count<=0)return(count); \ + if(!data)return(-1); \ + \ + return ReadArrays(data,count); \ + } + + STREAM_READ(char, Char ); + STREAM_READ(bool, Bool ); + STREAM_READ(int8, Int8 ); + STREAM_READ(uint8, Uint8 ); + + #undef STREAM_READ + + #define STREAM_READ(type,name) virtual bool Read##name(type &)=0; \ + virtual int64 Read##name(type *,const int64)=0; + + STREAM_READ(int16, Int16 ); + STREAM_READ(int32, Int32 ); + STREAM_READ(int64, Int64 ); + + STREAM_READ(uint16, Uint16 ); + STREAM_READ(uint32, Uint32 ); + STREAM_READ(uint64, Uint64 ); + + STREAM_READ(u16char, UTF16Char); + STREAM_READ(float, Float ); + STREAM_READ(double, Double ); + + #undef STREAM_READ + + bool Read(Vector2f &vec){return ReadFloat((float *)&vec,2)==2;} + bool Read(Vector3f &vec){return ReadFloat((float *)&vec,3)==3;} + bool Read(Vector4f &vec){return ReadFloat((float *)&vec,4)==4;} + + /** + * 自适应类型数据读取

+ * 请在多平台混用的情况下不要使用此函数,以免造成不同平台数据实质结构不一致的情况 + */ + template bool Read(T &data) + { + return(ReadFully(&data,sizeof(T))==sizeof(T)); + } + + /** + * 自适应类型数据阵列读取

+ * 请在多平台混用的情况下不要使用此函数,以免造成不同平台数据实质结构不一致的情况 + * @param data 数据存放区 + * @param count 数据个数 + * @return 实质读入的数据个数 + * @return <0 出错 + */ + template int64 ReadArrays(T *data,int64 count) + { + if(count<=0)return(count); + if(!data)return(-1); + + return ReadFully(data,count*sizeof(T))/sizeof(T); + } + + /** + * 自定义类型数据阵列读取

+ * 请在多平台混用的情况下不要使用此函数,以免造成不同平台数据实质结构不一致的情况 + * @param count 数据个数 + * @param alloc_count 分配数据个数(默认-1) + * @return 实质读入的数据指针,请使用delete[]释放 + * @return NULL 出错 + */ + template T *ReadArrays(int64 count) + { + if(count<=0)return(nullptr); + + T *data=new T[count]; + + if(data==0) + return(nullptr); + + if(ReadArrays(data,count)!=count) + { + delete[] data; + return(nullptr); + } + + return data; + } + + virtual bool ReadUTF16LEChars(u16char *,uint); ///<读取utf16-le格式字符阵列到u16char * + virtual bool ReadUTF16BEChars(u16char *,uint); ///<读取utf16-be格式字符阵列到u16char * + + //32bit str-length + virtual bool ReadUTF8String (char *, uint max_len=0); ///<读取utf8格式字符串(前缀四字节的字符串字节长度) + virtual bool ReadUTF8String (UTF8String &, uint max_len=0); ///<读取utf8格式字符串(前缀四字节的字符串字节长度) + virtual bool ReadUTF8String (UTF16String &, uint max_len=0); ///<读取utf8格式字符串(前缀四字节的字符串字节长度) + + virtual bool ReadUTF16LEString (u16char *, uint max_len=0); + virtual bool ReadUTF16BEString (u16char *, uint max_len=0); + + virtual bool ReadUTF16LEString (UTF16String &, uint max_len=0); ///<读取utf16-le格式字符串(前缀四字节的字符串字节长度) + virtual bool ReadUTF16BEString (UTF16String &, uint max_len=0); ///<读取utf16-be格式字符串(前缀四字节的字符串字节长度) + + //16bit str-length + virtual bool ReadUTF8ShortString (char *, uint max_len=0); + virtual bool ReadUTF8ShortString (UTF8String &, uint max_len=0); ///<读取utf8格式字符串(前缀四字节的字符串字节长度) + virtual bool ReadUTF8ShortString (UTF16String &, uint max_len=0); ///<读取utf8格式字符串(前缀四字节的字符串字节长度) + + virtual bool ReadUTF16LEShortString (u16char *, uint max_len=0); + virtual bool ReadUTF16BEShortString (u16char *, uint max_len=0); + + virtual bool ReadUTF16LEShortString (UTF16String &, uint max_len=0); ///<读取utf16-le格式字符串(前缀四字节的字符串字节长度) + virtual bool ReadUTF16BEShortString (UTF16String &, uint max_len=0); ///<读取utf16-be格式字符串(前缀四字节的字符串字节长度) + + //8bit str-length + virtual bool ReadUTF8TinyString (char *, uint max_len=0); + virtual bool ReadUTF8TinyString (UTF8String &, uint max_len=0); ///<读取utf8格式字符串(前缀四字节的字符串字节长度) + virtual bool ReadUTF8TinyString (UTF16String &, uint max_len=0); ///<读取utf8格式字符串(前缀四字节的字符串字节长度) + + virtual bool ReadUTF16LETinyString (u16char *, uint max_len=0); + virtual bool ReadUTF16BETinyString (u16char *, uint max_len=0); + + virtual bool ReadUTF16LETinyString (UTF16String &, uint max_len=0); ///<读取utf16-le格式字符串(前缀四字节的字符串字节长度) + virtual bool ReadUTF16BETinyString (UTF16String &, uint max_len=0); ///<读取utf16-be格式字符串(前缀四字节的字符串字节长度) + };//class DataInputStream + + template<> bool inline DataInputStream::ReadNumber(int8 &value){return ReadInt8(value);} + template<> bool inline DataInputStream::ReadNumber(uint8 &value){return ReadUint8(value);} + + #define DIS_READ_NUMBER(type,name) template<> bool inline DataInputStream::ReadNumber(type &value){return Read##name(value);} + + DIS_READ_NUMBER(int16, Int16 ); + DIS_READ_NUMBER(int32, Int32 ); + DIS_READ_NUMBER(int64, Int64 ); + + DIS_READ_NUMBER(uint16, Uint16 ); + DIS_READ_NUMBER(uint32, Uint32 ); + DIS_READ_NUMBER(uint64, Uint64 ); + + DIS_READ_NUMBER(u16char, UTF16Char); + DIS_READ_NUMBER(float, Float ); + DIS_READ_NUMBER(double, Double ); + + #undef DIS_READ_NUMBER + }//namespace io +}//namespace hgl +#include +#endif//HGL_IO_DATA_INPUT_STREAM_INCLUDE diff --git a/inc/hgl/io/DataOutputStream.h b/inc/hgl/io/DataOutputStream.h new file mode 100644 index 0000000..e1e7d29 --- /dev/null +++ b/inc/hgl/io/DataOutputStream.h @@ -0,0 +1,226 @@ +#ifndef HGL_IO_DATA_OUTPUT_STREAM_INCLUDE +#define HGL_IO_DATA_OUTPUT_STREAM_INCLUDE + +#include +#include +#include +#include +namespace hgl +{ + namespace io + { + class OutputStream; + + /** + * 格式数据输出流基类 + */ + class DataOutputStream ///格式数据输出流基类 + { + protected: + + OutputStream *out; + + public: + + DataOutputStream(OutputStream *os) + { + out=os; + } + + virtual ~DataOutputStream() + { + } + + virtual void Use(OutputStream *os) + { + out=os; + } + + virtual int64 Write(const void *buf,int64 size) + { + if(!buf||size<0)return(-1); + + return(out?out->Write(buf,size):-1); + } + + virtual int64 WriteFully(const void *buf,int64 size) + { + if(!buf||size<0)return(-1); + + return(out?out->WriteFully(buf,size):-1); + } + + virtual int64 Seek(int64 offset,SeekOrigin so=SeekOrigin::Begin) + { + return(out?out->Seek(offset,so):-1); + } + + virtual bool CanRestart ()const{return out?out->CanRestart ():false;} ///<是否可以复位 + virtual bool CanSeek ()const{return out?out->CanSeek ():false;} ///<是否可以定位 + virtual bool CanSize ()const{return out?out->CanSize ():false;} ///<是否可以取得尺寸 + + virtual bool Restart ()const{return out?out->Restart ():false;} ///<复位访问指针 + virtual int64 Tell ()const{return out?out->Tell ():-1;} ///<返回当前访问位置 + virtual int64 GetSize ()const{return out?out->GetSize ():-1;} ///<取得流长度 + virtual int64 Available ()const{return out?out->Available ():-1;} ///<剩下的可以不受阻塞写入的字节数 + + template bool WriteNumber(const T &value); + + #define STREAM_WRITE(type,name) virtual bool Write##name(const type &value) \ + { \ + return Write(value); \ + } \ + \ + virtual int64 Write##name(const type *data,const int64 count) \ + { \ + if(count<=0)return(count); \ + if(!data)return(-1); \ + \ + return WriteArrays(data,count); \ + } + + STREAM_WRITE(char, Char ); + STREAM_WRITE(bool, Bool ); + STREAM_WRITE(int8, Int8 ); + STREAM_WRITE(uint8, Uint8 ); + + #undef STREAM_WRITE + + #define STREAM_WRITE(type,name) virtual bool Write##name(const type &)=0; \ + virtual int64 Write##name(const type *,const int64)=0; + + STREAM_WRITE(int16, Int16 ); + STREAM_WRITE(int32, Int32 ); + STREAM_WRITE(int64, Int64 ); + + STREAM_WRITE(uint16, Uint16 ); + STREAM_WRITE(uint32, Uint32 ); + STREAM_WRITE(uint64, Uint64 ); + + STREAM_WRITE(u16char, UTF16Char); + STREAM_WRITE(float, Float ); + STREAM_WRITE(double, Double ); + + #undef STREAM_WRITE + + bool Write(const Vector2f &vec){return WriteFloat((float *)&vec,2)==2;} + bool Write(const Vector3f &vec){return WriteFloat((float *)&vec,3)==3;} + bool Write(const Vector4f &vec){return WriteFloat((float *)&vec,4)==4;} + + /** + * 自适应类型数据写入

+ * 请在多平台混用的情况下不要使用此函数,以免造成不同平台数据实质结构不一致的情况 + */ + template bool Write(const T &data) + { + return WriteFully(&data,sizeof(T))==sizeof(T); + } + + /** + * 自适应类型数据阵列写入

+ * 请在多平台混用的情况下不要使用此函数,以免造成不同平台数据实质结构不一致的情况 + * @param data 数据 + * @param count 数据个数 + * @return 实质写入的数据个数 + * @return -1 出错 + */ + template int64 WriteArrays(const T *data,int64 count) + { + if(count<=0)return(count); + if(!data)return(-1); + + return WriteFully(data,count*sizeof(T))/sizeof(T); + } + + template bool WriteUTF8Chars (const T *str,uint count); ///<按utf8格式写入字符阵列 + template bool WriteUTF16LEChars (const T *str,uint count); ///<按utf16-le格式写入字符阵列 + template bool WriteUTF16BEChars (const T *str,uint count); ///<按utf16-be格式写入字符阵列 + + template bool WriteUTF8Chars (const BaseString &str){return WriteUTF8Chars (str.c_str(),str.Length());} + template bool WriteUTF16LEChars (const BaseString &str){return WriteUTF16LEChars (str.c_str(),str.Length());} + template bool WriteUTF16BEChars (const BaseString &str){return WriteUTF16BEChars (str.c_str(),str.Length());} + + template bool WriteUTF8StringWithLength (const char *str,const uint length); + template bool WriteUTF8StringWithLength (const UTF16String &str); + + template bool WriteUTF16StringWithLength(const u16char *str,const uint len); + + public: + + //32 bit length + bool WriteUTF8String (const char *str,uint length); ///<按utf16-le格式写入字符串(前置4字节字符串长度,再写入字符阵列) + bool WriteUTF8String (const char *str ); ///<按utf8格式写入字符串(前置4字节字符串长度,再写入字符阵列) + bool WriteUTF8String (const UTF8String &str ); ///<按utf8格式写入字符串(前置4字节字符串长度,再写入字符阵列) + bool WriteUTF8String (const UTF16String &str ); ///<按utf8格式写入字符串(前置4字节字符串长度,再写入字符阵列) + + bool WriteUTF16LEString (const u16char *str,uint len); ///<按utf16-le格式写入字符串(前置4字节字符串长度,再写入字符阵列) + bool WriteUTF16BEString (const u16char *str,uint len); ///<按utf16-be格式写入字符串(前置4字节字符串长度,再写入字符阵列) + + bool WriteUTF16LEString (const UTF16String &str ); ///<按utf16-le格式写入字符串(前置4字节字符串长度,再写入字符阵列) + bool WriteUTF16BEString (const UTF16String &str ); ///<按utf16-be格式写入字符串(前置4字节字符串长度,再写入字符阵列) + + bool WriteUTF16LEString (const u16char *str ); ///<按utf16-le格式写入字符串(前置4字节字符串长度,再写入字符阵列) + bool WriteUTF16BEString (const u16char *str ); ///<按utf16-be格式写入字符串(前置4字节字符串长度,再写入字符阵列) + + bool WriteUTF16LEString (const UTF8String &str ){return WriteUTF16LEString(to_u16(str));} ///<按utf16-le格式写入字符串(前置4字节字符串长度,再写入字符阵列) + bool WriteUTF16BEString (const UTF8String &str ){return WriteUTF16BEString(to_u16(str));} ///<按utf16-be格式写入字符串(前置4字节字符串长度,再写入字符阵列) + + //16 bit length + bool WriteUTF8ShortString (const char *str,uint length); ///<按utf16-le格式写入字符串(前置2字节字符串长度,再写入字符阵列) + bool WriteUTF8ShortString (const char *str ); ///<按utf8格式写入字符串(前置2字节字符串长度,再写入字符阵列) + bool WriteUTF8ShortString (const UTF8String &str ); ///<按utf8格式写入字符串(前置2字节字符串长度,再写入字符阵列) + bool WriteUTF8ShortString (const UTF16String &str ); ///<按utf8格式写入字符串(前置2字节字符串长度,再写入字符阵列) + + bool WriteUTF16LEShortString(const u16char *str,uint len); ///<按utf16-le格式写入字符串(前置2字节字符串长度,再写入字符阵列) + bool WriteUTF16BEShortString(const u16char *str,uint len); ///<按utf16-be格式写入字符串(前置2字节字符串长度,再写入字符阵列) + + bool WriteUTF16LEShortString(const UTF16String &str ); ///<按utf16-le格式写入字符串(前置2字节字符串长度,再写入字符阵列) + bool WriteUTF16BEShortString(const UTF16String &str ); ///<按utf16-be格式写入字符串(前置2字节字符串长度,再写入字符阵列) + + bool WriteUTF16LEShortString(const u16char *str ); ///<按utf16-le格式写入字符串(前置2字节字符串长度,再写入字符阵列) + bool WriteUTF16BEShortString(const u16char *str ); ///<按utf16-be格式写入字符串(前置2字节字符串长度,再写入字符阵列) + + bool WriteUTF16LEShortString(const UTF8String &str ){return WriteUTF16LEShortString(to_u16(str));} ///<按utf16-le格式写入字符串(前置2字节字符串长度,再写入字符阵列) + bool WriteUTF16BEShortString(const UTF8String &str ){return WriteUTF16BEShortString(to_u16(str));} ///<按utf16-be格式写入字符串(前置2字节字符串长度,再写入字符阵列) + + //8 bit length + bool WriteUTF8TinyString (const char *str,uint length); ///<按utf16-le格式写入字符串(前置1字节字符串长度,再写入字符阵列) + bool WriteUTF8TinyString (const char *str ); ///<按utf8格式写入字符串(前置1字节字符串长度,再写入字符阵列) + bool WriteUTF8TinyString (const UTF8String &str ); ///<按utf8格式写入字符串(前置1字节字符串长度,再写入字符阵列) + bool WriteUTF8TinyString (const UTF16String &str ); ///<按utf8格式写入字符串(前置1字节字符串长度,再写入字符阵列) + + bool WriteUTF16LETinyString (const u16char *str,uint len); ///<按utf16-le格式写入字符串(前置1字节字符串长度,再写入字符阵列) + bool WriteUTF16BETinyString (const u16char *str,uint len); ///<按utf16-be格式写入字符串(前置1字节字符串长度,再写入字符阵列) + + bool WriteUTF16LETinyString (const UTF16String &str ); ///<按utf16-le格式写入字符串(前置1字节字符串长度,再写入字符阵列) + bool WriteUTF16BETinyString (const UTF16String &str ); ///<按utf16-be格式写入字符串(前置1字节字符串长度,再写入字符阵列) + + bool WriteUTF16LETinyString (const u16char *str ); ///<按utf16-le格式写入字符串(前置1字节字符串长度,再写入字符阵列) + bool WriteUTF16BETinyString (const u16char *str ); ///<按utf16-be格式写入字符串(前置1字节字符串长度,再写入字符阵列) + + bool WriteUTF16LETinyString (const UTF8String &str ){return WriteUTF16LETinyString(to_u16(str));} ///<按utf16-le格式写入字符串(前置1字节字符串长度,再写入字符阵列) + bool WriteUTF16BETinyString (const UTF8String &str ){return WriteUTF16BETinyString(to_u16(str));} ///<按utf16-be格式写入字符串(前置1字节字符串长度,再写入字符阵列) + };//class DataOutputStream + + template<> bool inline DataOutputStream::WriteNumber(const int8 &value){return WriteInt8(value);} + template<> bool inline DataOutputStream::WriteNumber(const uint8 &value){return WriteUint8(value);} + + #define DOS_WRITE_NUMBER(type,name) template<> bool inline DataOutputStream::WriteNumber(const type &value){return Write##name(value);} + + DOS_WRITE_NUMBER(int16, Int16 ); + DOS_WRITE_NUMBER(int32, Int32 ); + DOS_WRITE_NUMBER(int64, Int64 ); + + DOS_WRITE_NUMBER(uint16, Uint16 ); + DOS_WRITE_NUMBER(uint32, Uint32 ); + DOS_WRITE_NUMBER(uint64, Uint64 ); + + DOS_WRITE_NUMBER(u16char, UTF16Char); + DOS_WRITE_NUMBER(float, Float ); + DOS_WRITE_NUMBER(double, Double ); + + #undef DOS_WRITE_NUMBER + }//namespace io +}//namespace hgl +#include +#endif//HGL_IO_DATA_OUTPUT_STREAM_INCLUDEs diff --git a/inc/hgl/io/EndianDataInputStream.h b/inc/hgl/io/EndianDataInputStream.h new file mode 100644 index 0000000..433cdd1 --- /dev/null +++ b/inc/hgl/io/EndianDataInputStream.h @@ -0,0 +1,100 @@ +#ifndef HGL_IO_ENDIAN_DATA_INPUT_STREAM_INCLUDE +#define HGL_IO_ENDIAN_DATA_INPUT_STREAM_INCLUDE + +#include +#include +namespace hgl +{ + namespace io + { + class DirectDataInputStream:public DataInputStream + { + public: + + using DataInputStream::DataInputStream; + virtual ~DirectDataInputStream()=default; + + #define STREAM_DIRECT_READ(type,name) virtual bool Read##name(type &value) \ + { \ + return Read(value); \ + } \ + \ + virtual int64 Read##name(type *data,const int64 count) \ + { \ + if(count<=0)return(count); \ + if(!data)return(-1); \ + \ + return ReadArrays(data,count); \ + } + + STREAM_DIRECT_READ(int16, Int16 ); + STREAM_DIRECT_READ(int32, Int32 ); + STREAM_DIRECT_READ(int64, Int64 ); + + STREAM_DIRECT_READ(uint16, Uint16 ); + STREAM_DIRECT_READ(uint32, Uint32 ); + STREAM_DIRECT_READ(uint64, Uint64 ); + + STREAM_DIRECT_READ(u16char,UTF16Char); + STREAM_DIRECT_READ(float, Float ); + STREAM_DIRECT_READ(double, Double ); + + #undef STREAM_DIRECT_READ + };//class DirectDataInputStream + + class SwapDataInputStream:public DataInputStream + { + public: + + using DataInputStream::DataInputStream; + virtual ~SwapDataInputStream()=default; + + #define STREAM_SWAP_READ(type,name) virtual bool Read##name(type &value) \ + {\ + type swap_value; \ + \ + if(!Read(swap_value)) \ + return(false); \ + \ + value=EndianSwap(swap_value); \ + return(true); \ + } \ + \ + virtual int64 Read##name(type *data,const int64 count) \ + { \ + if(count<=0)return(count); \ + if(!data)return(-1); \ + \ + const int64 result=ReadArrays(data,count); \ + \ + if(result<=0)return(result); \ + \ + EndianSwap(data,result); \ + return(result); \ + } + + STREAM_SWAP_READ(int16, Int16 ); + STREAM_SWAP_READ(int32, Int32 ); + STREAM_SWAP_READ(int64, Int64 ); + + STREAM_SWAP_READ(uint16, Uint16 ); + STREAM_SWAP_READ(uint32, Uint32 ); + STREAM_SWAP_READ(uint64, Uint64 ); + + STREAM_SWAP_READ(u16char, UTF16Char); + STREAM_SWAP_READ(float, Float ); + STREAM_SWAP_READ(double, Double ); + + #undef STREAM_SWAP_READ + };//class SwapDataInputStream + +#if HGL_ENDIAN == HGL_LITTLE_ENDIAN + typedef DirectDataInputStream LEDataInputStream; + typedef SwapDataInputStream BEDataInputStream; +#else + typedef DirectDataInputStream BEDataInputStream; + typedef SwapDataInputStream LEDataInputStream; +#endif//HGL_ENDIAN == HGL_LITTLE_ENDIAN + }//namespace io +}//namespace hgl +#endif//HGL_IO_ENDIAN_DATA_INPUT_STREAM_INCLUDE diff --git a/inc/hgl/io/EndianDataOutputStream.h b/inc/hgl/io/EndianDataOutputStream.h new file mode 100644 index 0000000..fda089e --- /dev/null +++ b/inc/hgl/io/EndianDataOutputStream.h @@ -0,0 +1,103 @@ +#ifndef HGL_IO_ENDIAN_DATA_OUTPUT_STREAM_INCLUDE +#define HGL_IO_ENDIAN_DATA_OUTPUT_STREAM_INCLUDE + +#include +#include +namespace hgl +{ + namespace io + { + class DirectDataOutputStream:public DataOutputStream + { + public: + + DirectDataOutputStream(OutputStream *os):DataOutputStream(os) + { + } + + virtual ~DirectDataOutputStream() + { + } + + #define STREAM_DIRECT_WRITE(type,name) virtual bool Write##name(const type &value) \ + { \ + return Write(value); \ + } \ + \ + virtual int64 Write##name(const type *data,const int64 count) \ + { \ + if(count<=0)return(count); \ + if(!data)return(-1); \ + \ + return WriteArrays(data,count); \ + } + + STREAM_DIRECT_WRITE(int16, Int16 ); + STREAM_DIRECT_WRITE(int32, Int32 ); + STREAM_DIRECT_WRITE(int64, Int64 ); + + STREAM_DIRECT_WRITE(uint16, Uint16 ); + STREAM_DIRECT_WRITE(uint32, Uint32 ); + STREAM_DIRECT_WRITE(uint64, Uint64 ); + + STREAM_DIRECT_WRITE(u16char,UTF16Char); + STREAM_DIRECT_WRITE(float, Float ); + STREAM_DIRECT_WRITE(double, Double ); + + #undef STREAM_DIRECT_WRITE + };//class DirectDataOutputStream + + class SwapDataOutputStream:public DataOutputStream + { + public: + + SwapDataOutputStream(OutputStream *os):DataOutputStream(os) + { + } + + virtual ~SwapDataOutputStream() + { + } + + #define STREAM_SWAP_WRITE(type,name) virtual bool Write##name(const type &value) \ + {\ + return Write(EndianSwap(value)); \ + } \ + \ + virtual int64 Write##name(const type *data,const int64 count) \ + { \ + if(count<=0)return(count); \ + if(!data)return(-1); \ + \ + SharedArray swap_data=new type[count]; \ + \ + EndianSwap(swap_data,data,count); \ + \ + return WriteArrays(swap_data,count); \ + } + + STREAM_SWAP_WRITE(int16, Int16 ); + STREAM_SWAP_WRITE(int32, Int32 ); + STREAM_SWAP_WRITE(int64, Int64 ); + + STREAM_SWAP_WRITE(uint16, Uint16 ); + STREAM_SWAP_WRITE(uint32, Uint32 ); + STREAM_SWAP_WRITE(uint64, Uint64 ); + + STREAM_SWAP_WRITE(u16char, UTF16Char); + STREAM_SWAP_WRITE(float, Float ); + STREAM_SWAP_WRITE(double, Double ); + + #undef STREAM_SWAP_WRITE + };//class SwapDataOutputStream + +#if HGL_ENDIAN == HGL_LITTLE_ENDIAN + typedef DirectDataOutputStream LEDataOutputStream; + typedef SwapDataOutputStream BEDataOutputStream; +#else + typedef DirectDataOutputStream BEDataOutputStream; + typedef SwapDataOutputStream LEDataOutputStream; +#endif//HGL_ENDIAN == HGL_LITTLE_ENDIAN + }//namespace io +}//namespace hgl +#endif//HGL_IO_ENDIAN_DATA_OUTPUT_STREAM_INCLUDE diff --git a/inc/hgl/io/FileAccess.h b/inc/hgl/io/FileAccess.h new file mode 100644 index 0000000..0dc09fa --- /dev/null +++ b/inc/hgl/io/FileAccess.h @@ -0,0 +1,83 @@ +#ifndef HGL_IO_FILE_ACCESS_INCLUDE +#define HGL_IO_FILE_ACCESS_INCLUDE + +#include +#include +#include +namespace hgl +{ + namespace io + { + enum FileOpenMode ///文件访问模式枚举 + { + fomNone=0, + + fomCreate, ///<创建文件,如存在则失败 + fomCreateTrunc, ///<强制创建,如存在则抹掉 + fomCreateTemp, + fomOnlyRead, ///<只读方式 + fomOnlyWrite, ///<只写方式 + fomReadWrite, ///<可读可写 + fomAppend, ///<追加模式 + + fomEnd + };//enum FileOpenMode + + /** + * 文件访问实例管理类 + */ + class FileAccess ///文件访问实例管理类 + { + protected: + + OSString filename; + + int fp; + + struct_stat64 file_state; + + FileOpenMode mode; + + public: + + FileAccess(); + virtual ~FileAccess(); + + virtual bool Open(const OSString &,FileOpenMode fom); ///<以指定模式打开一个文件 + virtual bool Create(const OSString &fn){return Open(fn,fomCreate);} ///<创建一个新文件,如文件已存在则创建失败 + virtual bool CreateTrunc(const OSString &fn){return Open(fn,fomCreateTrunc);} ///<创建一个新文件,如文件已存在则抹消它 + virtual bool OpenRead(const OSString &fn){return Open(fn,fomOnlyRead);} ///<以只读模式打开一个文件 + virtual bool OpenWrite(const OSString &fn){return Open(fn,fomOnlyWrite);} ///<以只写模式打开一个文件 + virtual bool OpenReadWrite(const OSString &fn){return Open(fn,fomReadWrite);} ///<以读写模式打开一个文件 + virtual bool CreateTemp(); + + virtual void Close(); ///<关闭文件 + virtual void CloseRead(); ///<仅关闭读取 + virtual void CloseWrite(); ///<仅关闭写入 + + virtual int GetFileHandle()const{return fp;} + + virtual bool CanRead()const; ///<文件是否可读 + virtual bool CanPeek()const{return(CanRead()&&CanSeek());} ///<文件是否可预读 + virtual bool CanWrite()const; ///<文件是否可写 + virtual bool CanSeek()const; ///<文件是否可定位访问指针 + virtual bool CanRestart()const{return CanSeek();} ///<文件是否可复位访问 + virtual bool CanSize()const{return(true);} ///<文件是否可取得长度 + + virtual int64 Seek(int64,SeekOrigin=SeekOrigin::Begin); ///<定位访问指针 + virtual int64 Tell()const; ///<取得访问指针位置 + virtual int64 GetSize(); ///<取得文件长度 + virtual bool Restart(); ///<复位访问指针 + + virtual int64 Read(void *,int64); ///<读取指定长度数据 + virtual int64 Peek(void *,int64); ///<预读指定长度数据 + virtual int64 Write(const void *,int64); ///<写入指定长度数据 + + virtual int64 AvailableRead(); ///<剩下的可读数据 + + virtual int64 Read(int64,void *,int64); ///<在指定位置读取指定长度的数据 + virtual int64 Write(int64,const void *,int64); ///<在指定位置写入指定长度的数据 + };//class FileAccess + }//namespace io +}//namespace hgl +#endif//HGL_IO_FILE_ACCESS_INCLUDE diff --git a/inc/hgl/io/FileInputStream.h b/inc/hgl/io/FileInputStream.h new file mode 100644 index 0000000..c364187 --- /dev/null +++ b/inc/hgl/io/FileInputStream.h @@ -0,0 +1,78 @@ +#ifndef HGL_IO_FILE_INPUT_STREAM_INCLUDE +#define HGL_IO_FILE_INPUT_STREAM_INCLUDE + +#include +#include +namespace hgl +{ + namespace io + { + /** + * 文件输入流类 + */ + class FileInputStream:public InputStream ///文件输入流类 + { + protected: + + SharedPtr file; ///<文件访问指针 + + public: + + FileInputStream(); + FileInputStream(SharedPtr &); + virtual ~FileInputStream(); + + virtual bool Open(const OSString &); ///<打开文件 + virtual void Close(); ///<关闭文件输入流 + + virtual int GetFileHandle()const{return file->GetFileHandle();} + + virtual int64 Read(void *,int64); ///<读取数据 + virtual int64 Peek(void *,int64); ///<预读数据 + + virtual bool CanSeek()const; ///<是否可移动访问指针 + virtual bool CanRestart()const; ///<是否可复位访问 + virtual bool CanSize()const; ///<是否可访问文件长度 + virtual bool CanPeek()const; ///<是否可预读数据 + + virtual int64 Skip(int64); ///<跳过指定字节 + virtual int64 Tell()const; ///<取当前位置 + virtual int64 GetSize()const; ///<取得文件长度 + virtual bool Restart(); ///<复位访问指针 + virtual int64 Seek(int64,SeekOrigin=SeekOrigin::Begin); ///<移动访问指针 + + virtual int64 Available()const; ///<剩下的可以不受阻塞访问的字节数 + + virtual int64 Read(int64,void *,int64); ///<在指定位置读取指定长度的数据 + };//class FileInputStream + + class OpenFileInputStream + { + FileInputStream *fis; + + public: + + OpenFileInputStream(const OSString &filename) + { + fis=new FileInputStream(); + + if(!fis->Open(filename)) + { + delete fis; + fis=nullptr; + } + } + + ~OpenFileInputStream() + { + SAFE_CLEAR(fis); + } + + const bool operator !(){return !fis;} + operator FileInputStream *(){return fis;} + FileInputStream *operator &(){return fis;} + FileInputStream *operator ->(){return fis;} + };//class OpenFileInputStream + }//namespace io +}//namespace hgl +#endif//HGL_IO_FILE_INPUT_STREAM_INCLUDE diff --git a/inc/hgl/io/FileOutputStream.h b/inc/hgl/io/FileOutputStream.h new file mode 100644 index 0000000..0483103 --- /dev/null +++ b/inc/hgl/io/FileOutputStream.h @@ -0,0 +1,93 @@ +#ifndef HGL_IO_FILE_OUTPUT_STREAM_INCLUDE +#define HGL_IO_FILE_OUTPUT_STREAM_INCLUDE + +#include +#include +namespace hgl +{ + namespace io + { + /** + * 文件输出流类 + */ + class FileOutputStream:public OutputStream ///文件输出流类 + { + protected: + + SharedPtr file; ///<文件访问指针 + + virtual bool OpenFile(const OSString &,FileOpenMode); + + public: + + FileOutputStream(); + FileOutputStream(SharedPtr &); + virtual ~FileOutputStream(); + + virtual bool Open(const OSString &fn,FileOpenMode mode){return OpenFile(fn,mode);} ///<打开文件,指定一个模式 + virtual bool Open(const OSString &fn){return OpenFile(fn,fomOnlyWrite);} ///<打开文件 + virtual bool Create(const OSString &fn){return OpenFile(fn,fomCreate);} ///<创建文件,如存在创建失败 + virtual bool CreateTrunc(const OSString &fn){return OpenFile(fn,fomCreateTrunc);} ///<创建文件,如存在则抹去 + virtual bool OpenAppend(const OSString &fn){return OpenFile(fn,fomAppend);} ///<打开文件,追加模式 + + virtual void Close(); ///<关闭文件 + + virtual int64 Write(const void *,int64); ///<写入数据 + + virtual bool CanSeek()const; ///<是否可移动访问指针 + virtual bool CanRestart()const; ///<是否可复位访问 + virtual bool CanSize()const; ///<是否可访问文件长度 + + virtual int64 Tell()const; ///<取当前位置 + virtual int64 GetSize()const; ///<取得文件长度 + virtual bool Restart(); ///<复位访问指针 + virtual int64 Seek(int64,SeekOrigin=SeekOrigin::Begin); ///<移动访问指针 + virtual int64 Available()const{return -1;} ///<可不受影响写入的字节数 + + virtual int64 Write(int64,const void *,int64); ///<在指定位置写入指定长度的数据 + };//class FileOutputStream + + /** + * 打开一个文件输出流 + */ + class OpenFileOutputStream + { + FileOutputStream *fos; + + public: + + OpenFileOutputStream() + { + fos=nullptr; + } + + /** + * 打开一个文件输出流构造函数 + * @param filename 文件名 + * @param mode 打开模式,默认只写(必然可读) + * @see FileOpenMode + */ + OpenFileOutputStream(const OSString &filename,FileOpenMode mode=fomOnlyWrite) + { + fos=new FileOutputStream(); + + if(!fos->Open(filename)) + { + delete fos; + fos=nullptr; + } + } + + ~OpenFileOutputStream() + { + SAFE_CLEAR(fos); + } + + const bool operator !(){return !fos;} + operator FileOutputStream *(){return fos;} + FileOutputStream *operator &(){return fos;} + FileOutputStream *operator ->(){return fos;} + };//class OpenFileInputStream + }//namespace io +}//namespace hgl +#endif//HGL_IO_FILE_OUTPUT_STREAM_INCLUDE diff --git a/inc/hgl/io/IOType.h b/inc/hgl/io/IOType.h new file mode 100644 index 0000000..d09068a --- /dev/null +++ b/inc/hgl/io/IOType.h @@ -0,0 +1,34 @@ +#ifndef HGL_IO_TYPE_INCLUDE +#define HGL_IO_TYPE_INCLUDE + +#include +namespace hgl +{ + namespace io + { + class DataInputStream; + class DataOutputStream; + + template struct io_type + { + T value; + + public: + + io_type()=default; + io_type(const T &v){value=v;} + + bool Read(DataInputStream *); + bool Write(DataOutputStream *)const; + + void operator = (const T &v) + { + value=v; + } + + operator T (){return value;} + operator const T ()const{return value;} + };//template struct io_type + }//namespace io +}//namespace hgl +#endif//HGL_IO_TYPE_INCLUDE diff --git a/inc/hgl/io/InputStream.h b/inc/hgl/io/InputStream.h new file mode 100644 index 0000000..ab26b41 --- /dev/null +++ b/inc/hgl/io/InputStream.h @@ -0,0 +1,39 @@ +#ifndef HGL_IO_INPUT_STREAM_INCLUDE +#define HGL_IO_INPUT_STREAM_INCLUDE + +#include +#include +namespace hgl +{ + namespace io + { + /** + * 数据输入流基类 + */ + class InputStream:public SeekAccess ///数据输入流基类 + { + public: + + virtual ~InputStream()=default; + + virtual void Close()=0; ///<关闭输入流 + + virtual int64 Read(void *,int64)=0; ///<读取数据 + virtual int64 Peek(void *,int64)=0; ///<预览数据 + virtual int64 ReadFully(void *buf,int64 buf_size){return Read(buf,buf_size);} ///<充分读取,保证读取到指定长度的数据(不计算超时) + + virtual bool CanRestart()const=0; ///<是否可以复位 + virtual bool CanSeek()const=0; ///<是否可以定位 + virtual bool CanSize()const=0; ///<是否可以取得尺寸 + virtual bool CanPeek()const=0; ///<是否可以预览数据 + + virtual bool Restart()=0; ///<复位访问指针 + virtual int64 Skip(int64)=0; ///<跳过指定字节不访问 + virtual int64 Seek(int64,SeekOrigin=SeekOrigin::Begin)=0; ///<移动访问指针 + virtual int64 Tell()const=0; ///<返回当前访问位置 + virtual int64 GetSize()const=0; ///<取得流长度 + virtual int64 Available()const=0; ///<剩下的可以不受阻塞访问的字节数 + };//class InputStream + }//namespace io +}//namespace hgl +#endif//HGL_IO_INPUT_STREAM_INCLUDE diff --git a/inc/hgl/io/JavaInputStream.h b/inc/hgl/io/JavaInputStream.h new file mode 100644 index 0000000..3b07a1c --- /dev/null +++ b/inc/hgl/io/JavaInputStream.h @@ -0,0 +1,71 @@ +#ifndef HGL_IO_JAVA_INPUT_STREAM_INCLUDE +#define HGL_IO_JAVA_INPUT_STREAM_INCLUDE + +#include +namespace hgl +{ + namespace io + { + /** + * Java数据输入流
+ * 接口类似于java.io.DataInputStream,用于和Java程序进行交互 + */ + class JavaInputStream + { + protected: + + BEDataInputStream *in; + + public: + + JavaInputStream(InputStream *is) + { + in=new BEDataInputStream(is); + } + + virtual ~JavaInputStream() + { + delete in; + } + + int64 read (void *ptr,int size){return in?in->ReadFully(ptr,size):-1;} + int skipBytes (int size) {return in?in->Seek(size,soCurrent):-1;} + + bool readBoolean (bool &b) {return in?in->ReadBool (b):false;} + bool readByte (int8 &i) {return in?in->ReadInt8 (i):false;} + bool readUnsignedByte (uint8 &i) {return in?in->ReadUint8 (i):false;} + + bool readShort (int16 &i) {return in?in->ReadInt16 (i):false;} + bool readUnsignedShort (uint16 &i) {return in?in->ReadUint16 (i):false;} + bool readInt (int32 &i) {return in?in->ReadInt32 (i):false;} + bool readLong (int64 &i) {return in?in->ReadInt64 (i):false;} + bool readFloat (float &f) {return in?in->ReadFloat (f):false;} + bool readDouble (double &d) {return in?in->ReadDouble (d):false;} + + bool readChar (u16char &c) + { + if(!in) + return(false); + + uint16 c16; + + if(!in->Read(c16)) + return(false); + + c=BigToCurrentEndian(c16); + return(true); + } + + bool readChars (u16char *wstr,const int count) + { + return in?in->ReadUTF16BEChars(wstr,count):false; + } + + bool readUTF (UTF16String &str) + { + return in?in->ReadUTF8ShortString(str); + } + };//class JavaInputStream + }//namespace io +}//namespace hgl +#endif//HGL_IO_JAVA_INPUT_STREAM_INCLUDE diff --git a/inc/hgl/io/JavaOutputStream.h b/inc/hgl/io/JavaOutputStream.h new file mode 100644 index 0000000..bf2d91d --- /dev/null +++ b/inc/hgl/io/JavaOutputStream.h @@ -0,0 +1,62 @@ +#ifndef HGL_IO_JAVA_OUTPUT_STREAM_INCLUDE +#define HGL_IO_JAVA_OUTPUT_STREAM_INCLUDE + +#include +namespace hgl +{ + namespace io + { + /** + * Java数据输出流
+ * 接口类似于java.io.DataOutputStream,用于和Java程序进行交互 + */ + class JavaOutputStream + { + protected: + + BEDataOutputStream *out; + + public: + + JavaOutputStream(OutputStream *os) + { + out=new BEDataOutputStream(os); + } + + virtual ~JavaOutputStream() + { + delete out; + } + + int64 write (const void *ptr,int size) {return out?out->WriteFully(ptr,size):-1;} + + bool writeBoolean (const bool &b) {return out?out->WriteBool (b):false;} + bool writeByte (const int8 &i) {return out?out->WriteInt8 (i):false;} + bool writeUnsignedByte (const uint8 &i) {return out?out->WriteUint8 (i):false;} + + bool writeShort (const int16 &i) {return out?out->WriteInt16 (i):false;} + bool writeUnsignedShort (const uint16 &i) {return out?out->WriteUint16(i):false;} + bool writeInt (const int32 &i) {return out?out->WriteInt32 (i):false;} + bool writeLong (const int64 &i) {return out?out->WriteInt64 (i):false;} + bool writeFloat (const float &f) {return out?out->WriteFloat (f):false;} + bool writeDouble (const double &d) {return out?out->WriteDouble(d):false;} + + bool writeChar (const u16char &c) + { + if(!out) + return(false); + + return out->Write(ToBigEndian(c)); + } + + bool writeChars (const u16char *wstr,const int64 count) + { + return out?out->WriteUTF16BEChars(wstr,count):false; + } + + bool writeUTF (const UTF8String &str){return out?out->WriteUTF8ShortString(str);} + bool writeUTF (const UTF16String &str){return out?out->WriteUTF8ShortString(str);} + };//class JavaOutputStream + }//namespace io +}//namespace hgl +#endif//HGL_IO_JAVA_OUTPUT_STREAM_INCLUDE diff --git a/inc/hgl/io/MemoryInputStream.h b/inc/hgl/io/MemoryInputStream.h new file mode 100644 index 0000000..8cebe5f --- /dev/null +++ b/inc/hgl/io/MemoryInputStream.h @@ -0,0 +1,162 @@ +#ifndef HGL_IO_MEMORY_INPUT_STREAM_INCLUDE +#define HGL_IO_MEMORY_INPUT_STREAM_INCLUDE + +#include +namespace hgl +{ + namespace io + { + /** + * 内存数据输入流,从内存块中取得数据。 + */ + class MemoryInputStream:public InputStream ///内存数据输入流 + { + protected: + + const uint8 *buf; + size_t buf_size; + size_t cur_pos; + + public: + + MemoryInputStream() + { + buf=0; + + buf_size=0; + cur_pos=0; + } + + virtual ~MemoryInputStream() + { + } + + /** + * 关联一个数据区到当前输入流 + * @param data 数据指针 + * @param size 数据长度字节数 + * @return 是否成功 + */ + bool Link(const void *data,const size_t size) + { + if(!data) + return(false); + + buf=(uint8 *)data; + buf_size=size; + cur_pos=0; + + return(true); + } + + /** + * 更新关联的数据区长度,不复位cur_pos + * @param data 数据指针 + * @param size 数据长度字节数 + * @return 是否成功 + */ + bool Update(void *data,size_t size) + { + if(!data) + return(false); + + buf=(uint8 *)data; + buf_size=size; + + return(true); + } + + void Unlink() + { + buf=0; + } + + void Close() + { + Unlink(); + } + + int64 Read(void *data,int64 size) + { + const int result=Peek(data,size); + + if(result>0) + cur_pos+=result; + + return result; + } + + int64 Peek(void *data,int64 size) + { + if(!buf||!data||size<0) + return(-1); + + if(cur_pos+size>buf_size) + size=buf_size-cur_pos; + + if(size<=0) + return(0); + + memcpy(data,buf+cur_pos,size); + + return size; + } + + bool CanRestart()const{return true;} + bool CanSeek()const{return true;} + bool CanSize()const{return true;} + bool CanPeek()const{return true;} + + bool Restart() + { + cur_pos=0; + return(true); + } + + int64 Skip(int64 bytes) + { + return Seek(bytes,SeekOrigin::Current); + } + + int64 Seek(int64 off,SeekOrigin so) + { + if(!CanSeek())return(-1); + + if(so==SeekOrigin::Current) + { + off+=cur_pos; + } + else + if(so==SeekOrigin::End) + { + off+=buf_size; + } + + if(off<0||off>=buf_size) + return(-1); + + cur_pos=off; + return cur_pos; + } + + int64 Tell()const + { + if(!buf)return(-1); + return cur_pos; + } + + int64 GetSize()const + { + if(!buf)return(-1); + return buf_size; + } + + int64 Available()const + { + if(!buf)return(-1); + return buf_size-cur_pos; + } + };//class MemoryInputStream + }//namespace io +}//namespace hgl +#endif//HGL_IO_MEMORY_INPUT_STREAM_INCLUDE diff --git a/inc/hgl/io/MemoryOutputStream.h b/inc/hgl/io/MemoryOutputStream.h new file mode 100644 index 0000000..04baf93 --- /dev/null +++ b/inc/hgl/io/MemoryOutputStream.h @@ -0,0 +1,235 @@ +#ifndef HGL_IO_MEMORY_OUTPUT_STREAM_INCLUDE +#define HGL_IO_MEMORY_OUTPUT_STREAM_INCLUDE + +#include +namespace hgl +{ + namespace io + { + /** + * 内存数据输出流,将数据输出到一个内存块中。 + */ + class MemoryOutputStream:public OutputStream ///内存数据输出流 + { + protected: + + uint8 *buf; + + size_t max_size; + size_t buf_size; + size_t cur_pos; + + bool one; + + public: + + MemoryOutputStream() + { + buf=0; + max_size=0; + buf_size=0; + cur_pos=0; + one=false; + } + + virtual ~MemoryOutputStream() + { + Close(); + } + + void *GetData()const{return buf;} + + /** + * 创建一个当前流数据的内存拷贝,此函数需用户自行delete[] + * @param len 存放数据长度的指针 + * @return 创建好的内存拷贝 + */ + void *CreateCopyData(uint *len)const + { + if(buf_size<=0) + return(nullptr); + + uint8 *data=new uint8[buf_size+1]; + memcpy(data,buf,buf_size); + data[buf_size]=0; + + if(len) + *len=buf_size; + + return data; + } + + /** + * 关联一个数据区到当前输出流 + * @param ptr 数据指针 + * @param size 数据长度字节数 + * @param one_instance 是否仅此一份实例(如果是,将由MemoryOutputStream类负责释放) + * @return 是否成功 + */ + bool Link(void *ptr,size_t size,bool one_instance=false) + { + if(!ptr||!size) + return(false); + + buf=(uint8 *)ptr; + buf_size=size; + max_size=size; + cur_pos=0; + + one=one_instance; + + return(true); + } + + /** + * 更新关联的数据区长度,不复位cur_pos + * @param ptr 数据指针 + * @param size 数据长度字节数 + * @return 是否成功 + */ + bool Update(void *ptr,size_t size) + { + if(!ptr||!size) + return(false); + + buf=(uint8 *)ptr; + buf_size=size; + max_size=0; + + return(true); + } + + void Unlink() + { + buf=0; + buf_size=0; + max_size=0; + } + + bool Create(int64 size) + { + Close(); + + if(size<=0) + return(false); + + buf=(uint8 *)hgl_malloc(size); + + if(!buf) + return(false); + + one=true; + cur_pos=0; + buf_size=size; + max_size=size; + + return(true); + } + + void Close() override + { + if(buf) + { + if(one) + hgl_free(buf); + + buf=0; + } + + buf_size=0; + max_size=0; + } + + void ClearData() + { + cur_pos=0; + buf_size=0; + } + + int64 Write(const void *ptr,int64 size) override + { + if(!ptr||size<0) + return(-1); + + if(!buf) + { + if(!Create(size)) + return(-1); + } + + if(cur_pos+size>buf_size) + { + if(one) + { + buf_size=cur_pos+size; + + if(buf_size>max_size) + { + max_size=power_to_2(buf_size); + + buf=(uint8 *)hgl_realloc(buf,max_size); + } + } + else + size=buf_size-cur_pos; + } + + if(size<=0) + return(0); + + memcpy(buf+cur_pos,ptr,size); + + cur_pos+=size; + + return size; + } + + bool CanRestart()const override{return true;} + bool CanSeek()const override{return true;} + bool CanSize()const override{return true;} + + bool Restart() override + { + cur_pos=0; + return(true); + } + + int64 Seek(int64 off,SeekOrigin so=SeekOrigin::Begin) override + { + if(!CanSeek())return(-1); + + if(so==SeekOrigin::Current) + { + off+=cur_pos; + } + else + if(so==SeekOrigin::End) + { + off+=buf_size; + } + + if(off<0||off>=buf_size) + return(-1); + + cur_pos=off; + return cur_pos; + } + + int64 Tell()const override + { + return cur_pos; + } + + int64 GetSize()const override + { + return buf_size; + } + + int64 Available()const override + { + return buf_size-cur_pos; + } + };//class MemoryOutputStream + }//namespace io +}//namespace hgl +#endif//HGL_IO_MEMORY_OUTPUT_STREAM_INCLUDE diff --git a/inc/hgl/io/OutputStream.h b/inc/hgl/io/OutputStream.h new file mode 100644 index 0000000..624f6cf --- /dev/null +++ b/inc/hgl/io/OutputStream.h @@ -0,0 +1,36 @@ +#ifndef HGL_IO_OUTPUT_STREAM_INCLUDE +#define HGL_IO_OUTPUT_STREAM_INCLUDE + +#include +#include +namespace hgl +{ + namespace io + { + /** + * 数据输出流基类 + */ + class OutputStream:public SeekAccess ///数据输出流基类 + { + public: + + virtual ~OutputStream()=default; + + virtual void Close()=0; ///<关闭输出流 + + virtual int64 Write(const void *,int64)=0; ///<写入数据 + virtual int64 WriteFully(const void *buf,int64 buf_size){return Write(buf,buf_size);} ///<充分写入,保证完整写入指定长度的数据 + + virtual bool CanRestart()const=0; ///<是否可以复位 + virtual bool CanSeek()const=0; ///<是否可以定位 + virtual bool CanSize()const=0; ///<是否可以取得尺寸 + + virtual bool Restart()=0; ///<复位访问指针 + virtual int64 Seek(int64,SeekOrigin=SeekOrigin::Begin)=0; ///<移动访问指针 + virtual int64 Tell()const=0; ///<返回当前访问位置 + virtual int64 GetSize()const=0; ///<取得流长度 + virtual int64 Available()const=0; ///<剩下的可以不受阻塞写入的字节数 + };//class OutputStream + }//namespace io +}//namespace hgl +#endif//HGL_IO_OUTPUT_STREAM_INCLUDE diff --git a/inc/hgl/io/RandomAccessFile.h b/inc/hgl/io/RandomAccessFile.h new file mode 100644 index 0000000..ed24b74 --- /dev/null +++ b/inc/hgl/io/RandomAccessFile.h @@ -0,0 +1,47 @@ +#ifndef HGL_IO_RANDOM_ACCESS_FILE_INCLUDE +#define HGL_IO_RANDOM_ACCESS_FILE_INCLUDE + +#include +#include +#include +namespace hgl +{ + namespace io + { + /** + * 随机文件访问

+ * 可同时被DataInputStream/DataOutputStream包含引用,但需注意他们将共用一个访问指针 + */ + class RandomAccessFile:public InputStream,public OutputStream + { + protected: + + SharedPtr file; ///<文件访问指针 + + public: + + RandomAccessFile(); + RandomAccessFile(SharedPtr &); + ~RandomAccessFile(); + + virtual bool Open(const OSString &); ///<打开文件 + virtual void Close(); ///<关闭文件 + + virtual int64 Read(void *,int64); ///<读取数据 + virtual int64 Write(const void *,int64); ///<写入数据 + + virtual int64 Read(int64,void *,int64); ///<在指定位置读取指定长度的数据 + virtual int64 Write(int64,const void *,int64); ///<在指定位置写入指定长度的数据 + + virtual bool CanSeek()const; ///<是否可移动访问指针 + virtual bool CanRestart()const; ///<是否可复位访问 + virtual bool CanSize()const; ///<是否可访问文件长度 + + virtual int64 Tell()const; ///<取当前位置 + virtual int64 GetSize(); ///<取得文件长度 + virtual bool Restart(); ///<复位访问指针 + virtual int64 Seek(int64,SeekOrigin=SeekOrigin::Begin); ///<移动访问指针 + };//class RandomAccessFile + }//namespace io +}//namespace hgl +#endif//HGL_IO_RANDOM_ACCESS_FILE_INCLUDE diff --git a/inc/hgl/io/SeekAccess.h b/inc/hgl/io/SeekAccess.h new file mode 100644 index 0000000..8977421 --- /dev/null +++ b/inc/hgl/io/SeekAccess.h @@ -0,0 +1,36 @@ +#ifndef HGL_IO_SEEK_ACCESS_INCLUDE +#define HGL_IO_SEEK_ACCESS_INCLUDE + +#include +namespace hgl +{ + namespace io + { + enum class SeekOrigin /// 资源偏移方向枚举 + { + Begin=0, ///<从资源最开始处开始,offset必须大于0。移到资源的offset位置 + Current, ///<从资源当前位置开始,移到资源的Position+offset位置 + End ///<从资源的结束位置开始,offset必须小于0,表示结束前的字符数 + };//enum SeekOrigin + + /** + * 定位访问功能基类 + */ + class SeekAccess + { + public: + + virtual ~SeekAccess()=default; + + virtual bool CanRestart()const=0; ///<是否可以复位 + virtual bool CanSeek()const=0; ///<是否可以定位 + virtual bool CanSize()const=0; ///<是否可以取得尺寸 + + virtual bool Restart()=0; ///<复位访问指针 + virtual int64 Seek(int64,SeekOrigin=SeekOrigin::Begin)=0; ///<移动访问指针 + virtual int64 Tell()const=0; ///<返回当前访问位置 + virtual int64 GetSize()const=0; ///<取得文件长度 + };//class SeekAccess + }//namespace io +}//namespace hgl +#endif//HGL_IO_SEEK_ACCESS_INCLUDE diff --git a/inc/hgl/io/TextOutputStream.h b/inc/hgl/io/TextOutputStream.h new file mode 100644 index 0000000..20f838b --- /dev/null +++ b/inc/hgl/io/TextOutputStream.h @@ -0,0 +1,176 @@ +#ifndef HGL_IO_TEXT_OUTPUT_STREAM_INCLUDE +#define HGL_IO_TEXT_OUTPUT_STREAM_INCLUDE + +#include +#include +namespace hgl +{ + namespace io + { + /** + * 文本输出流
+ * 用于将数据输出成文件,用于日志、配置等文本信息处理。 + */ + class TextOutputStream + { + protected: + + ByteOrderMask bom; ///<文本编码 + DataOutputStream *out; ///<数据输出流 + + public: + + TextOutputStream(ByteOrderMask _bom,DataOutputStream *_out) + { + bom=_bom; + out=_out; + } + + virtual ~TextOutputStream() + { + delete out; + } + + const ByteOrderMask GetBOM()const + { + return bom; + } + + DataOutputStream *GetDataOutputStream() + { + return out; + } + + operator DataOutputStream *() + { + return out; + } + + bool WriteBOM() ///<写入文本文件bom头 + { + if(!out)return(false); + + const BOMFileHeader *bom_item=BOMData+bom; + + return(out->Write(bom_item->data,bom_item->size)==bom_item->size); + } + + virtual bool WriteChars(const char *,int64)=0; ///<写入一个字符串 + virtual bool WriteChars(const u16char *,int64)=0; ///<写入一个字符串 + + template + bool WriteString(const BaseString &str) ///<写入一个字符串 + { + return WriteChars(str.c_str(),str.Length()); + } + + bool WriteLineEnd() ///<写入一个换行符 + { + return WriteChars(HGL_LINE_END,HGL_LINE_END_SIZE); + } + + template + bool WriteLine(const N *str,int64 size) + { + if(!WriteChars(str,size)) + return(false); + + return WriteLineEnd(); + } + + template + bool WriteLine(const BaseString &str) + { + return WriteLine(str.c_str(),str.Length()); + } + + /** + * 向流中写入一个文本(注:整体按标准文本文件模式) + */ + template + bool WriteText(const StringList &sl) + { + const int count=sl.GetCount(); + + for(int i=0;i + bool Write(const StringList &sl) + { + const int count=sl.GetCount(); + + if(!out->WriteInt32(count)) //写入行数 + return(false); + + if(count<=0) + return(true); + + SharedArray line_length=new int32[count]; + SharedArray str_list=new T *[count]; + int32 *line_p=line_length; + T **str_p=str_list; + + int32 total=0; + + for(int i=0;i &str=sl[i]; + + const int len=str.Length(); + + total+=len; + + *line_p++=len; + + *str_list++=str.c_str(); + } + + if(out->WriteInt32(line_length,count)!=count) //写入每行长度 + return(false); + + line_p=line_length; + str_p=str_list; + + SharedArray text=new T[total]; + T *text_p=text; + + for(int i=0;i class EndianTextOutputStream:public TextOutputStream ///文本输出流 + { + public: + + EndianTextOutputStream(OutputStream *); + + bool WriteChars(const char *,int64); ///<写入一个字符串 + bool WriteChars(const u16char *,int64); ///<写入一个字符串 + };//template class EndianTextOutputStream + + typedef EndianTextOutputStream UTF8TextOutputStream; + typedef EndianTextOutputStream UTF16LETextOutputStream; + typedef EndianTextOutputStream UTF16BETextOutputStream; + + template TextOutputStream *CreateTextOutputStream(OutputStream *os); + }//namespace io +}//namespace hgl +#endif//HGL_IO_TEXT_OUTPUT_STREAM_INCLUDE diff --git a/inc/hgl/math/FastTriangle.h b/inc/hgl/math/FastTriangle.h new file mode 100644 index 0000000..3c4d68d --- /dev/null +++ b/inc/hgl/math/FastTriangle.h @@ -0,0 +1,23 @@ +#ifndef HGL_ALGORITHM_MATH_FAST_TRIANGLE_FUNCTION_INCLUDE +#define HGL_ALGORITHM_MATH_FAST_TRIANGLE_FUNCTION_INCLUDE + +namespace hgl +{ + 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函数 +}//namespace hgl +#endif//HGL_ALGORITHM_MATH_FAST_TRIANGLE_FUNCTION_INCLUDE diff --git a/inc/hgl/math/Math.h b/inc/hgl/math/Math.h new file mode 100644 index 0000000..6637bfb --- /dev/null +++ b/inc/hgl/math/Math.h @@ -0,0 +1,8 @@ +#ifndef HGL_ALGORITHM_MATH_INCLUDE +#define HGL_ALGORITHM_MATH_INCLUDE + +#include +#include // Game Math and Geometry Library +#include + +#endif//HGL_ALGORITHM_MATH_INCLUDE diff --git a/inc/hgl/math/Matrix.h b/inc/hgl/math/Matrix.h new file mode 100644 index 0000000..10e7ea9 --- /dev/null +++ b/inc/hgl/math/Matrix.h @@ -0,0 +1,156 @@ +#ifndef HGL_ALGORITHM_MATH_VECTOR_MATRIX_INCLUDE +#define HGL_ALGORITHM_MATH_VECTOR_MATRIX_INCLUDE + +#include +#include +//注:GLM/CML(OpenGLMode)是列矩阵,计算坐标matrix*pos +// 而MGL是行矩阵,需要反过来pos*matrix + +namespace hgl +{ + using Matrix3f=float3x3; + using Matrix4f=float4x4; + + struct WorldMatrix + { + alignas(16) Matrix4f ortho; //2D正角视图矩阵 + + alignas(16) Matrix4f projection; +// alignas(16) Matrix4f inverse_projection; + alignas(16) Matrix4f modelview; + alignas(16) Matrix4f mvp; + alignas(16) Vector4f view_pos; //眼睛坐标 + };//struct WorldMatrix + + inline Matrix4f identity() + { + return Matrix4f::identity; + } + + inline Matrix4f inverse(const Matrix4f &m) + { + return m.Inverted(); + } + + inline Matrix4f ortho( float left, + float right, + float bottom, + float top, + float znear, + float zfar ) + { + return Matrix4f( + 2.0f / (right - left), 0.0f, 0.0f, -(right + left) / (right - left), + 0.0f, 2.0f / (bottom - top), 0.0f, -(bottom + top) / (bottom - top), + 0.0f, 0.0f, 1.0f / (znear - zfar), znear / (znear - zfar), + 0.0f, 0.0f, 0.0f, 1.0f); + } + + /** + * 生成一个正角视图矩阵 + * @param width 宽 + * @param height 高 + * @param znear 近平面z值 + * @param zfar 远平台z值 + */ + inline Matrix4f ortho(float width,float height,float znear,float zfar) + { + return Matrix4f( + 2.0f / width, 0.0f, 0.0f, -1, + 0.0f, 2.0f / height, 0.0f, -1, + 0.0f, 0.0f, 1.0f / (znear - zfar), znear / (znear - zfar), + 0.0f, 0.0f, 0.0f, 1.0f); + } + + /** + * 生成一个正角视图矩阵 + * @param width 宽 + * @param height 高 + */ + inline Matrix4f ortho(float width,float height) + { + return Matrix4f( + 2.0f / width, 0.0f, 0.0f, -1, + 0.0f, 2.0f / height, 0.0f, -1, + 0.0f, 0.0f, -1.0f , 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + } + + /** + * 生成一个透视矩阵 + * @param aspect_ratio 宽高比 + * @param field_of_view 视野 + * @param znear 近截面 + * @param zfar 远截面 + */ + inline Matrix4f perspective(float field_of_view, + float aspect_ratio, + float znear, + float zfar) + { + const float f = 1.0f / tan( hgl_ang2rad( 0.5f * field_of_view ) ); + + // float scaleX, shearXy, shearXz, x; + //float shearYx, scaleY, shearYz, y; + //float shearZx, shearZy, scaleZ, z; + //float shearWx, shearWy, shearWz, w; + + return Matrix4f( + f / aspect_ratio, 0.0f, 0.0f, 0.0f, + 0.0f, -f, 0.0f, 0.0f, + 0.0f, 0.0f, zfar / (znear - zfar), (znear * zfar) / (znear - zfar), + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + // 某些引擎这两项会乘0.5,那是因为他们是 -1 to 1 的Z值设定,而我们是0 to 1,所以这里不用乘 + // 同理,camera的znear为接近0的正数,zfar为一个较大的正数,默认使用16/256 + + 0.0f, 0.0f, -1.0f, 0.0f); + } + + 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(); + } +}//namespace hgl +#endif//HGL_ALGORITHM_MATH_VECTOR_MATRIX_INCLUDE diff --git a/inc/hgl/math/Vector.h b/inc/hgl/math/Vector.h new file mode 100644 index 0000000..6ad9854 --- /dev/null +++ b/inc/hgl/math/Vector.h @@ -0,0 +1,346 @@ +#ifndef HGL_ALGORITHM_MATH_VECTOR_INCLUDE +#define HGL_ALGORITHM_MATH_VECTOR_INCLUDE + +#ifdef _MSC_VER +#pragma warning(disable:4244) // double -> int 精度丢失警告 +#endif//_MSC_VER + +#include +#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 Vector2f=float2; + using Vector3f=float3; + using Vector4f=float4; + + 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); + } + + 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()); + } + + 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); + } + + template union vec2 + { + struct { T x,y; }; + struct { T r,g; }; + struct { T u,v; }; + T data[2]; + + public: + + vec2(){x=y=0;} + vec2(T v1,T v2):x(v1),y(v2){} + vec2(const vec2 &v2) + { + x=v2.x; + y=v2.y; + } + + vec2(const Vector2f &v2f) + { + x=v2f.x; + y=v2f.y; + } + + operator const Vector2f()const{return Vector2f(x,y);} + }; + + template union vec3 + { + struct { T x,y,z; }; + struct { T r,g,b; }; + struct { T u,v,w; }; + T data[3]; + + public: + + vec3(){x=y=z=0;} + vec3(T v1,T v2,T v3):x(v1),y(v2),z(v3){} + vec3(const vec3 &v3) + { + x=v3.x; + y=v3.y; + z=v3.z; + } + + vec3(const Vector3f &v3f) + { + x=v3f.x; + y=v3f.y; + z=v3f.z; + + return *this; + } + + operator const Vector3f()const{return Vector3f(x,y,z);} + }; + + template union vec4 + { + struct { T x,y,z,w; }; + struct { T r,g,b,a; }; + T data[4]; + + public: + + vec4(){x=y=z=w=0;} + vec4(T v1,T v2,T v3,T v4):x(v1),y(v2),z(v3),w(v4){} + vec4(const vec4 &v4) + { + x=v4.x; + y=v4.y; + z=v4.z; + w=v4.w; + } + + vec4(const Vector4f &v4f) + { + x=v4f.x; + y=v4f.y; + z=v4f.z; + w=v4f.w; + + return *this; + } + + operator const Vector4f()const{return Vector4f(x,y,z,w);} + }; +}//namespace hgl +#endif//HGL_ALGORITHM_MATH_VECTOR_INCLUDE diff --git a/inc/hgl/platform/Exit.h b/inc/hgl/platform/Exit.h new file mode 100644 index 0000000..33838c2 --- /dev/null +++ b/inc/hgl/platform/Exit.h @@ -0,0 +1,10 @@ +#ifndef HGL_EXIT_INCLUDE +#define HGL_EXIT_INCLUDE + +namespace hgl +{ + typedef int (*SignalAppExitFunc)(); //程序退出处理事件函数 + + void SetSignalAppExit(SignalAppExitFunc); //设置程序退出处理事件函数 +}//namespace hgl +#endif//HGL_EXIT_INCLUDE diff --git a/inc/hgl/platform/ExternalModule.h b/inc/hgl/platform/ExternalModule.h new file mode 100644 index 0000000..97463bf --- /dev/null +++ b/inc/hgl/platform/ExternalModule.h @@ -0,0 +1,36 @@ +#ifndef HGL_EXTERNAL_MODULE_INCLUDE +#define HGL_EXTERNAL_MODULE_INCLUDE + +#include +#include +#include OS_EXTERNAL_H +namespace hgl +{ + /** + * 这个类用于对外部动态库的调用,支持Windows/Linux/BSD/MacOSX
+ * Windows 下动态库扩展名为.DLL
+ * FreeBSD/MacOSX 下动态库扩展名为.dylib
+ * Linux 下动态库扩展名为.so + */ + class ExternalModule ///外部模块调用类 + { + ExternalModulePointer fp; + + public: //方法 + + ExternalModule(); ///<本类构造函数 + ExternalModule(ExternalModulePointer); ///<本类构造函数 + virtual ~ExternalModule(); ///<本类析构函数 + + bool Load(const os_char *); ///<加载一个外部模块 + void Clear(); ///<清除当前模块 + + void *FindFunc(const char *); ///<查找函数 + void *GetFunc(const char *); ///<取得函数 + + int Get(FuncLoad *); ///<加载函数列表 + };//class ExternalModule + + ExternalModule *LoadExternalModule(const os_char *); ///<加载一个外部模块 +}//namespace hgl +#endif//HGL_EXTERNAL_MODULE_INCLUDE diff --git a/inc/hgl/platform/FuncLoad.h b/inc/hgl/platform/FuncLoad.h new file mode 100644 index 0000000..8686ee8 --- /dev/null +++ b/inc/hgl/platform/FuncLoad.h @@ -0,0 +1,31 @@ +#ifndef HGL_FUNC_LOAD_INCLUDE +#define HGL_FUNC_LOAD_INCLUDE + +namespace hgl +{ + /** + * 函数加载定义数据结构 + */ + struct FuncLoad + { + char func_name[64]; ///<函数名称 + void **func_pointer; ///<函数指针 + };//struct FuncLoad + + #define HGL_FUNC_LOAD_LIST_BEGIN(name) struct FuncLoad name[]={ + #define HGL_FUNC_LOAD(name) {#name,(void **)&name}, + #define HGL_FUNC_LOAD_LIST_END {"",(void **)0}}; + + inline void ClearFuncLoadPointer(struct FuncLoad *flp) + { + if(!flp)return; + + while(flp->func_pointer) + { + flp->func_pointer=(void **)0; + + ++flp; + } + } +}//namespace hgl +#endif//HGL_FUNC_LOAD_INCLUDE diff --git a/inc/hgl/platform/Platform.h b/inc/hgl/platform/Platform.h new file mode 100644 index 0000000..43e9522 --- /dev/null +++ b/inc/hgl/platform/Platform.h @@ -0,0 +1,334 @@ +#ifndef HGL_PLATFORM_INCLUDE +#define HGL_PLATFORM_INCLUDE + +#ifdef _DEBUG + #define HGL_LIB_DEBUG_NAME "Debug" +#else + #define HGL_LIB_DEBUG_NAME "Release" +#endif// + +#define HGL_MERGE32(a,b,c,d) (a|b<<8|c<<16|d<<24) + +#define HGL_OS_Windows HGL_MERGE32('W','i','n',' ') +#define HGL_OS_macOS HGL_MERGE32('m','a','c',' ') +#define HGL_OS_iOS HGL_MERGE32('i','O','S',' ') +#define HGL_OS_FreeBSD HGL_MERGE32('F','B','S','D') +#define HGL_OS_NetBSD HGL_MERGE32('N','B','S','D') +#define HGL_OS_OpenBSD HGL_MERGE32('O','B','S','D') +#define HGL_OS_Linux HGL_MERGE32('L','i','n','u') +#define HGL_OS_Cygwin HGL_MERGE32('C','y','g','w') +#define HGL_OS_PSP2 HGL_MERGE32('P','S','P','2') +#define HGL_OS_PS4 HGL_MERGE32('P','S','4',' ') +#define HGL_OS_AIX HGL_MERGE32('A','I','X',' ') +#define HGL_OS_Android HGL_MERGE32('A','n','d','r') +#define HGL_OS_Wasm HGL_MERGE32('W','a','s','m') + +#define HGL_CPU_X86_32 HGL_MERGE32('8','6','3','2') +#define HGL_CPU_X86_64 HGL_MERGE32('8','6','6','4') +#define HGL_CPU_MIPS HGL_MERGE32('M','I','P','S') +#define HGL_CPU_MIPSel HGL_MERGE32('M','I','e','l') +#define HGL_CPU_MIPS64 HGL_MERGE32('M','I','6','4') +#define HGL_CPU_PowerPC HGL_MERGE32('P','P','C',' ') +#define HGL_CPU_PowerPC64 HGL_MERGE32('P','P','6','4') +#define HGL_CPU_Cell HGL_MERGE32('C','E','L','L') +#define HGL_CPU_ARM7 HGL_MERGE32('A','R','M','7') +#define HGL_CPU_ARM64 HGL_MERGE32('A','R','6','4') + +#define HGL_COMPILER_Microsoft HGL_MERGE32('M','S','C',' ') +#define HGL_COMPILER_GNU HGL_MERGE32('G','N','U',' ') +#define HGL_COMPILER_MinGW32 HGL_MERGE32('M','G','3','2') +#define HGL_COMPILER_Intel HGL_MERGE32('I','n','t','e') +#define HGL_COMPILER_IBM HGL_MERGE32('I','B','M',' ') +#define HGL_COMPILER_DigitalMars HGL_MERGE32('D','i','M','a') +#define HGL_COMPILER_LLVM HGL_MERGE32('L','L','V','M') +#define HGL_COMPILER_PGI HGL_MERGE32('P','G','I',' ') + +#define HGL_BIG_ENDIAN 'B' +#define HGL_LITTLE_ENDIAN 'L' + +#if defined(__amd64__) ||defined(__amd64) || \ + defined(__x86_64__) ||defined(__x86_64) || \ + defined(_M_AMD64) ||defined(_M_X64) + #define HGL_CPU HGL_CPU_X86_64 + #define HGL_CPU_NAME OS_TEXT("X86-64Bit") + #define HGL_LIB_CPU_NAME OS_TEXT("x64") + #define HGL_MIN_MEMORY_ALLOC_BYTES 8 + #define HGL_ENDIAN HGL_LITTLE_ENDIAN +#elif defined(i386) || defined(__i386__) || defined(__i386) ||defined(_M_IX86) + #define HGL_CPU HGL_CPU_X86_32 + #define HGL_CPU_NAME OS_TEXT("X86-32Bit") + #define HGL_LIB_CPU_NAME OS_TEXT("x86") + #define HGL_MIN_MEMORY_ALLOC_BYTES 4 + #define HGL_ENDIAN HGL_LITTLE_ENDIAN +#elif defined(_M_MIPS)||defined(_MIPS_ARCH)||defined(__mips__)||defined(__mips)||defined(mips)||defined(__MIPS__) + #define HGL_MIN_MEMORY_ALLOC_BYTES 4 + #ifdef __MIPSEL__ + #define HGL_CPU HGL_CPU_MIPSel + #define HGL_CPU_NAME OS_TEXT("MIPSel") + #define HGL_LIB_CPU_NAME OS_TEXT("MIPSel") + #define HGL_ENDIAN HGL_LITTLE_ENDIAN + #else + #define HGL_CPU HGL_CPU_MIPS + #define HGL_CPU_NAME OS_TEXT("MIPS") + #define HGL_LIB_CPU_NAME OS_TEXT("MIPS") + #define HGL_ENDIAN HGL_BIG_ENDIAN + #endif//__MIPSEL__ +#elif defined(__mips64__)||defined(mips64) + #define HGL_MIN_MEMORY_ALLOC_BYTES 8 + #define HGL_CPU HGL_CPU_MIPS64 + #define HGL_CPU_NAME OS_TEXT("MIPS64") + #define HGL_LIB_CPU_NAME OS_TEXT("MIPS64") + #define HGL_ENDIAN HGL_BIG_ENDIAN +#elif defined(__powerpc__) || defined(__powerpc) \ + ||defined(__POWERPC__) \ + || defined(__ppc__) || defined(__PPC__) || defined(__ppc) \ + || defined(_M_PPC) ||defined(_M_MPPC) \ + || defined(_ARCH_PPC) || defined(_ARCH_PWR) + #ifdef __PPU__ + #define HGL_CPU HGL_CPU_Cell + #define HGL_CPU_NAME OS_TEXT("Cell") + #define HGL_LIB_CPU_NAME OS_TEXT("Cell") + #else + #ifdef defined(__ppc64__)||defined(__PPC64__)||defined(__powerpc64__) \ + ||defined(_ARCH_PPC64)||defined(__64BIT__) + #define HGL_CPU HGL_CPU_PowerPC64 + #define HGL_CPU_NAME OS_TEXT("PowerPC64") + #define HGL_LIB_CPU_NAME OS_TEXT("PowerPC64") + #else + #define HGL_CPU HGL_CPU_PowerPC + #define HGL_CPU_NAME OS_TEXT("PowerPC") + #define HGL_LIB_CPU_NAME OS_TEXT("PowerPC") + #endif//PowerPC64 + #endif + + #define HGL_MIN_MEMORY_ALLOC_BYTES 8 + #define HGL_ENDIAN HGL_BIG_ENDIAN +#elif defined(__arm__)||defined(__arm) \ + ||defined(_ARM) \ + ||defined(_M_ARM) \ + ||defined(__ARM_ARCH__7__) \ + ||defined(__ARM_ARCH__7A__) \ + ||defined(__ARM_ARCH__7R__) \ + ||defined(__ARM_ARCH__7M__) \ + ||defined(__ARM_ARCH__7S__) + #define HGL_CPU HGL_CPU_ARM7 + #define HGL_CPU_NAME OS_TEXT("ARM7") + #define HGL_LIB_CPU_NAME OS_TEXT("ARM7") + #define HGL_MIN_MEMORY_ALLOC_BYTES 4 + #define HGL_ENDIAN HGL_LITTLE_ENDIAN +#elif defined(__aarch64__) + #define HGL_CPU HGL_CPU_ARM64 + #define HGL_CPU_NAME OS_TEXT("ARM64") + #define HGL_LIB_CPU_NAME OS_TEXT("ARM64") + #define HGL_MIN_MEMORY_ALLOC_BYTES 4 + #define HGL_ENDIAN HGL_LITTLE_ENDIAN +#elif defined(__wasm__) + + #error Not support WebAssembly.please wait update...... + + #define HGL_OS HGL_OS_Wasm + #define HGL_COMPILER HGL_COMPILER_LLVM +#else + #error Not support the cpu. +#endif + +#if HGL_ENDIAN == HGL_BIG_ENDIAN + #define HGL_CPU_ENDIAN OS_TEXT("Big Endian") +#else + #define HGL_CPU_ENDIAN OS_TEXT("Little Endian") +#endif//HGL_ENDIAN == HGL_BIG_ENDIAN + +#if defined(__WIN32__)||defined(_WIN32)||defined(WIN32)||defined(__WINDOWS__)||defined(__WIN64__)||defined(_WIN64)||defined(WIN64) + #define HGL_OS HGL_OS_Windows +#elif defined(__APPLE__)||defined(__MAC__)||defined(macintosh)||defined(__APPLE_CC__) + + #define HGL_OS_BSD 1 + + #include "TargetConditionals.h" + #if TARGET_OS_IPHONE + #if TARGET_IPHONE_SIMULATOR + #define HGL_OS HGL_OS_iOS_Simulator + #else + #define HGL_OS HGL_OS_iOS + #endif//TARGET_IPHONE_SIMULATOR + #elif TARGET_OS_MAC + #define HGL_OS HGL_OS_macOS + #endif// +#elif defined(__ANDROID__) + #define HGL_OS HGL_OS_Android +#elif defined(__FreeBSD)||defined(__FreeBSD__) + #define HGL_OS HGL_OS_FreeBSD + #define HGL_OS_BSD 1 +#elif defined(__NetBSD)||defined(__NetBSD__) + #define HGL_OS HGL_OS_NetBSD + #define HGL_OS_BSD 1 +#elif defined(__OPENBSD)||defined(__OpenBSD__) + #define HGL_OS HGL_OS_OpenBSD + #define HGL_OS_BSD 1 +#elif defined(__linux__)||defined(__LINUX__)||defined(linux)||defined(__linux) + #define HGL_OS HGL_OS_Linux +#elif defined(__CYGWIN__) + #define HGL_OS HGL_OS_Cygwin +#elif defined(SN_TARGET_PSP2)||defined(__PSV__)||defined(__psv__)||defined(_PSV)||defined(__PSVita__)||defined(__PSVita) + #define HGL_OS HGL_OS_PSP2 +#elif defined(SN_TARGET_ORBIS) + #define HGL_OS HGL_OS_PS4 +#elif defined(_AIX)||defined(__AIX)||defined(__AIX__)||defined(__aix)||defined(__aix__) + #define HGL_OS HGL_OS_AIX +#endif// + +#if defined(__clang__) + #define HGL_COMPILER HGL_COMPILER_LLVM +#elif defined(__INTEL_COMPILER)||defined(__ECL)||defined(__ICL)||defined(__ICC) + #define HGL_COMPILER HGL_COMPILER_Intel +#elif defined(__IBMC__)||defined(__IBMCPP__) + #define HGL_COMPILER HGL_COMPILER_IBM +#elif defined(__DMC__)||defined(__SC__)||defined(__ZTC__) + #define HGL_COMPILER HGL_COMPILER_DigitalMars +#elif defined(_MSC_VER) + #define HGL_COMPILER HGL_COMPILER_Microsoft +#elif defined(__PGI) + #define HGL_COMPILER HGL_COMPILER_PGI +#elif defined(__MINGW32__) + #define HGL_COMPILER HGL_COMPILER_MinGW32 +#elif defined(__GNUC__) + #define HGL_COMPILER HGL_COMPILER_GNU +#else + #error Can not support the Compiler. +#endif// + +#if defined(SetEventCall)||defined(SafeCallEvent)||defined(CallEvent)||defined(DefEvent) + #error SetEventCall,SafeCallEvent,CallEvent,DefEvent 其中之一已经定义 +#endif// + +#if defined(Property)||defined(PropertyRead)||defined(PropertyWrite) + #error Property,PropertyRead,PropertyWrite 其中之一已经定义 +#endif// + +// #ifndef UNICODE +// #define UNICODE //定义使用UNICODE编码 +// #endif//UNICODE + +#if HGL_OS == HGL_OS_Windows + + #include + + #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/SystemInfo.h b/inc/hgl/platform/SystemInfo.h new file mode 100644 index 0000000..ee72268 --- /dev/null +++ b/inc/hgl/platform/SystemInfo.h @@ -0,0 +1,69 @@ +#ifndef HGL_SYSTEMINFO_INCLUDE +#define HGL_SYSTEMINFO_INCLUDE + +#include +#include +namespace hgl +{ + /** + * 内存信息结构体 + */ + struct MemInfo ///内存信息结构体 + { + uint64 AvailPhys; ///<有效物理内存 + uint64 TotalPhys; ///<总共物理内存 + + uint64 AvailPageFile; ///<有效页面文件 + uint64 TotalPageFile; ///<总共页面文件 + + uint64 AvailVirtual; ///<有效虚拟内存 + uint64 TotalVirtual; ///<总计虚拟内存 + + public: + + MemInfo(); + };//struct MemInfo + + /** + * 操作系统及引擎相关路径 + */ + struct SystemPath ///操作系统及引擎相关路径 + { + OSString start; ///<当前应用程序起始路径 + + OSString os; ///<操作系统路径 + OSString osfont; ///<操作系统字库路径 + OSString library; ///<操作系统辅助库路径 + + OSString common_data; ///<所有用户共用应用程序数据路径 + OSString local_data; ///<本地应用程序数据路径 + + OSString temp; ///<临时文件路径 + + OSString mydata; ///<当前用户应用程序数据保存路径 + OSString myprogram; ///<“我的程序”路径(Windows下为开始菜单程序路径,Mac下为应用程序路径) + OSString mydesktop; ///<“桌面”路径 + + OSString desktop; ///<所有用户桌面路径 + + OSString engine; ///<引擎所在路径 + OSString plug_ins; ///<引擎插件路径 + };//struct SystemPath + + /** + * 系统信息 + */ + struct SystemInfo ///系统信息结构 + { + MemInfo mem; ///<内存信息 + + u16char os_name[256]; ///<操作系统全名 + + SystemPath path; ///<系统相关路径 + + public: + + SystemInfo(); + };//struct SystemInfo +}//namespace hgl +#endif//HGL_SYSTEMINFO_INCLUDE diff --git a/inc/hgl/platform/compiler/DataTypeGNU.h b/inc/hgl/platform/compiler/DataTypeGNU.h new file mode 100644 index 0000000..18b403a --- /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 0000000..2af4d18 --- /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 0000000..a2a23d1 --- /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 0000000..7574ec1 --- /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 0000000..e15facd --- /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 0000000..bc0e05b --- /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 0000000..e8cd7c6 --- /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 0000000..028e0ed --- /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 0000000..e72e3b9 --- /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 0000000..ad87165 --- /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 0000000..6bf3aef --- /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 0000000..ede3759 --- /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 0000000..997e0bd --- /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 0000000..15a8476 --- /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 0000000..65842a4 --- /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/proc/Fifo.h b/inc/hgl/proc/Fifo.h new file mode 100644 index 0000000..fc45564 --- /dev/null +++ b/inc/hgl/proc/Fifo.h @@ -0,0 +1,29 @@ +#ifndef HGL_MULTI_PROC_FIFO_INCLUDE +#define HGL_MULTI_PROC_FIFO_INCLUDE + +#include +namespace hgl +{ + /** + * 命名管道通信 + */ + class Fifo ///命名管道通信 + { + public: + + char filename[HGL_MAX_PATH]; + + int fd; + + public: + + Fifo() + { + *filename=0; + fd=-1; + } + + bool Create(const char *); ///<创建一个管道通信文件(注:只需要文件名,不需要完整路径) + };//namespace hgl +}//namespace hgl +#endif//HGL_MULTI_PROC_FIFO_INCLUDE diff --git a/inc/hgl/proc/FifoInputStream.h b/inc/hgl/proc/FifoInputStream.h new file mode 100644 index 0000000..59e16ac --- /dev/null +++ b/inc/hgl/proc/FifoInputStream.h @@ -0,0 +1,35 @@ +#ifndef HGL_MULTI_PROC_FIFO_INPUT_STREAM_INCLUDE +#define HGL_MULTI_PROC_FIFO_INPUT_STREAM_INCLUDE + +#include +#include + +namespace hgl +{ + namespace io + { + /** + * 命名管道输入流 + */ + class FifoInputStream:public InputStream + { + Fifo *f; + + public: + + FifoInputStream(Fifo *_f) + { + f=_f; + } + + virtual ~FifoInputStream() + { + if(f) + delete f; + } + + + };//class FifoInputStream + }//namespace io +}//namespace hgl +#endif//HGL_MULTI_PROC_FIFO_INPUT_STREAM_INCLUDE diff --git a/inc/hgl/proc/Pipe.h b/inc/hgl/proc/Pipe.h new file mode 100644 index 0000000..42f2afd --- /dev/null +++ b/inc/hgl/proc/Pipe.h @@ -0,0 +1,24 @@ +#ifndef HGL_MULTI_PROC_PIPE_INCLUDE +#define HGL_MULTI_PROC_PIPE_INCLUDE + +#include + +#if HGL_OS==HGL_OS_Windows +#include +#endif// + +namespace hgl +{ + #if HGL_OS==HGL_OS_Windows + using pipe_ptr=HANDLE; + constexpr pipe_ptr PIPE_NULL=nullptr; + #else + using pipe_ptr=int; + constexpr pipe_ptr PIPE_NULL=-1; + #endif// + + using pipe_pair=pipe_ptr[2]; + + bool CreatePipe(pipe_pair &); ///<创建一对通信管道 +}//namespace hgl +#endif//HGL_MULTI_PROC_PIPE_INCLUDE diff --git a/inc/hgl/proc/Proc.h b/inc/hgl/proc/Proc.h new file mode 100644 index 0000000..4663d2f --- /dev/null +++ b/inc/hgl/proc/Proc.h @@ -0,0 +1,41 @@ +#ifndef HGL_PROCESS_INCLUDE +#define HGL_PROCESS_INCLUDE + +#include +namespace hgl +{ + /** + * 进程管理类 + */ + class Process ///进程管理类 + { + OSString work_path; + OSString filename; + StringList args; + + int pid; + + public: + + Process() + { + pid=-1; + } + + virtual ~Process() + { + } + + bool SetWorkPath(const OSString &wp); ///<设置工作目录 + bool SetExecFile(const OSString &ef); ///<设置执行文件 + void AddArgv(const OSString &argv){if(!argv.IsEmpty())args.Add(argv);} ///<增加一个参数 + void ClearArgs(){args.Clear();} ///<清除所有参数 + + bool Execute(); ///<执行程序 + + bool Wait(); ///<等待子进程暂停或是终止 + bool Kill(); ///<杀掉子进程 + bool RequestTerminate(); ///<请求子进程终止 + };//class Process +}//namespace hgl +#endif//HGL_PROCESS_INCLUDE diff --git a/inc/hgl/proc/ProcMutex.h b/inc/hgl/proc/ProcMutex.h new file mode 100644 index 0000000..e24bcbb --- /dev/null +++ b/inc/hgl/proc/ProcMutex.h @@ -0,0 +1,37 @@ +#ifndef HGL_PROCESS_MUTEX_INCLUDE +#define HGL_PROCESS_MUTEX_INCLUDE + +#include + +#if HGL_OS!=HGL_OS_Windows + #include +#endif//HGL_OS!=HGL_OS_Windows + +namespace hgl +{ + /** + * 进程排斥 + */ + class ProcMutex ///进程排斥 + { +#if HGL_OS==HGL_OS_Windows + void *lock; +#else + sem_t *lock; +#endif//HGL_OS==HGL_OS_Windows + + public: + + ProcMutex(); + ~ProcMutex(){Clear();} + + bool Create(const os_char *); ///<创建进程排斥 + void Clear(); ///<清除进程排斥 + + bool Lock(); ///<锁定 + bool TryLock(); ///<尝试锁定 + + bool Unlock(); ///<解锁 + };//class ProcMutex +}//namespace hgl +#endif//HGL_PROCESS_MUTEX_INCLUDE diff --git a/inc/hgl/thread/ASyncEvent.h b/inc/hgl/thread/ASyncEvent.h new file mode 100644 index 0000000..eacb2f6 --- /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 0000000..abad088 --- /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 0000000..0cfa6a2 --- /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 0000000..f4f1a93 --- /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 0000000..188c545 --- /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 0000000..3128a8e --- /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 0000000..b5365be --- /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 0000000..6f9f8c4 --- /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 0000000..569748c --- /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 0000000..4465f66 --- /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 0000000..ae6ca3f --- /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 0000000..7e5a0f7 --- /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 0000000..921f596 --- /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 0000000..e8a07cc --- /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 0000000..9773db8 --- /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 ///排斥访问类(仅当前进程) + { + hgl_thread_mutex ptr; + + public: + + ThreadMutex(); ///<本类构造函数 + virtual ~ThreadMutex(); ///<本类析构函数 + + hgl_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 0000000..14d038a --- /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 0000000..db1a552 --- /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 0000000..1664a64 --- /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 0000000..7360cc4 --- /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 0000000..758db60 --- /dev/null +++ b/inc/hgl/type/BaseString.h @@ -0,0 +1,1207 @@ +#ifndef HGL_TYPE_BASE_STRING_INCLUDE +#define HGL_TYPE_BASE_STRING_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/Color.h b/inc/hgl/type/Color.h new file mode 100644 index 0000000..e1bd0c5 --- /dev/null +++ b/inc/hgl/type/Color.h @@ -0,0 +1,244 @@ +#ifndef HGL_COLOR_TABLE_INCLUDE +#define HGL_COLOR_TABLE_INCLUDE + +#include +namespace hgl +{ + /** + * 颜色数据定义 + */ + struct COLOR_DEF ///颜色数据定义 + { + int red,green,blue; ///<三原色 + int yum; ///<亮度 + + float r,g,b; ///<三原色浮点值 + float y; ///<亮度浮点值 + + char eng_name[32]; ///<英文名称 + u16char chs_name[16]; ///<中文名称 + }; + + /** + * 颜色枚举 + */ + enum COLOR_ENUM ///颜色枚举 + { + ceNone, + + ceAliceBlue, ///<艾利斯兰 + ceAndroidGreen, ///<安卓绿 + ceAntiqueWhite, ///<古董白 + ceAppleGreen, ///<苹果绿 + ceAqua, ///<浅绿色 + ceAquaMarine, ///<碧绿色 + + ceArdenRed, ///<雅顿红(注:商业使用需获得Elizabeth Arden公司授权) + + ceAzure, ///<天蓝色 + ceBananaMania, ///<香蕉黄(芯) + ceBananaYellow, ///<香蕉黄(皮) + ceBeige, ///<米色 + ceBisque, ///<桔黄色 + ceBlack, ///<黑色 + ceBlanchedAlmond, ///<白杏色 + ceBlue, ///<蓝色 + ceBlueViolet, ///<紫罗兰色 + ceBrown, ///<褐色 + ceBurlyWood, ///<实木色 + ceCadetBlue, ///<军兰色 + ceCaribbeanGreen, ///<加勒比海绿 + ceChartreuse, ///<黄绿色 + ceCherryBlossomPink, ///<樱桃花粉 + ceChocolate, ///<巧克力色 + ceCoral, ///<珊瑚色 + ceCornflowerBlue, ///<菊花兰 + ceCornsilk, ///<米绸色 + ceCrimson, ///<暗深红 + ceCyan, ///<青色 + ceDarkBlue, ///<暗蓝色 + ceDarkCyan, ///<暗青色 + ceDarkGoldenrod, ///<暗金黄 + ceDarkGray, ///<暗灰色 + ceDarkGreen, ///<暗绿色 + ceDarkGrey, ///<暗白色 + ceDarkKhaki, ///<暗黄褐色 + ceDarkMagenta, ///<暗洋红 + ceDarkOliveGreen, ///<暗橄榄绿 + ceDarkOrange, ///<暗桔黄 + ceDarkOrchid, ///<暗紫色 + ceDarkRed, ///<暗红色 + ceDarkSalmon, ///<暗肉色 + ceDarkSeaGreen, ///<暗海兰 + ceDarkSlateBlue, ///<暗灰兰 + ceDarkSlateGray, ///<墨绿色 + ceDarkSlateGrey, ///<暗灰绿 + ceDarkTurquoise, ///<暗宝石绿 + ceDarkViolet, ///<暗紫罗兰 + ceDeepPink, ///<深粉红 + ceDeepSkyBlue, ///<深天蓝 + ceDimGray, ///<暗灰色 + ceDimGrey, ///<暗灰白 + ceDodgerBlue, ///<闪兰色 + ceFireBrick, ///<火砖色 + ceFloralWhite, ///<花白色 + ceForestGreen, ///<森林绿 + ceFrenchBeige, ///<法国米色 + ceFrenchBlue, ///<法国兰 + ceFrenchLilac, ///<法国丁香色 + ceFuchsia, ///<紫红色 + ceGainsboro, ///<淡灰色 + ceGhostWhite, ///<幽灵白 + ceGold, ///<金色 + ceGoldenrod, ///<金麒麟色 + ceGoldenYellow, ///<金黄 + ceGray, ///<灰色 + ceGreen, ///<绿色 + ceGreenYellow, ///<蓝绿色 + ceGrey, ///<灰白色 + ceHollywoodCerise, ///<好莱坞樱桃红 + ceHoneydew, ///<蜜色 + ceHotPink, ///<火热粉 + ceHunterGreen, ///<猎人绿 + ceIndianGreen, ///<印度绿 + ceIndianRed, ///<印度红 + ceIndianYellow, ///<印度黄 + ceIndigo, ///<靛青色 + ceIvory, ///<象牙白 + ceKhaki, ///<黄褐色 + ceLavender, ///<淡紫色 + ceLavenderBlush, ///<淡紫红 + ceLawnGreen, ///<草绿色 + ceLemon, ///<柠檬色 + ceLemonYellow, ///<柠檬黄 + ceLemonChiffon, ///<柠檬绸 + ceLightBlue, ///<亮蓝色 + ceLightCoral, ///<亮珊瑚色 + ceLightCyan, ///<亮青色 + ceLightGoldenrodYellow, ///<亮金黄 + ceLightGray, ///<亮灰色 + ceLightGreen, ///<亮绿色 + ceLightGrey, ///<亮灰白 + ceLightPink, ///<亮粉红 + ceLightSalmon, ///<亮肉色 + ceLightSeaGreen, ///<亮海蓝 + ceLightSkyBlue, ///<亮天蓝 + ceLightSlateGray, ///<亮蓝灰 + ceLightSlateGrey, ///<亮蓝白 + ceLightSteelBlue, ///<亮钢兰 + ceLightYellow, ///<亮黄色 + ceLime, ///<酸橙色 + ceLimeGreen, ///<橙绿色 + ceLinen, ///<亚麻色 + ceLion, ///<獅子棕 + ceMagenta, ///<红紫色 + ceMaroon, ///<粟色 + ceMediumAquamarine, ///<间绿色 + ceMediumBlue, ///<间兰色 + ceMediumOrchid, ///<间淡紫 + ceMediumPurple, ///<间紫色 + ceMediumSeaGreen, ///<间海蓝 + ceMediumSlateBlue, ///<间暗蓝 + ceMediumSpringGreen, ///<间春绿 + ceMediumTurquoise, ///<间绿宝石 + ceMediumVioletRed, ///<间紫罗兰 + ceMidNightBlue, ///<中灰蓝 + ceMint, ///<薄荷色 + ceMintCream, ///<薄荷霜 + ceMintGreen, ///<薄荷绿 + ceMistyRose, ///<浅玫瑰 + ceMoccasin, ///<鹿皮色 + + ceMozillaBlue, /// +namespace hgl +{ + /** + * r,g,b三原色类 + */ + class Color3f ///RGB三原色类 + { + void Clamp(); + + public: + + float r,g,b; ///1)One();else{r=g=b=v;}} ///<设置颜色 + + void To(float,float,float,float); ///<转换到另一颜色 + void To(const float *rgb,float v){To(*rgb,*(rgb+1),*(rgb+2),v);} ///<转换到另一颜色 + void To(Color3f &c,float v){To(c.r,c.g,c.b,v);} ///<转换到另一颜色 + + void Black(){r=0,g=0,b=0;} ///<黑色 + void White(){r=1,g=1,b=1;} ///<白色 + + void Red(){r=1,g=0,b=0;} ///<红色 + void Green(){r=0,g=1,b=0;} ///<绿色 + void Blue(){r=0,g=0,b=1;} ///<蓝色 + + void Yellow(){r=1,g=1,b=0;} ///<黄色 + void Purple(){r=1,g=0,b=1;} ///<紫色 + + void Grey(float v){r=v,g=v,b=v;Clamp();} ///<灰色 + void Grey(float,float,float); ///<指彩色变成灰色 + void Grey(); ///<将当前色彩变成灰色 + + //操作符重载 + void operator = (const float *v){r=*v++;g=*v++;b=*v;} + void operator = (COLOR_ENUM ce){Use(ce);} + + bool operator == (const Color3f &); + bool operator != (const Color3f &); + + void operator += (const Color3f &v){r+=v.r;g+=v.g;b+=v.b;Clamp();} + void operator -= (const Color3f &v){r-=v.r;g-=v.g;b-=v.b;Clamp();} + void operator *= (const Color3f &v){r*=v.r;g*=v.g;b*=v.b;Clamp();} + void operator /= (const Color3f &v){r/=v.r;g/=v.g;b/=v.b;Clamp();} + + void operator *= (float v){r*=v;g*=v;b*=v;Clamp();} + void operator /= (float v){r/=v;g/=v;b/=v;Clamp();} + + Color3f operator + (const Color3f &v){return(Color3f(r+v.r,g+v.g,b+v.b));} + Color3f operator - (const Color3f &v){return(Color3f(r-v.r,g-v.g,b-v.b));} + Color3f operator * (const Color3f &v){return(Color3f(r*v.r,g*v.g,b*v.b));} + Color3f operator / (const Color3f &v){return(Color3f(r/v.r,g/v.g,b/v.b));} + + Color3f operator * (float v){return(Color3f(r*v,g*v,b*v));} + Color3f operator / (float v){return(Color3f(r/v,g/v,b/v));} + + operator float *() const {return((float *)this);} //使得本类可以直接当做float *使用 + operator const float *() const {return((const float *)this);} //使得本类可以直接当做const float *使用 + };//class Color3f + + const Color3f BlackColor3f(0,0,0); + const Color3f WhiteColor3f(1,1,1); + const Color3f RedColor3f(1,1,0); + const Color3f GreenColor3f(0,1,0); + const Color3f BlueColor3f(0,0,1); + const Color3f YellowColor3f(1,1,0); + + #define DEF_RGB_U8_TO_COLOR3F(r,g,b) Color3f(float(r)/255.0f,float(g)/255.0f,float(b)/255.0f) +}//namespace hgl +#endif//HGL_COLOR_3_FLOAT_INCLUDE diff --git a/inc/hgl/type/Color4f.h b/inc/hgl/type/Color4f.h new file mode 100644 index 0000000..97d6c4c --- /dev/null +++ b/inc/hgl/type/Color4f.h @@ -0,0 +1,100 @@ +#ifndef HGL_COLOR_4_FLOAT_INCLUDE +#define HGL_COLOR_4_FLOAT_INCLUDE + +#include +namespace hgl +{ + #define HGL_FLOAT_TO_U32(c1,c2,c3,c4) uint32( \ + (uint8(c1 * 255) << 24 ) | \ + (uint8(c2 * 255) << 16 ) | \ + (uint8(c3 * 255) << 8 ) | \ + (uint8(c4 * 255) ) ) + + #define HGL_FLOAT_TO_RGBA8(r,g,b,a) HGL_FLOAT_TO_U32(r,g,b,a) + #define HGL_FLOAT_TO_BGRA8(r,g,b,a) HGL_FLOAT_TO_U32(b,g,r,a) + #define HGL_FLOAT_TO_ARGB8(r,g,b,a) HGL_FLOAT_TO_U32(a,r,g,b) + #define HGL_FLOAT_TO_ABGR8(r,g,b,a) HGL_FLOAT_TO_U32(a,b,g,r) + + /** + * r,g,b,a四原色类 + */ + class Color4f ///RGBA四原色类 + { + void Clamp(); + + public: + + float r,g,b,a; ///1)One();else{r=v;g=v;b=v;}} ///<设置颜色 + + void To(float,float,float,float); ///<转换到另一颜色 + void To(const Color4f &c,float v){To(c.r,c.g,c.b,v);} ///<转换到另一颜色 + void To(const Color3f &c,float v){To(c.r,c.g,c.b,v);} ///<转换到另一颜色 + + uint32 ToRGBA8()const{ return HGL_FLOAT_TO_RGBA8(r, g, b, a); } ///<输出一个rgba8格式的颜色数据 + uint32 ToBGRA8()const{ return HGL_FLOAT_TO_BGRA8(r, g, b, a); } ///<输出一个bgra8格式的颜色数据 + uint32 ToARGB8()const{ return HGL_FLOAT_TO_ARGB8(r, g, b, a); } ///<输出一个argb8格式的颜色数据 + uint32 ToABGR8()const{ return HGL_FLOAT_TO_ABGR8(r, g, b, a); } ///<输出一个abgr8格式的颜色数据 + + void Grey(); ///<将当前色彩变成灰色 + + //操作符重载 + void operator = (const float *v){r=*v++;g=*v++;b=*v++;a=*v;} + void operator = (const Color3f &v){r=v.r;g=v.g;b=v.b;a=1;} + void operator = (const Color4f &v){r=v.r;g=v.g;b=v.b;a=v.a;} + void operator = (COLOR_ENUM ce){Use(ce,a);} + + bool operator == (const Color4f &); + bool operator != (const Color4f &); + + void operator += (const Color4f &v){r+=v.r;g+=v.g;b+=v.b;a+=v.a;Clamp();} + void operator -= (const Color4f &v){r-=v.r;g-=v.g;b-=v.b;a-=v.a;Clamp();} + void operator *= (const Color4f &v){r*=v.r;g*=v.g;b*=v.b;a*=v.a;Clamp();} + void operator /= (const Color4f &v){r/=v.r;g/=v.g;b/=v.b;a/=v.a;Clamp();} + + void operator += (const Color3f &v){r+=v.r;g+=v.g;b+=v.b;Clamp();} + void operator -= (const Color3f &v){r-=v.r;g-=v.g;b-=v.b;Clamp();} + void operator *= (const Color3f &v){r*=v.r;g*=v.g;b*=v.b;Clamp();} + void operator /= (const Color3f &v){r/=v.r;g/=v.g;b/=v.b;Clamp();} + + void operator *= (float v){r*=v;g*=v;b*=v;a*=v;Clamp();} + void operator /= (float v){r/=v;g/=v;b/=v;a/=v;Clamp();} + + Color4f operator + (const Color4f &v){return(Color4f(r+v.r,g+v.g,b+v.b,a+v.a));} + Color4f operator - (const Color4f &v){return(Color4f(r-v.r,g-v.g,b-v.b,a-v.a));} + Color4f operator * (const Color4f &v){return(Color4f(r*v.r,g*v.g,b*v.b,a*v.a));} + Color4f operator / (const Color4f &v){return(Color4f(r/v.r,g/v.g,b/v.b,a/v.a));} + + Color4f operator * (float v){return(Color4f(r*v,g*v,b*v,a*v));} + Color4f operator / (float v){return(Color4f(r/v,g/v,b/v,a/v));} + + operator float *() const {return((float *)this);} //使得本类可以直接当做float *使用 + operator const float *() const {return((const float *)this);} //使得本类可以直接当做const float *使用 + };//class Color4f + + #define DEF_RGBA_U8_TO_COLOR4F(r,g,b,a) Color4f(float(r)/255.0f,float(g)/255.0f,float(b)/255.0f,float(a)/255.0f) +}//namespace hgl +#endif//HGL_COLOR_4_FLOAT_INCLUDE diff --git a/inc/hgl/type/DataType.h b/inc/hgl/type/DataType.h new file mode 100644 index 0000000..2b5b23b --- /dev/null +++ b/inc/hgl/type/DataType.h @@ -0,0 +1,12 @@ +#ifndef HGL_DATATYPE_INCLUDE +#define HGL_DATATYPE_INCLUDE + +#include // 平台定义 +#include // 常用宏定义 +#include // 智能指针 +#include // 字符与简单字符处理 +#include // 常用数值宏及内联函数 +#include // 编码序定义 +#include // 比较操作符实现定义 + +#endif//HGL_DATATYPE_INCLUDE diff --git a/inc/hgl/type/DateTime.h b/inc/hgl/type/DateTime.h new file mode 100644 index 0000000..d72de60 --- /dev/null +++ b/inc/hgl/type/DateTime.h @@ -0,0 +1,178 @@ +#ifndef HGL_DATETIME_INCLUDE +#define HGL_DATETIME_INCLUDE + +#include +#include + +namespace hgl +{ + namespace io + { + class DataInputStream; + class DataOutputStream; + }//namespace io + + /** + * 时间类,这个类用来保存和计算时间。 + * + * 当您对Hours,Minutes,Seconds中任何一个值进行加减时,其它值都会自动计算。如:11:30这个值,使用Minutes+=55。会自动计算出55分钟后的时间,值为12:25 + */ + class Time ///时间类 + { + int32 gmt_off; ///<当前时区与UTC时间的差值 + + int8 hours; + int8 minutes; + int8 seconds; + int32 micro_seconds; + int8 week_day; ///<为了取这个星期过了多少秒用的 + + public: + + int GetGMT ()const{return gmt_off;} ///<取得当前时间与UTC时间的时差 + + int GetHour ()const{return hours;} ///<时 + int GetMinute ()const{return minutes;} ///<分 + int GetSecond ()const{return seconds;} ///<秒 + int GetMicroSecond ()const{return micro_seconds;} ///<微秒(百万分之一秒) + + int GetDaySeconds ()const{return (hours*HGL_TIME_ONE_HOUR)+(minutes*HGL_TIME_ONE_MINUTE)+seconds;} ///<今天过了多少秒 + + int GetWeekSeconds ()const ///<这个星期过了多少秒 + { + int week = week_day; + if(week_day > 0) + --week; + + if(week_day == 0) + week=(HGL_DAY_ONE_WEEK-1); + + return ((week*HGL_HOUR_ONE_DAY+hours)*HGL_TIME_ONE_HOUR)+(minutes*HGL_TIME_ONE_MINUTE)+seconds; + } + +// int GetPastWeekSeconds()const{return int(GetDoubleTime()-GetWeekSeconds());} ///<过去那些年到这周一0点过了多少秒 + + void SetGMT(int go){gmt_off=go;} + void SetHour(int); + void SetMinute(int); + void SetSecond(int); + void SetMicroSecond(int); + + public: + + Time(); + Time(const double); + Time(int,int,int,int); + Time(const Time &); + + void Clear() + { + gmt_off=0; + hours=0; + minutes=0; + seconds=0; + micro_seconds=0; + week_day=0; + } + + void Set(int h,int m=0,int s=0,int ms=0,int wd=0); + + Time &operator = (const Time &); + + const int Comp(const Time &)const; + + CompOperator(const Time &,Comp); + + void Sync(const double=0); ///<和系统时间同步 + + bool SaveToStream(io::DataOutputStream *) const; + bool LoadFromStream(io::DataInputStream *); + };//class Time + + /** + * 日期类,这个类用来保存和计算日期。带有闰年的处理 + * + * 当您对Year,Month,Day中任意一个值进行修改时,其它值都会自动跟着计算。如1981-4-17,如果使用Day+=400,会自动计算出400天之后的日期,结果是1982-5-21 + */ + class Date ///日期类 + { + int32 year; + int8 month; + int8 day; + + int8 week_day; + int16 year_day; + + int8 max_days_per_month; + + public: + + int GetYear ()const{return year;} ///<年 + int GetMonth ()const{return month;} ///<月 + int GetDay ()const{return day;} ///<日 + int GetMaxDays ()const{return max_days_per_month;} ///<本月天数 + int GetWeekDay ()const{return week_day;} ///<星期,0为星期天 + int GetYearDay ()const{return year_day;} ///<今天为这一年的第几天 + + void SetYear (int y){year=y;} + void SetMonth (int); + void SetDay (int); + + public: + + Date(); + Date(const double); + Date(int,int,int); + Date(const Date &); + + void Clear() + { + year=0; + month=0; + day=0; + + week_day=0; + year_day=0; + + max_days_per_month=0; + } + + void Set(int y,int m,int d,int wd=0,int yd=0); + + Date &operator = (const Date &); + + const int Comp(const Date &)const; + + CompOperator(const Date &,Comp); + + void Sync(const double=0); ///<和系统日期同步 + + bool SaveToStream(io::DataOutputStream *) const; + bool LoadFromStream(io::DataInputStream *); + };//class Date + + /** + * 根据当前时间,转换出Date/Time两个结构 + */ + void ToDateTime(Date &,Time &,const double cur_time=0); + + /** + * 根据日期和时间,转换出以秒为单位的时间值 + * @param year 年 + * @param month 月 + * @param day 日 + * @param hour 小时 + * @param minute 分 + * @param second 秒 + * @param micro_second 微秒(1/1000秒) + * @return 转换出的值 + */ + double FromDateTime(const int year,const int month,const int day, + const int hour,const int minute=0,const int second=0,const int micro_second=0,const int gmt_off=0); + + /** + * 根据Date/Time转换出以秒为单位的时间值 + */ + double FromDateTime(const Date &,const Time &); +}//namespace hgl +#endif//HGL_DATETIME_INCLUDE diff --git a/inc/hgl/type/EnumClass.h b/inc/hgl/type/EnumClass.h new file mode 100644 index 0000000..a5384d1 --- /dev/null +++ b/inc/hgl/type/EnumClass.h @@ -0,0 +1,13 @@ +#ifndef HGL_ENUM_CLASS_INCLUDE +#define HGL_ENUM_CLASS_INCLUDE + +namespace hgl +{ + template class EnumAsUInteger + { + public: + + + };//template class EnumAsUInteger +}//namespace hgl +#endif//HGL_ENUM_CLASS_INCLUDE diff --git a/inc/hgl/type/LRUCache.cpp b/inc/hgl/type/LRUCache.cpp new file mode 100644 index 0000000..74e969b --- /dev/null +++ b/inc/hgl/type/LRUCache.cpp @@ -0,0 +1,354 @@ +#ifndef HGL_TYPE_LRU_CACHE_CPP +#define HGL_TYPE_LRU_CACHE_CPP + +#include +namespace hgl +{ + /** + * 本类构造函数 + * @param value 缓冲区最大数据量 + */ + template + LRUCache::LRUCache(int value) + { + if(value<=0) + { + LOG_ERROR(OS_TEXT("ActiveChain缓冲区大小被设置<=0")); + + value=3; + } + + count=0; + max_count=value; + + start_item=nullptr; + end_item=nullptr; + } + + template + LRUCache::~LRUCache() + { + Clear(); + } + + template + void LRUCache::SetMaxCount(int value) + { + if(value<=0) + { + LOG_ERROR(OS_TEXT("ActiveChain缓冲区大小被设置<=0,此次设置无效!")); + } + else + max_count=value; + } + + template + bool LRUCache::Create(const F &,T &) + { + return true; + } + + template + void LRUCache::Clear(const F &,T &) + { + } + + template + void LRUCache::ClearEnd() + { + LruItem *temp=end_item->prev; + + Clear(end_item->key,end_item->value); + + delete end_item; + + end_item=temp; + + if(end_item) //如果只有一个数据,end_item会为NULL + end_item->next=nullptr; + else + { + #ifdef _DEBUG + if(count!=1) + { + LOG_ERROR(OS_TEXT("ActiveChain出错,end_item=nullptr,count!=1")); + } + #endif// + start_item=nullptr; //如果end_item为空,start_item也应该为空 + } + + count--; + } + + /** + * 添加一个数据 + * @param key 数据标识 + * @param value 数据 + */ + template + LRUCacheItem *LRUCache::Add(const F &key,const T &value) + { + LruItem *temp; + + while(count>=max_count)ClearEnd(); //满了,清除超出的数据 + + temp=new LruItem; + temp->key=key; + temp->value=value; + + temp->prev=nullptr; + temp->next=start_item; + + if(start_item) //如果还没有数据,start会为NULL + start_item->prev=temp; + + start_item=temp; //将当前数据设成start_item + + count++; + + if(!end_item) + { + #ifdef _DEBUG //理由上end_item为NULL时应该是没有数据 + if(count!=1) + { + LOG_ERROR(OS_TEXT("ActiveChain出错,end_item=nullptr,count!=1")); + } + else + #endif//_DEBUG + end_item=start_item; + } + + return(temp); + } + + template + void LRUCache::MoveToStart(LruItem *item) + { + if(item==start_item) + return; + //不是首节点,这个情况下count肯定>1 + if(item!=end_item) //也不是尾节点,这个情况下count肯定>2 + { + if(item->next) + item->next->prev=item->prev; + + if(item->prev) + item->prev->next=item->next; + + start_item->prev=item; + + item->prev=nullptr; + item->next=start_item; + + start_item=item; + } + else //为尾节点 + { + end_item=end_item->prev; + end_item->next=nullptr; + + item->prev=nullptr; + item->next=start_item; + + start_item->prev=item; + + start_item=item; + } + } + + /** + * 取得一个数据,在没有数据时,不自动创建数据,返回false + * @param key 数据标识 + * @param value 数据存放地 + * @param mts 是否对数据调频 + * @return 是否取得数据成功 + */ + template + bool LRUCache::Find(const F &key,T &value,bool mts) + { + if(count<=0)return(false); + + int n=count; + LruItem *temp=start_item; + + while(n--) + { + if(temp->key==key) + { + value=temp->value; + + if(mts) + MoveToStart(temp); + + return(true); + } + else + temp=temp->next; + } + + return(false); + } + + /** + * 取得一个数据,如果数据不存在,调用Create创建数据,如失败返回false + * @param key 数据标识 + * @param value 数据存放地 + * @param mts 是否对数据动态调频 + * @return 是否取得数据 true/false + */ + template + bool LRUCache::Get(const F &key,T &value,bool mts) + { + if(Find(key,value,mts)) + return(true); + + while(count>=max_count)ClearEnd(); //满了,清除超出的数据 + + if(Create(key,value)) + { + Add(key,value); + + return(true); + } + + return(false); + } + + /** + * 清数所有数据 + */ + template + void LRUCache::Clear() + { + if(count<=0)return; + + int n=0; + LruItem *temp=start_item; + + while(temp) + { + LruItem *obj=temp; + + Clear(obj->key,obj->value); + + temp=obj->next; + + delete obj; + n++; + } + + if(n!=count) + { + LOG_ERROR(OS_TEXT("LRUCache Count=")+OSString(count)+OS_TEXT(",Clear=")+OSString(n)); + } + + count=0; + start_item=nullptr; + end_item=nullptr; + } + + template + void LRUCache::Delete(LruItem *obj) + { + if(!obj)return; + + Clear(obj->key,obj->value); + + if(count>1) + { + if(obj==start_item) + { + start_item=obj->next; + + start_item->prev=nullptr; + } + else + if(obj==end_item) + { + end_item=obj->prev; + + end_item->next=nullptr; + } + else + { + obj->prev->next=obj->next; + + obj->next->prev=obj->prev; + } + } + else + { + start_item=nullptr; + end_item=nullptr; + } + + delete obj; + + count--; + } + + template + void LRUCache::DeleteByKey(const F &key) + { + if(count<=0)return; + + int n=count; + LruItem *temp=start_item; + + while(n--) + { + if(temp->key==key) + { + Delete(temp); + return; + } + + temp=temp->next; + } + } + + template + void LRUCache::DeleteByValue(T &value) + { + if(count<=0)return; + + int n=count; + LruItem *temp=start_item; + + while(n--) + { + if(temp->value==value) + { + Delete(temp); + return; + } + + temp=temp->next; + } + } + +// template +// bool LRUCache::Update(const F &key,T &value) +// { +// if(Find(key,value,false)) +// { +// LruItem *obj=temp; +// +// Clear(obj->key,obj->value); +// +// Create(obj->key,obj->value); +// +// return(true); +// } +// +// if(Create(key,value)) +// { +// Add(key,value); +// +// return(true); +// } +// +// return(false); +// } +}//namespace hgl +#endif//HGL_TYPE_LRU_CACHE_CPP diff --git a/inc/hgl/type/LRUCache.h b/inc/hgl/type/LRUCache.h new file mode 100644 index 0000000..9167e81 --- /dev/null +++ b/inc/hgl/type/LRUCache.h @@ -0,0 +1,78 @@ +#ifndef HGL_TYPE_LRU_CACHE_INCLUDE +#define HGL_TYPE_LRU_CACHE_INCLUDE + +#include +namespace hgl +{ + template struct LRUCacheItem + { + F key; //识别标识 + + T value; //数据 + + LRUCacheItem *prev, //前一数据 + *next; //后一数据 + };//template struct LRUCacheItem + + /** + * 最近使用数据缓冲区管理模板(当缓冲区满时,将最长时间没有使用的清除)
+ * 现这个模板使用双头链表,每次添加或使用的数据会被移到链表的最前端。
+ * 这样使用率最低的数据会被存在链表的最末端,当缓冲区满时,最末端的数据将会被清除。 + */ + template class LRUCache ///缓冲区管理模板(以最终使用时间为基准) + { + public: + + using LruItem=LRUCacheItem; + + protected: + + LruItem *start_item, //首数据 + *end_item; //尾数据 + + int count,max_count; + + protected: + + virtual bool Create(const F &,T &); ///<创建数据 + virtual void Clear(const F &,T &); ///<清除数据 + + void MoveToStart(LruItem *); ///<移动某一个数据到最前面 + + void Delete(LruItem *); ///<清除某一个数据 + + void ClearEnd(); ///<清除最后一个数据 + + public: + + const int GetCount ()const{return count;} ///<取得当前有多少数据 + const int GetMaxCount ()const{return max_count;} ///<取得最大可以有多少数据 + virtual void SetMaxCount (int); ///<设置最大可以有多少数据 + int GetFreeCount()const{return max_count-count;} ///<取得当前缓冲区剩于量 + + public: + + LRUCache(int); + virtual ~LRUCache(); + + virtual LruItem * Add (const F &,const T &); ///<增加一个数据 + virtual bool Find (const F &,T &,bool=true); ///<取得一个数据(如果没有不会自动创建) + virtual bool Get (const F &,T &,bool=true); ///<取得一个数据(如果没有会自动创建) + void Clear (); ///<清除所有数据 + LruItem * GetEnd (bool mts=true) ///<取最后一项 + { + LruItem *obj=end_item; + + if(mts) + MoveToStart(obj); + + return(obj); + } + + void DeleteByKey(const F &); + void DeleteByValue(T &); +// bool Update (const F &,T &); ///<更新数据 + };//template class LRUCache +}//namespace hgl +#include +#endif//HGL_TYPE_LRU_CACHE_INCLUDE diff --git a/inc/hgl/type/List.cpp b/inc/hgl/type/List.cpp new file mode 100644 index 0000000..72c9ae2 --- /dev/null +++ b/inc/hgl/type/List.cpp @@ -0,0 +1,492 @@ +#ifndef HGL_LIST_CPP +#define HGL_LIST_CPP + +//-------------------------------------------------------------------------------------------------- +// 代码中的部分memcpy可替换为memmove,但这样会引起CodeGuard/Valgrind之类的内存调试器报错 +//-------------------------------------------------------------------------------------------------- +namespace hgl +{ + template + bool List::Get(int index,T &ti)const + { + if(!items||index<0||index>=count) + return(false); + + memcpy(&ti,items+index,sizeof(T)); + return(true); + } + + template + bool List::Begin(T &ti)const + { + if(!items) + return(false); + + memcpy(&ti,items,sizeof(T)); + return(true); + } + + template + bool List::End(T &ti)const + { + if(!items) + return(false); + + memcpy(&ti,items+count-1,sizeof(T)); + return(true); + } + + template + bool List::Rand(T &ti)const + { + if(!items||count<=0) + return(false); + + memcpy(&ti,items+(lrand48()%count),sizeof(T)); + return(true); + } + + template + void List::Set(int index,const T &val) + { + #ifdef _DEBUG + if(!items||index<0||index>=count) + { + LOG_ERROR(OS_TEXT("List<>::Set(index=")+OSString(index)+OS_TEXT(",T &) error,DataCount=")+OSString(count)); + } + else + memcpy(items+index,&val,sizeof(T));//items[index]=val; + #else + if(index>=0&&index + T *List::Add() + { + if(!items) + { + count=1; + max_count=1; + items=hgl_aligned_malloc(1); + + return items; + } + else + { + max_count=power_to_2(count+1); + + items=(T *)hgl_realloc(items,max_count*sizeof(T)); + + ++count; + return(items+(count-1)); + } + } + + /** + * 向列表中添加一个数据对象 + * @param data 要添加的数据对象 + * @return 这个数据的索引号 + */ + template + int List::Add(const T &data) + { + if(!items) + { + count=0; + max_count=1; + items=hgl_aligned_malloc(1); + } + else + { + max_count=power_to_2(count+1); + + items=(T *)hgl_realloc(items,max_count*sizeof(T)); + } + + memcpy(items+count,&data,sizeof(T));//items[count]=data; + return(count++); + } + + /** + * 重复向列表中添加一个数据对象 + * @param data 要添加的数据对象 + * @param n 要添加的数据个数 + * @return 这个数据的索引号 + * @return -1 出错 + */ + template + int List::Add(const T &data,int n) + { + if(n<=0)return(-1); + + if(!items) + { + count=0; + max_count=power_to_2(n); + items=hgl_aligned_malloc(max_count); + } + else + { + max_count=power_to_2(count+n); + + items=(T *)hgl_realloc(items,max_count*sizeof(T)); + } + + T *p=items; + int result=count; + + for(int i=0;i + int List::Add(const T *data,int n) + { + if(!items) + { + count=0; + max_count=power_to_2(n); + + items=hgl_aligned_malloc(max_count); + } + else + { + max_count=power_to_2(count+n); + + items=(T *)hgl_realloc(items,max_count*sizeof(T)); + } + + memcpy(items+count,data,n*sizeof(T)); + + int r=count; + + count+=n; + return(r); + } + + /** + * 清除整个列表 + */ + template + void List::Clear() + { + count=0; + max_count=0; + + if(items) + { + hgl_free(items); + items=0; + } + } + + /** + * 清除整个列表,但不清除缓冲区 + */ + template + void List::ClearData() + { + count=0; + } + + template + void List::DeleteClear() + { + if(count) + { + T *p=items; + + while(count--) + { + delete *p; + ++p; + } + + count=0; + } + } + + /** + * 在列表中查找指定的数据项 + * @param data 要查找的数据项 + * @return 数据在列表中的位置 + */ + template + int List::Find(const T &data)const + { + int n=count; + + while(n--) +// if(items[n]==data)return(n); + if(memcmp(items+n,&data,sizeof(T))==0) + return(n); + + return(-1); + } + + /** + * 删除列表中的指定项,删除后将最后一个数据移到被删除的位置 + * @param index 要删除的数据项的索引值 + * @return 是否成功 + */ + template + bool List::Delete(int index) + { + if(count>0&&index>=0&&index + bool List::DeleteMove(int index) + { + if(count>0&&index>=0&&index + bool List::Delete(int start,int number) + { + if(start>=count)return(false); + + if(start<0) + { + number+=start; + start=0; + } + + if(start+number>count) + number=count-start; + + if(number<=0)return(false); + + count-=number; + + if(start + bool List::DeleteByValue(const T &dat) + { + int index=Find(dat); + + if(index!=-1) + { + Delete(index); + return(true); + } + else + return(false); + } + + /** + * 删除列表中的指定项 + * @param data 要删除的数据项 + * @param n 要删除的数据个数 + */ + template + void List::DeleteByValue(const T *data,int n) + { + while(n--) + { + int index=Find(*data); + + ++data; + + if(index!=-1) + Delete(index); + } + } + + /** + * 交换列表中两个数据的位置 + * @param a 第一个数据的位置 + * @param b 第二个数据的位置 + */ + template + void List::Exchange(int a,int b) + { + //T t; + char t[sizeof(T)]; + +// t=items[a]; + +// items[a]=items[b]; +// items[b]=t; + + memcpy(&t,items+a,sizeof(T)); + memcpy(items+a,items+b,sizeof(T)); + memcpy(items+b,&t,sizeof(T)); + } + + /** + * 在列表的指定位置中插入一个数据 + * @param index 插入数据的位置 + * @param data 要插入的数据 + */ + template + void List::Insert(int index,const T &data) + { + if(index<0)index=0; + + if(index(max_count); + } + else + { + max_count=power_to_2(count+1); + + items=(T *)hgl_realloc(items,max_count*sizeof(T)); + } + + memmove(items+index+1,items+index,(count-index)*sizeof(T)); + + memcpy(items+index,&data,sizeof(T));//items[index]=data; + + ++count; + } + else + Add(data); + } + + /** + * 移动列表中的某一项到新的位置 + * @param index 要移动的数据位置 + * @param newindex 新的位置 + */ + template + void List::Move(int index,int newindex) + { + if(index==newindex)return; + if(index<=0||index>=count)return; + if(newindex<0)newindex=0; + if(newindex>=count)newindex=count-1; + + //T t; + char t[sizeof(T)]; + + memcpy(&t,items+index,sizeof(T));//t=items[index]; + + if(index + void List::PreMalloc(int new_count) + { + if(max_count>=new_count)return; + + max_count=power_to_2(new_count); + + if(!items) + items=hgl_aligned_malloc(max_count); + else + items=(T *)hgl_realloc(items,max_count*sizeof(T)); + } + + template + void List::SetCount(int new_count) + { + if(count==new_count)return; + + if(new_count<=0) + { + ClearData(); + return; + } + + PreMalloc(new_count); + + count=new_count; + } + + /** + * 复制整个列表 + * @param lt 列表 + */ + template + void List::operator = (const List <) + { + if(lt.count<=0) + { + count=0; + return; + } + + SetCount(lt.count); + + memcpy(items,lt.items,count*sizeof(T)); + } + + template + void List::operator = (const std::initializer_list &l) + { + ClearData(); + + SetCount((int)l.size()); + + memcpy(items,l.begin(),count*sizeof(T)); + } +}//namespace hgl +#endif//HGL_LIST_CPP diff --git a/inc/hgl/type/List.h b/inc/hgl/type/List.h new file mode 100644 index 0000000..352c608 --- /dev/null +++ b/inc/hgl/type/List.h @@ -0,0 +1,195 @@ +#ifndef HGL_LIST_INCLUDE +#define HGL_LIST_INCLUDE + +#include +#include +#include + +namespace hgl +{ + /** + * List类用于保存数据列表。可以在列表中添加、删除、查找、访问和排序数据。 + */ + template class List ///列表处理类 + { + protected: + + int count=0; + int max_count=0; + T *items=nullptr; + + public: //属性 + + int GetCount ()const{return count;} ///<取得列表内数据数量 + virtual void SetCount (int); ///<设置列表内数据数量 + virtual void PreMalloc (int); ///<预分配指定数量的数据空间 + T * GetData ()const{return items;} ///<提供原始数据项 + int GetBytes ()const{return count*sizeof(T);} ///<取得原始数据总字节数 + + public: //方法 + + List(){}; ///<本类构造函数 + List(const List <){operator=(lt);} ///<本类构造函数 + List(const std::initializer_list <){operator=(lt);} + + virtual ~List(){Clear();} ///<本类析构函数 + + virtual T * Add(); ///<添加一个空数据 + virtual int Add(const T &); ///<增加一个数据 + virtual int Add(const T &,int n); ///<重复增加一个数据 + virtual int Add(const T *,int n); ///<增加一批数据 + int Add(const List &l){return Add(l.items,l.count);} ///<增加一批数据 + + virtual void Clear(); ///<清除所有数据 + virtual void ClearData(); ///<清除所有数据,但不清空缓冲区 + virtual int Find(const T &)const; ///<查找指定数据的索引 + bool IsExist(const T &flag)const{return Find(flag)!=-1;} ///<确认数据项是否存在 + virtual bool Delete(int); ///<删除指定索引的数据 + virtual bool Delete(int,int); ///<删除指定索引的数据 + virtual bool DeleteMove(int); ///<删除指定索引的数据,将后面紧邻的数据前移 + virtual bool DeleteByValue(const T &); ///<删除一个指定数据 + virtual void DeleteByValue(const T *,int); ///<删除一批指定的数据 + virtual void Exchange(int,int); ///<根据索引交换两个数据 + virtual void Insert(int,const T &); ///<在指定索引处插入一个数据 + virtual void Move(int,int); ///<移动一个数据到移指索引处 + + void DeleteClear(); ///<清除所有数据并全部调用delete + + virtual void operator = (const List &); ///<操作符重载复制一个列表 + virtual void operator = (const std::initializer_list &l); + + virtual void operator += (const T &obj){Add(obj);} ///<操作符重载添加一个数据 + virtual void operator << (const T &obj){Add(obj);} ///<操作符重载添加一个数据 + virtual void operator -= (const T &obj){DeleteByValue(obj);} ///<操作符重载删除一个数据 + + T * GetPointer(const int index) ///<取得指定序列号数据的索引 + { + return(index>=count?nullptr:items+index); + } + + const T * GetPointer(const int index) const ///<取得指定序列号数据的索引 + { + return(index>=count?nullptr:items+index); + } + + bool Get(int,T &)const; ///<取得指定索引处的数据 + void Set(int,const T &); ///<设置指定索引处的数据 + bool Rand(T &)const; ///<随机取得一个数据 + + virtual bool Begin(T &)const; ///<取第一个数据 + virtual bool End(T &)const; ///<取最后一个数据 + + virtual void Enum(void (*enum_func)(T &)) ///<枚举所有数据成员 + { + T *obj=items; + + for(int i=0;i class List + + template T *GetListObject(const List &list,const int index) + { + T *obj; + + if(list.Get(index,obj)) + return(obj); + + return(nullptr); + } +}//namespace hgl + +#include +//-------------------------------------------------------------------------------------------------- +namespace hgl +{ + /** + * 自定义对象列表处理类与标准列表处理类的区别在于它对数据生成/清除时会多调用虚拟函数Create/Delte + */ + template class CusObjectList:public List ///对象列表处理类 + { + public: + + virtual void SetCount(int); + +// virtual T * CreateObject()=0; ///<创建一个数据,但不加入列表 + virtual void DeleteObject(T *)=0; ///<删除一个数据 + + public: + + typedef T *ItemPointer; + + public: //方法 + + CusObjectList(){} + virtual ~CusObjectList(); + + public: + +// virtual T * Append(); ///<追加一个数据 +// virtual T * Insert(int); ///<在指定索引处创建一个数据 + void Insert(int,const ItemPointer &); ///<在指定索引处插入一个数据 + + virtual void Clear(); ///<清除所有数据 + virtual void ClearData(); ///<清除所有数据,但不清空缓冲区 + + virtual bool Unlink(int index){return List::Delete(index);} ///<将指定索引处的数据与列表断开 + virtual bool UnlinkMove(int index){return List::DeleteMove(index);} ///<将指定索引处的数据与列表断开,将前移后面的数据 + virtual bool Unlink(int start,int number){return List::Delete(start,number);} ///<将指定索引处的数据与列表断开 + virtual bool UnlinkByValue(const ItemPointer &ip){return List::DeleteByValue(ip);} ///<将一个指定数据与列表断开 + virtual void UnlinkByValue(const ItemPointer *ip,int n){List::DeleteByValue(ip,n);} ///<将一批指定数据与列表断开 + virtual void UnlinkAll(){List::ClearData();} ///<断开所有数据 + + virtual bool Delete(int); ///<删除指定索引处的数据 + virtual bool DeleteMove(int); ///<删除指定索引处的数据 + virtual bool DeleteByValue(const ItemPointer &); ///<删除指定的一个数据 + virtual void DeleteByValue(const ItemPointer *,int); ///<删除指定的一批数据 + virtual void DeleteAll(); ///<删除所有数据 + + virtual ItemPointer &operator[](int n)const ///<操作符重载取得指定索引处的数据 + { + static T *null_pointer=nullptr; + + if(n<0||n>=this->count) + return(null_pointer); + + return this->items[n]; + } + + virtual void Enum(void (*enum_func)(T *)) ///<枚举所有数据成员 + { + T **obj=this->items; + + for(int i=0;icount;i++) + { + enum_func(*obj); + + ++obj; + } + } + };//template class CusObjectList + + /** + * 对象列表处理类
+ * 将自定义对象列表中的Create重载为new,Delete重载为delete + */ + template class ObjectList:public CusObjectList + { + private: + +// virtual T * CreateObject(){return(new T);} ///<创建一个数据 + virtual void DeleteObject(T *obj){if(obj)delete obj;} ///<删除一个数据 + + public: + + virtual ~ObjectList() + { + CusObjectList::Clear(); + } + };//class ObjectList +}//namespace hgl +#include +#endif//HGL_LIST_INCLUDE diff --git a/inc/hgl/type/Map.cpp b/inc/hgl/type/Map.cpp new file mode 100644 index 0000000..c5894d9 --- /dev/null +++ b/inc/hgl/type/Map.cpp @@ -0,0 +1,582 @@ +#ifndef HGL_MAP_CPP +#define HGL_MAP_CPP + +namespace hgl +{ + /** + * 查找数据是否存在 + * @param flag 数据标识 + * @return 数据所在索引,-1表示不存在 + */ + template + int _Map::Find(const F &flag)const + { + int left=0,right=data_list.GetCount()-1; //使用left,right而不使用min,max是为了让代码能够更好的阅读。 + int mid; + + DataPair **data_array=data_list.GetData(); + + while(left<=right) + { + if(data_array[left ]->left==flag)return(left); + if(data_array[right]->left==flag)return(right); + + mid=(right+left)>>1; + + if(data_array[mid]->left==flag)return(mid); + + if(data_array[mid]->left>flag) + { + ++left; + right=mid-1; + } + else + { + --right; + left=mid+1; + } + } + +// LOG_PROBLEM(OS_TEXT("Map::Find,no result.")); + return(-1); + } + + template + bool _Map::FindPos(const F &flag,int &pos)const + { + int left=0,right=data_list.GetCount()-1; + int mid; + + DataPair **data_array=data_list.GetData(); + + while(left<=right) + { + if(data_array[left ]->left>flag) + { + pos=left; + return(false); + } + else + if(data_array[left ]->left==flag) + { + pos=left; + return(true); + } + + if(data_array[right]->leftleft==flag) + { + pos=right; + return(true); + } + + mid=(right+left)>>1; + + if(data_array[mid]->left==flag) + { + pos=mid; + return(true); + } + + if(data_array[mid]->left>flag) + { + if(data_array[mid-1]->leftleft==flag) + { + pos=mid-1; + return(true); + } + + ++left; + right=mid-1; + } + else + { + if(data_array[mid+1]->left>flag) + { + pos=mid+1; + return(false); + } + else + if(data_array[mid+1]->left==flag) + { + pos=mid+1; + return(true); + } + + --right; + left=mid+1; + } + } + +// LOG_PROBLEM(OS_TEXT("Map::FindPos,no result.")); + pos=-1; + return(false); + } + + template + int _Map::FindByValue(const T &data)const + { + const int count=data_list.GetCount(); + + DataPair **data_array=data_list.GetData(); + + for(int i=0;iright==data) + return(i); + + ++data_array; + } + + return -1; + } + + /** + * 添加一个数据 + * @param flag 数据标识 + * @param data 数据 + * @return 新创建好的数据结构 + */ + template + DataPair *_Map::Add(const F &flag,const T &data) + { + DataPair *ds=data_pool.Acquire(); + + ds->left=flag; + ds->right=data; + + int pos; + + if(FindPos(flag,pos)) + return(nullptr); + + data_list.Insert(pos,ds); + + return(ds); + } + + /** + * 添加一个数据 + * @param flag 数据标识 + * @return 创建好的数据 + */ + template + T &_Map::Add(const F &flag) + { + DataPair *ds=data_pool.Acquire(); + + ds->left=flag; + + int pos; + + FindPos(flag,pos); + + data_list.Insert(pos,ds); + + return ds->right; + } + + /** + * 添加一个数据 + * @param obj 数据 + */ + template + void _Map::Add(DataPair *obj) + { + data_list.Insert(FindPos(obj->left),obj); + } + + /** + * 根据索引取得数据 + * @param flag 数据索引 + * @param data 数据存放处 + * @return 是否取得成功 + */ + template + bool _Map::Get(const F &flag,T &data) const + { + int index=Find(flag); + + DataPair *obj=GetListObject(data_list,index); + + if(!obj) + return(false); + + data=obj->right; + + return(true); + } + + template + bool _Map::Check(const F &key,const T &value) const + { + int index=Find(key); + + DataPair *obj=GetListObject(data_list,index); + + if(!obj) + return(false); + + return (value==obj->right); + } + + /** + * 根据序号取得数据 + * @param index 序号 + * @param f 数据索引存放处 + * @param t 数据存放处 + * @return 是否取得成功 + */ + template + bool _Map::Get(int index,F &f,T &t) const + { + if(index<0||index>=data_list.GetCount())return(false); + + DataPair *ds=data_list[index]; + + f=ds->left; + t=ds->right; + + return(true); + } + + /** + * 根据序号取得索引 + * @param index 序号 + * @param f 数据索引存放处 + * @return 是否取得成功 + */ + template + bool _Map::GetKey(int index,F &f) + { + if(index<0||index>=data_list.GetCount())return(false); + + DataPair *ds=data_list[index]; + + f=ds->left; + + return(true); + } + + /** + * 根据序号取得数据 + * @param index 序号 + * @param t 数据存放处 + * @return 是否取得成功 + */ + template + bool _Map::GetValue(int index,T &t) + { + if(index<0||index>=data_list.GetCount())return(false); + + DataPair *ds=data_list[index]; + + if(!ds)return(false); + + t=ds->right; + + return(true); + } + + /** + * 根据序号设置数据 + * @param index 数据序号 + * @param t 数据 + */ + template + bool _Map::SetValueBySerial(int index,T &t) + { + if(index<0||index>=data_list.GetCount())return(false); + + data_list[index]->right=t; + + return(true); + } + + /** + * 将指定数据从列表中移除同时取得这个数据 + * @param flag 数据标识 + * @param data 数据存放位处 + * @return 是否成功 + */ + template + bool _Map::Delete(const F &flag,T &data) + { + int index=Find(flag); + + DataPair *dp=GetListObject(data_list,index); + + if(!dp) + return(false); + + data=dp->right; + + data_pool.Release(dp); + data_list.DeleteMove(index); + + return(true); + } + + /** + * 根据索引将指定数据从列表中移除 + * @param flag 索引 + * @return 是否成功 + */ + template + bool _Map::DeleteByKey(const F &flag) + { + return DeleteBySerial(Find(flag)); + } + + /** + * 根据索引将指定数据从列表中批量移除 + * @param fp 索引列表 + * @param count 索引数量 + * @return 是否成功 + */ + template + int _Map::DeleteByKey(const F *fp,const int count) + { + if(!fp||count<=0)return(0); + + int total=0; + + for(int i=0;i + bool _Map::DeleteByValue(const T &data) + { + return DeleteBySerial(FindByValue(data)); + } + + /** + * 根据序号将指定数据从列表中移除 + * @param index 序号 + * @return 是否成功 + */ + template + bool _Map::DeleteBySerial(int index) + { + if(index<0 + ||index>=data_list.GetCount())return(false); + + data_pool.Release(GetListObject(data_list,index)); + data_list.DeleteMove(index); + + return(true); + } + + /** + * 根据序号将指定数据从列表中移除 + * @param start 起始序号 + * @param number 数量 + * @return 是否成功 + */ + template + bool _Map::DeleteBySerial(int start,int number) + { + DataPair **dp=data_list.GetData()+start; + + for(int i=0;i + void _Map::Update(const F &flag,const T &data) + { + int result; + + if(FindPos(flag,result)) + { + DataPair *dp=GetListObject(data_list,result); + + if(dp) + dp->right=data; + } + else + { + DataPair *ds=data_pool.Acquire(); + + ds->left=flag; + ds->right=data; + + data_list.Insert(result,ds); + } + } + + /** + * 更改数据,这个更改和Set不同,它要求指定标识的数据必须存在,则否就会更改失败 + * @param flag 数据标识 + * @param data 新的数据内容 + * @param return 是否更改成功 + */ + template + bool _Map::Change(const F &flag,const T &data) + { + DataPair *dp=GetListObject(data_list,Find(flag)); + + if(!dp) + return(false); + + dp->right=data; + return(true); + } + + /** + * 清除所有数据 + */ + template + void _Map::Clear() + { + data_pool.ClearAll(); + data_list.Clear(); + } + + /** + * 清除所有数据,但不释放内存 + */ + template + void _Map::ClearData() + { + data_pool.ReleaseAll(); + data_list.ClearData(); + } + + template + void _Map::operator=(const _Map &ftd) + { + Clear(); + + data_pool.ClearAll(); + data_list.ClearData(); + + const int count=ftd.data_list.GetCount(); + + if(count<=0) + return; + + IDItem **obj=ftd.data_list.GetData(); + + for(int i=0;ileft=(*obj)->left; + new_obj->right=(*obj)->right; + + data_list.Add(new_obj); + + ++obj; + } + } + + template + void _Map::Enum(void (*enum_func)(const F &,T)) + { + const int count=data_list.GetCount(); + + if(count<=0) + return; + + IDItem **idp=data_list.GetData(); + + for(int i=0;ileft,(*idp)->right); + + ++idp; + } + } + + template + void _Map::EnumKey(void (*enum_func)(const F &)) + { + const int count=data_list.GetCount(); + + if(count<=0) + return; + + IDItem **idp=data_list.GetData(); + + for(int i=0;ileft); + + ++idp; + } + } + + template + void _Map::EnumAllValue(void (*enum_func)(T)) + { + const int count=data_list.GetCount(); + + if(count<=0) + return; + + IDItem **idp=data_list.GetData(); + + for(int i=0;iright); + + ++idp; + } + } + + template + void _Map::EnumValue(bool (*enum_func)(T)) + { + const int count=data_list.GetCount(); + + if(count<=0) + return; + + IDItem **idp=data_list.GetData(); + + for(int i=0;iright)) + return; + + ++idp; + } + } +}//namespace hgl +#endif//HGL_MAP_CPP diff --git a/inc/hgl/type/Map.h b/inc/hgl/type/Map.h new file mode 100644 index 0000000..1f35cf7 --- /dev/null +++ b/inc/hgl/type/Map.h @@ -0,0 +1,340 @@ +#ifndef HGL_MAP_INCLUDE +#define HGL_MAP_INCLUDE + +#include +#include +#include +#include +namespace hgl +{ + /** + * 索引数据模板 + */ + template class _Map + { + public: + + using IDItem=DataPair; + + protected: + + ObjectPool data_pool; + List data_list; + + using this_calss=_Map; + + public: //方法 + + _Map()=default; + virtual ~_Map()=default; + + const int GetCount()const{return data_list.GetCount();} ///<取得数据总量 + + IDItem * Add(const F &,const T &); ///<添加一个数据,数果索引已存在,返回nullptr + T & Add(const F &); ///<添加一个数据 + void Add(IDItem *); ///<添加一个数据 + bool FindPos(const F &,int &)const; ///<查找数据如果插入后,会所在的位置,返回是否存在这个数据 + int FindPos(const F &flag)const{int pos;FindPos(flag,pos);return(pos);} ///<查找数据如果插入后,会所在的位置 + int Find(const F &)const; ///<查找数据是否存在,返回-1表示数据不存在 + int FindByValue(const T &)const; ///<查找数据是否存在,返回-1表示数据不存在 + bool KeyExist(const F &key)const{return(Find(key)!=-1);} ///<确认这个数据是否存在 + bool ValueExist(const T &value)const{return(FindByValue(value)!=-1);} ///<确认这个数据是否存在 + bool Check(const F &key,const T &value)const; ///<确认数据是否是这个 + virtual bool Get(const F &,T &) const; ///<取得数据 + virtual bool Delete(const F &,T &); ///<将指定数据从列表中移除,并获得这个数据 + virtual bool DeleteByKey(const F &); ///<根据索引将指定数据从列表中移除 + virtual int DeleteByKey(const F *,const int); ///<根据索引将指定数据从列表中批量移除 + virtual bool DeleteByValue(const T &); ///<根据数据将指定数据从列表中移除 + virtual bool DeleteBySerial(int); ///<根据序号将指定数据从列表中移除 + virtual bool DeleteBySerial(int,int); ///<根据序号将指定数据从列表中移除 + virtual void Update(const F &,const T &); ///<更新一个数据的内容(如不存在则添加) + virtual bool Change(const F &,const T &); ///<更改一个数据的内容(如不存在则更改失效) + virtual void Clear(); ///<清除所有数据 + virtual void ClearData(); ///<清除所有数据,但不释放内存 + + List &GetList(){return data_list;} ///<取得线性列表 + IDItem ** GetDataList()const{return data_list.GetData();} ///<取得纯数据线性列表 + + template + int GetKey(IT &il_list) ///<取得所有索引合集 + { + const int count=data_list.GetCount(); + + if(count<=0) + return count; + + IDItem **idp=data_list.GetData(); + + for(int i=0;ileft); + ++idp; + } + + return count; + } + + template + int GetValue(IT &il_list) ///<取得所有数值合集 + { + const int count=data_list.GetCount(); + + if(count<=0) + return count; + + IDItem **idp=data_list.GetData(); + + for(int i=0;iright); + ++idp; + } + + return count; + } + + IDItem *GetItem(int n){return GetListObject(data_list,n);} ///<取指定序号的数据 + bool Get(int,F &,T &) const; ///<取指定序号的数据 + bool GetKey(int,F &); ///<取指定序号的索引 + bool GetValue(int,T &); ///<取指定序号的数据 + + bool SetValueBySerial(int,T &); ///<根据序号设置数据 + + void operator=(const _Map &); ///<操作符重载,复制一个列表 + + void Enum(void (*enum_func)(const F &,T)); ///<枚举所有数据项 + void EnumKey(void (*enum_func)(const F &)); ///<枚举所有索引 + void EnumAllValue(void (*enum_func)(T)); ///<枚举所有数值 + void EnumValue(bool (*enum_func)(T)); ///<枚举所有数值(返回true/false表示是否继续) + };//class _Map + + template class Map:public _Map > + { + public: + + Map()=default; + virtual ~Map()=default; + };//class Map + + template T_U *GetListObject(Map &list,const T_ID &id) + { + T_U *result; + + if(!list.Get(id,result)) + return(nullptr); + + return result; + } + + template class _MapObject:public _Map + { + protected: + + typedef _Map SuperClass; + + virtual void DeleteObject(const F &,T *)=0; ///<删除一个数据 + void DeleteObject(DataPair *ds) + { + if(!ds)return; + DeleteObject(ds->left,ds->right); + } + + void DeleteObject(int index) + { + DeleteObject(GetListObject(this->data_list,index)); + } + + public: + + _MapObject()=default; + virtual ~_MapObject() + { + if(SuperClass::GetCount()>0) + { + //LOG_ERROR(u"这是一个严重的程序设计错误,会产生纯虚函数调用,请在派生类的析构函数中调用Clear函数以清除数据。"); + //LOG_ERROR(OS_TEXT("This is a serious design errors, will produce the pure virtual function call, please call in the destructor of the derived class the function to clear the data.")); + } + } + + /** + * 断开一个数据 + * @param flag 要断开的数据标识 + * @return 是否断开成功 + */ + bool UnlinkByKey(const F &flag) + { + return UnlinkBySerial(SuperClass::Find(flag)); + } + + /** + * 断开一个数据 + * @param tp 要断开的数据 + * @return 是否断开成功 + */ + bool UnlinkByValue(T *tp) + { + return UnlinkBySerial(this->FindByValue(tp)); + } + + /** + * 断开一个数据关联 + * @param index 要断开的数据的序列号 + * @return 是否断开成功 + */ + bool UnlinkBySerial(int index) + { + if(index<0||index>=this->data_list.GetCount())return(false); + + SuperClass::DeleteBySerial(index); + + return(true); + } + + /** + * 断开所有数据关联 + */ + void UnlinkAll() + { + SuperClass::Clear(); + } + + /** + * 删除一个数据 + * @param flag 要删除的数据标识 + * @return 是否删除成功 + */ + bool DeleteByKey(const F &flag) + { + return DeleteBySerial(SuperClass::Find(flag)); + } + + /** + * 删除一个数据 + * @param tp 要删除的数据 + * @return 是否删除成功 + */ + bool DeleteByValue(T *tp) + { + return DeleteBySerial(this->FindByValue(tp)); + } + + /** + * 删除一个数据 + * @param index 要删除的数据的序列号 + * @return 是否删除成功 + */ + bool DeleteBySerial(int index) + { + if(index<0||index>=this->data_list.GetCount())return(false); + + DeleteObject(index); + SuperClass::DeleteBySerial(index); + + return(true); + } + + /** + * 清除所有数据 + */ + void DeleteAll() + { + int n=this->data_list.GetCount(); + + while(n--) + DeleteObject(n); + + _Map::Clear(); + } + + /** + * 更新数据,如果数据不存在就添加一个新的 + * @param flag 数据标识 + * @param data 新的数据内容 + */ + void Update(const F &flag,T *data) + { + int index=this->Find(flag); + + if(index!=-1) + { + DeleteObject(index); + + DataPair *dp=GetListObject(this->data_list,index); + + if(dp) + dp->right=data; + } + else + { + this->Add(flag,data); + } + } + + /** + * 更改数据,这个更改和Set不同,它要求指定标识的数据必须存在,则否就会更改失败 + * @param flag 数据标识 + * @param data 新的数据内容 + * @param return 是否更改成功 + */ + bool Change(const F &flag,T *data) + { + int index=this->Find(flag); + + if(index!=-1) + { + DeleteObject(index); + + DataPair *dp=GetListObject(this->data_list,index); + + if(!dp) + return(false); + + dp->right=data; + return(true); + } + else + return(false); + } + + void Clear(){DeleteAll();} + };//class _MapObject + + template class CusMapObject:public _MapObject + { + protected: + + //virtual T * CreateObject(const F &){return(new T);} ///<创建一个数据 + virtual void DeleteObject(const F &,T *obj){delete obj;} ///<删除一个数据 + + public: + + CusMapObject()=default; + virtual ~CusMapObject() + { + _MapObject::Clear(); + } + };//class CusMapObject + + template class MapObject:public CusMapObject > + { + public: + + MapObject()=default; + virtual ~MapObject() + { + CusMapObject >::Clear(); + } + + T *operator[](const F &index)const + { + auto *obj=GetListObject(this->data_list,this->Find(index)); + + if(obj) + return obj->right; + else + return nullptr; + }; + };//class MapObject +}//namespace hgl +#include +#endif//HGL_MAP_INCLUDE diff --git a/inc/hgl/type/MemBlock.h b/inc/hgl/type/MemBlock.h new file mode 100644 index 0000000..3acd173 --- /dev/null +++ b/inc/hgl/type/MemBlock.h @@ -0,0 +1,203 @@ +#ifndef HGL_MEM_BLOCK_INCLUDE +#define HGL_MEM_BLOCK_INCLUDE + +#include +#include +#include +#include +namespace hgl +{ + /** + * 内存块模版 + */ + template class MemBlock + { + protected: + + T *buf; + size_t cur_size; + size_t buf_size; + + public: + + size_t GetLength ()const{return cur_size;} ///<取得内存块长度(注:非字节数) + const size_t GetMaxLength ()const{return buf_size;} ///<取得内存块最大长度(注:非字节数) + const size_t GetBytes ()const{return cur_size*sizeof(T);} ///<取得内存块字节数 + const size_t GetMaxBytes ()const{return buf_size*sizeof(T);} ///<取得内存块最大字节数 + + /** + * 分配指定空间出来,供未来使用 + */ + void Malloc(size_t size) + { + if(size<=buf_size) + return; + + buf_size=power_to_2(size); + + if(!buf) + buf=(T *)hgl_malloc(buf_size*sizeof(T)); + else + buf=(T *)hgl_realloc(buf,buf_size*sizeof(T)); + } + + /** + * 设置当前数据长度 + */ + void SetLength(size_t size) ///<设置内存块长度(注:非字节数) + { + Malloc(size); + + cur_size=size; + } + + void AddLength(size_t size) + { + SetLength(cur_size+size); + } + + public: + + MemBlock() + { + buf=0; + cur_size=0; + buf_size=0; + } + + MemBlock(size_t size) + { + if(size<=0) + buf=0; + else + buf=(T *)hgl_malloc(size*sizeof(T)); + + if(buf) + { + cur_size=size; + buf_size=size; + } + else + { + cur_size=0; + buf_size=0; + } + } + + virtual ~MemBlock() + { + Clear(); + } + + void Clear() + { + if(buf) + hgl_free(buf); + + cur_size=0; + buf_size=0; + } + + void ClearData() + { + cur_size=0; + } + + void Zero() + { + if(buf) + memset(buf,0,buf_size); + } + + /** + * 设置数据,请保证数据使用hgl_malloc分配,否则会因为释放函数不配对出现错误 + */ + void SetData(T *d,int s) + { + Clear(); + + buf=d; + buf_size=s; + cur_size=s; + } + + /** + * 解除数据关联 + */ + void Unlink() + { + buf=nullptr; + cur_size=0; + buf_size=0; + } + + /** + * 复制内存块中的数据 + * @param d 复制出来的缓冲区指针 + * @param s 要复制出来的数据个数 + */ + void CopyData(T *d,int s) + { + SetLength(s); + memcpy(buf,d,s*sizeof(T)); + } + + T *data()const{return buf;} + T *GetData()const{return buf;} + + size_t length()const{return cur_size;} + size_t GetCount()const{return cur_size;} + + size_t bytes()const + { + return cur_size*sizeof(T); + } + + operator T *()const + { + return buf; + } + + T *operator ->()const + { + return buf; + } + + T &operator[](int n) + { + return buf+n; + } + };//template class MemBlock + + /** + * 加载一个文件到内存块类中 + */ + template MemBlock *LoadFileToMemBlock(const OSString &filename) + { + io::FileInputStream fis; + + if(!fis.Open(filename))return(nullptr); + + const size_t file_size =fis.GetSize(); + const size_t size =(file_size+sizeof(T)-1)/sizeof(T); + + MemBlock *mb=new MemBlock(size); + + fis.Read(mb->data(),file_size); + + return(mb); + } + + /** + * 保存一个内存块到文件 + */ + template bool SaveMemBlockToFile(const OSString &filename,const MemBlock &mb) + { + const size_t size=mb.bytes(); + + if(size<=0)return(true); + + return(hgl::filesystem::SaveMemoryToFile(filename,mb.data(),mb.bytes())==size); + } +}//namespace hgl +#endif//HGL_MEM_BLOCK_INCLUDE diff --git a/inc/hgl/type/ObjectList.cpp b/inc/hgl/type/ObjectList.cpp new file mode 100644 index 0000000..ef55dc2 --- /dev/null +++ b/inc/hgl/type/ObjectList.cpp @@ -0,0 +1,249 @@ +#ifndef HGL_OBJECT_LIST_CPP +#define HGL_OBJECT_LIST_CPP + +#include +namespace hgl +{ + /** + * 对象列表析构函数,会调用DeleteAll函数 + */ + template + CusObjectList::~CusObjectList() + { + Clear(); + } + +// /** +// * 生成一个对象,并返回它的指针 +// */ +// template +// T *CusObjectList::Append() +// { +// if(!this->items) +// { +// this->max_count=1; +// this->items=(T **)hgl_aligned_malloc(1); +// } +// else +// { +// if(this->count>=this->max_count) +// this->max_count<<=1; +// +// this->items=(T **)hgl_realloc(this->items,this->max_count*sizeof(T *)); +// } +// +// return(this->items[this->count++]=CreateObject()); +// } + +// /** +// * 在指定位置插入一个对象 +// */ +// template +// T *CusObjectList::Insert(int index) +// { +// if(index<0)index=0; +// +// if(indexcount) +// { +// if(this->count>=this->max_count) +// this->max_count<<=1; +// +// this->items=(T **)hgl_realloc(this->items,this->max_count*sizeof(T *)); +// +// memmove(this->items+index+1,this->items+index,(this->count-index)*sizeof(T *)); +// +// this->count++; +// +// return(this->items[index]=CreateObject()); +// } +// +// return(Append()); +// } + + /** + * 在指定位置插入一个对象 + */ + template + void CusObjectList::Insert(int index,const ItemPointer &obj) + { + List::Insert(index,obj); + } + + /** + * 清除所有对象,作用和DeleteAll一样 + */ + template + void CusObjectList::Clear() + { + DeleteAll(); + List::Clear(); + } + + /** + * 清除所有对象,但不释放内存 + */ + template + void CusObjectList::ClearData() + { + DeleteAll(); + List::ClearData(); + } + + /** + * 删除列表中的指定项 + * + * 这个函数在删除指定对象时,附加使用delete方法 + * @param index 要删除的对象的索引值 + * @return 是否成功 + */ + template + bool CusObjectList::Delete(int index) + { + if(index>=0&&indexcount) + { + DeleteObject(this->items[index]); + + this->count--; + + if(indexcount) + memcpy(this->items+index,this->items+this->count,sizeof(T *)); + + return(true); + } + else + return(false); + } + + /** + * 删除列表中的指定项 + * + * 这个函数在删除指定对象时,附加使用delete方法 + * @param index 要删除的对象的索引值 + * @return 是否成功 + */ + template + bool CusObjectList::DeleteMove(int index) + { + if(index>=0&&indexcount) + { + DeleteObject(this->items[index]); + + this->count--; + + if(indexcount) + memmove(this->items+index,this->items+index+1,(this->count-index)*sizeof(T *)); + + return(true); + } + else + return(false); + } + + /** + * 删除列表中的指定项 + * + * 这个函数在删除指定对象时,附加使用delete方法 + * @param obj 要删除的对象 + * @return 是否成功 + */ + template + bool CusObjectList::DeleteByValue(const ItemPointer &obj) + { + int n=this->count; + + while(n--) + { + if(this->items[n]==obj) + { + DeleteObject(this->items[n]); + + this->count--; + + if(ncount) + memmove(this->items+n,this->items+n+1,(this->count-n)*sizeof(T *)); + + return(true); + } + } + + return(false); + } + + /** + * 将一批对象从列表中删除 + * @param obj 要删除的对象 + * @param n 要删除的对象个数 + */ + template + void CusObjectList::DeleteByValue(const ItemPointer *obj,int n) + { + while(n--) + { + int index=List::Find(*obj); + + obj++; + + if(index!=-1) + Delete(index); + } + } + /** + * 删除整个列表中的所有对象 + * + * 这个函数在删除每一个对象时,都会使用一次delete + */ + template + void CusObjectList::DeleteAll() + { + if(this->count) + { + int n=this->count; + + while(n--) + DeleteObject(this->items[n]); + + this->count=0; + } + } + + template + void CusObjectList::SetCount(int new_count) + { + if(this->count==new_count)return; + + if(new_count<=0) + { + DeleteAll(); + } + else + { + this->max_count=power_to_2(new_count); + + if(this->items) + { + if(new_count>this->count) + { + this->items=(T **)hgl_realloc(this->items,this->max_count*sizeof(T *)); + +// for(;this->countcount++) +// this->items[this->count]=CreateObject(); + } + else + { + while(this->count-->new_count) + DeleteObject(this->items[this->count]); + + this->items=(T **)hgl_realloc(this->items,this->max_count*sizeof(T *)); + } + } +// else +// { +// this->items=(T **)hgl_aligned_malloc(this->max_count); +// +// while(new_count--) +// this->items[this->count++]=CreateObject(); +// } + } + } +}//namespace hgl +#endif//HGL_OBJECT_LIST_CPP diff --git a/inc/hgl/type/Pair.h b/inc/hgl/type/Pair.h new file mode 100644 index 0000000..13d4cfa --- /dev/null +++ b/inc/hgl/type/Pair.h @@ -0,0 +1,82 @@ +#ifndef HGL_TYPE_PAIR_INCLUDE +#define HGL_TYPE_PAIR_INCLUDE + +#include +#include + +namespace hgl +{ + /** + * 成对数据模板 + */ + template struct Pair ///成对数据模板 + { + L left; + R right; + + using SelfClass=Pair; + + public: + + Pair()=default; + + Pair(const L &l,const R &r) + { + left=l; + right=r; + } + + Pair(const SelfClass &p) + { + operator=(p); + } + + Pair(const SelfClass *p) + { + operator=(p); + } + + virtual ~Pair()=default; + + SelfClass &operator=(const SelfClass &p) + { + left=p.left; + right=p.right; + + return(*this); + } + + SelfClass &operator=(const SelfClass *p) + { + if(!p)return(*this); + + left=p->left; + right=p->right; + + return(*this); + } + + void Swap(Pair &p) + { + p.left=right; + p.right=left; + } + + //不使用CompOperator是因为某些类型无法做+-处理 + + const bool operator == (const SelfClass &p)const + { + if(this->left!=p.left)return(false); + + return this->right==p.right; + } + + const bool operator != (const SelfClass &p)const + { + if(this->left==p.left)return(false); + + return this->right!=p.right; + } + };//template struct Pair +}//namespace hgl +#endif//HGL_TYPE_PAIR_INCLUDE diff --git a/inc/hgl/type/Pool.cpp b/inc/hgl/type/Pool.cpp new file mode 100644 index 0000000..7e1c9b9 --- /dev/null +++ b/inc/hgl/type/Pool.cpp @@ -0,0 +1,144 @@ +#ifndef HGL_POOL_CPP +#define HGL_POOL_CPP + +#include +#include +namespace hgl +{ + template + void Pool::PreMalloc(int num) + { + if(num<=0)return; + + for(int i=0;ihistory_max) + history_max=count; + } + + template + T Pool::Acquire() + { + T result; + + if(!Inactive.Pop(result)) + { + result=Create(); + + count++; + + if(count>history_max) + history_max=count; + } + + Active.Add(result); + + return(result); + } + + template + void Pool::Append(T value) + { + T result; + + if(!Inactive.Pop(result)) + { + count++; + + if(count>history_max) + history_max=count; + } + + Active.Add(result); + + result=value; + } + + template + bool Pool::Release(T value) + { + int index=Active.Find(value); + + if(index!=-1) + { + Active.Delete(index); + + Inactive.Push(value); + + return(true); + } + + return(false); + } + + template + int Pool::Release(T *vl,int count) + { + int total=0; + + for(int i=0;i + int Pool::ReleaseAll() + { + int count=Active.GetCount(); + T *p=Active.GetData(); + + for(int i=0;i + void Pool::ClearInactive() + { + T result; + + count-=Inactive.GetCount(); + + while(Inactive.Pop(result)) + Clear(result); + } + + template + void Pool::ClearAll() + { + { //不能直接调ClearInactive + T result; + + count-=Inactive.GetCount(); + + while(Inactive.Pop(result)) + Clear(result); + } + + { + int n=Active.GetCount(); + T *p=Active.GetData(); + + while(n--) + { + Clear(*p); + ++p; + } + + Active.Clear(); + } + + count=0; + } +}//namespace hgl +#endif//HGL_POOL_CPP diff --git a/inc/hgl/type/Pool.h b/inc/hgl/type/Pool.h new file mode 100644 index 0000000..ada94bb --- /dev/null +++ b/inc/hgl/type/Pool.h @@ -0,0 +1,267 @@ +#ifndef HGL_POOL_INCLUDE +#define HGL_POOL_INCLUDE + +#include +#include +#include +#include +#include +namespace hgl +{ + /** + * 数据池模板用于管于两个队列,一个在用的,一个空闲的 + */ + template class Pool ///数据池 + { + protected: + + List Active; + Queue Inactive; + + int count; + int history_max; + + protected: + + virtual T Create()=0; ///<创建数据 + virtual void Clear(T)=0; ///<清除数据 + + public: //属性 + + virtual int GetActiveCount() const{return Active.GetCount();} ///<取得活动数据数量 + virtual int GetInactiveCount() const{return Inactive.GetCount();} ///<取得非活动数据数量 + virtual int GetHistoryMaxCount()const{return history_max;} ///<取得历史性最大数据数量 + + public: + + Pool(){count=0;history_max=0;} + virtual ~Pool()=default; + + virtual void PreMalloc(int); ///<预分配空间 + + virtual T Acquire(); ///<申请一个数据 + virtual void Append(T); ///<添加一个数据 + virtual bool Release(T); ///<释放一个数据 + virtual int Release(T *,int); ///<释放一批数据 + virtual int ReleaseAll(); ///<释放所有数据 + + virtual void ClearInactive(); ///<清除所有空闲的 + virtual void ClearAll(); ///<清除所有的 + };//template class Pool + + template class MTPool:public Pool ///多线程数据池 + { + RWLock lock; + + protected: + + virtual T Create()=0; ///<创建数据 + virtual void Clear(T)=0; ///<清除数据 + + public: + + virtual int GetActiveCount() {OnlyReadLock rl(lock);return Pool::Active.GetCount(); } + virtual int GetInactiveCount() {OnlyReadLock rl(lock);return Pool::Inactive.GetCount(); } + virtual int GetHistoryMaxCount(){OnlyReadLock rl(lock);return Pool::history_max; } + + public: + + virtual ~MTPool()=default; + + virtual T *ReadLock(int &c) ///<读列表锁定(用于访问整个列表) + { + lock.ReadLock(); + + c=Pool::GetActiveCount(); + return(Pool::Active.GetData()); + } + + virtual T *WriteLock(int &c) ///<写列表锁定(用于访问整个列表) + { + lock.WriteLock(); + + c=Pool::GetActiveCount(); + return(Pool::Active.GetData()); + } + + virtual T *TryReadLock(int &c) ///<尝试读列表锁定(用于访问整个列表) + { + if(!lock.TryReadLock()) + return(nullptr); + + c=Pool::GetActiveCount(); + return(Pool::Active.GetData()); + } + + virtual T *TryWriteLock(int &c) ///<尝试写列表锁定(用于访问整个列表) + { + if(!lock.TryWriteLock()) + return(nullptr); + + c=Pool::GetActiveCount(); + return(Pool::Active.GetData()); + } + + virtual void ReadLock(){lock.ReadLock();} + virtual void WriteLock(){lock.WriteLock();} + virtual bool TryReadLock(){return lock.TryReadLock();} + virtual bool TryWriteLock(){return lock.TryWriteLock();} + + virtual void ReadUnlock(){lock.ReadUnlock();} ///<读访问解锁(用于访问整个列表) + virtual void WriteUnlock(){lock.WriteUnlock();} ///<写访问解锁(用于访问整个列表) + + virtual T SafeAcquire() ///<安全申请一个数据 + { + T tmp; + + lock.WriteLock(); + tmp=Pool::Acquire(); + lock.WriteUnlock(); + + return tmp; + } + + virtual void SafeAppend(T tmp) ///<安全添加一个数据 + { + lock.WriteLock(); + Pool::Append(tmp); + lock.WriteUnlock(); + } + + virtual bool SafeRelease(T tmp) ///<安全释放一个数据 + { + bool result; + + lock.WriteLock(); + result=Pool::Release(tmp); + lock.WriteUnlock(); + + return result; + } + + virtual int SafeRelease(T *tmp,int num) ///<安全释放一批数据 + { + int result; + + lock.WriteLock(); + result=Pool::Release(tmp,num); + lock.WriteUnlock(); + + return result; + } + + virtual int SafeReleaseAll() ///<安全释放所有数据 + { + int result; + + lock.WriteLock(); + result=Pool::ReleaseAll(); + lock.WriteUnlock(); + + return(result); + } + + virtual void SafeClearInactive() ///<安全清除所有空闲数据 + { + lock.WriteLock(); + Pool::ClearInactive(); + lock.WriteUnlock(); + } + + virtual void SafeClearAll() ///<安全清除所有的 + { + lock.WriteLock(); + Pool::ClearAll(); + lock.WriteUnlock(); + } + };//template class MTPool + + template class _ObjectPool:public Pool ///对象池 + { + virtual T *Create()=0; + + virtual void Clear(T *obj) { if(obj)delete obj; } + + public: + + using Pool::Pool; + virtual ~_ObjectPool(){Pool::ClearAll();} + + virtual bool Release(T *obj) override ///<释放一个数据 + { + if(!obj)return(true); + + return Pool::Release(obj); + } + };//template class _ObjectPool + + template class ObjectPool:public _ObjectPool ///对象池 + { + virtual T *Create()override{return(new T());} + + public: + + using _ObjectPool::_ObjectPool; + virtual ~ObjectPool(){_ObjectPool::ClearAll();} + };//template class ObjectPool + + template class _MTObjectPool:public MTPool ///多线程对象池 + { + virtual T *Create() override=0; + + virtual void Clear(T *obj) override { if(obj)delete obj; } + + public: + + using MTPool::MTPool; + virtual ~_MTObjectPool(){MTPool::ClearAll();} + };//template class MTObjectPool + + template class MTObjectPool:public _MTObjectPool ///多线程对象池 + { + virtual T *Create() override {return(new T());} + + virtual void Clear(T *obj) override { if(obj)delete obj; } + + public: + + using _MTObjectPool::_MTObjectPool; + virtual ~MTObjectPool(){_MTObjectPool::ClearAll();} + };//template class MTObjectPool + + template class MemBlockPool:public Pool ///内存块池 + { + int memblock_size; + + T *Create() { return(new T[memblock_size]); } + + void Clear(T *obj) { if(obj)delete[] obj; } + + public: + + MemBlockPool(int size){SetSize(size);} + virtual ~MemBlockPool(){Pool::ClearAll();} + + void SetSize(int size){memblock_size=size;} + int GetSize(){return memblock_size;} + };//template class MemBlockPool + + template class MTMemBlockPool:public MTPool ///多线程内存块池 + { + int memblock_size; + + T *Create() { return(new T[memblock_size]); } + + void Clear(T *obj) { if(obj)delete[] obj; } + + public: + + MTMemBlockPool(int size){SetSize(size);} + virtual ~MTMemBlockPool(){MTPool::ClearAll();} + + void SetSize(int size){memblock_size=size;} + int GetSize(){return memblock_size;} + };//template class MTMemBlockPool +}//namespace hgl +#include +#endif//HGL_POOL_INCLUDE diff --git a/inc/hgl/type/Queue.cpp b/inc/hgl/type/Queue.cpp new file mode 100644 index 0000000..661d7de --- /dev/null +++ b/inc/hgl/type/Queue.cpp @@ -0,0 +1,239 @@ +#ifndef HGL_QUEUE_CPP +#define HGL_QUEUE_CPP + +namespace hgl +{ + /** + * 本类构造函数 + * @param m 如果m的值不为0,则表示使用固定的队列大小。固定大小的队列会在一开始即分配好内存。 + */ + template + Queue::Queue(int m) + { + count=0; + + if(m) + { + max_count=m; + + items=hgl_aligned_malloc(max_count); + } + else max_count=0; + + mem_count=max_count; + } + + template + Queue::~Queue() + { + if(count||max_count)hgl_free(items); + } + + /** + * 修改队列的最大值 + */ + template + void Queue::SetMax(int m) + { + if(max_count||(!max_count&&count)) + items=(T *)hgl_realloc(items,m*sizeof(T)); + else + items=hgl_aligned_malloc(m); + + max_count=m; + mem_count=m; + + if(count>=max_count)count=max_count-1; + } + + /** + * 清除队列中的所有数据 + */ + template + void Queue::Clear() + { + if(max_count==0) + if(count) + { + hgl_free(items); + mem_count=0; + } + + count=0; + } + + /** + * 清除队列中的所有数据,但不释放内存 + */ + template + void Queue::ClearData() + { + count=0; + } + + /** + * 访问队列中的一个数据,但不清除它 + * @param t 取出的数据保存地 + * @return 是否成功取出数据 + */ + template + bool Queue::Peek(T &t) + { + if(count) + { +// t=items[0]; + memcpy(&t,items,sizeof(T)); + return(true); + } + else + return(false); + } + + /** + * 删除队列中的指定数据 + * @param index 索引 + */ + template + bool Queue::Delete(int index) + { + if(index<0||index>=count) + return(false); + + count--; + + if(count) + { + if(index + bool Queue::Pop(T &t) + { + if(count) + { +// t=items[0]; + memcpy(&t,items,sizeof(T)); + + count--; + + if(max_count==0) + { + if(count) + { + //memcpy(items,items+1,count*sizeof(T)); + memmove(items,items+1,count*sizeof(T)); +// items=(T *)hgl_realloc(items,count*sizeof(T)); + } + } + else + { + memcpy(items,items+1,count*sizeof(T)); + } + + return(true); + } + else + return(false); + } + + /** + * 向队列中放入一个数据 + * @param data 要放入的数据指针 + * @return true 放入数据成功 + * @return false 放入数据失败 + */ + template + bool Queue::Push(const T &data) + { + if(max_count) + { + if(count>=max_count)return(false); + } + else + { + if(count) + { + if(count+1>mem_count) + { + mem_count=power_to_2(count+1); + + items=(T *)hgl_realloc(items,mem_count*sizeof(T)); + } + } + else + { + items=hgl_aligned_malloc(1); + + mem_count=1; + } + } + +// items[count++]=data; + memcpy(items+count,&data,sizeof(T)); + count++; + + return(true); + } + + template + int Queue::Find(const T &data) + { + if(count<=0) + return(-1); + + T *p=items; + for(int i=0;i + void Queue::operator =(const Queue &ori) + { + if(ori.count==0)return; + + Clear(); + + max_count=ori.count; + count=ori.count; + + if(max_count==0) + mem_count=count; + else + mem_count=max_count; + + items=hgl_aligned_malloc(mem_count); + + memcpy(items,ori.items,mem_count*sizeof(T)); + } +} + +namespace hgl +{ + template + void QueueObject::Clear() + { + int n=Queue::count; + + while(n--) + delete Queue::items[n]; + + Queue::Clear(); + } +} +#endif//HGL_QUEUE_CPP diff --git a/inc/hgl/type/Queue.h b/inc/hgl/type/Queue.h new file mode 100644 index 0000000..c83514b --- /dev/null +++ b/inc/hgl/type/Queue.h @@ -0,0 +1,75 @@ +#ifndef HGL_QUEUE_INCLUDE +#define HGL_QUEUE_INCLUDE + +#include +namespace hgl +{ + /** + * Queue模板类用于保存一个先进先出、后进后出的数据队列 + * + * 注:这个类还在测试中,请不要修改这个类的源代码,如有修改意见,请致电作者。 + */ + template class Queue ///队列顺序数据访问类 + { + protected: + + int max_count; + int mem_count; + int count; + T *items; + + public: //属性 + + T *GetData()const{return items;} ///<取得原始数据 + int GetCount()const{return count;} ///<取得数据数量 + + int GetMax()const{return max_count;} ///<取得最大数量 + void SetMax(int); ///<设置最大数量 + + T *GetData(){return items;} ///<取得原始数据 + + public: //方法 + + Queue(int=0); + virtual ~Queue(); + + bool Peek(T &); ///<尝试访问一个数据 + bool Pop(T &); ///<弹出一个数据 + bool Push(const T &); ///<压入一个数据 + + int Find(const T &); ///<查找队列中这个数据的编号 + bool Delete(int); ///<删除队列中指定编号的数据 + + void Clear(); ///<清除所有数据 + void ClearData(); ///<清除所有数据,但不释放内存 + + bool GetItem(int n,T &ti) ///<取得指定项数据 + { + if(n<0||n>=count)return(false); + + ti=items[n]; + return(true); + } + + virtual void operator =(const Queue &); + };//template class Queue + + template class QueueObject:public Queue ///堆栈对象 + { + public: + + using Queue::Queue; + virtual ~QueueObject(){Clear();} + + void Clear(); + + T *operator[](int n)const + { + if(n<0||n>=Queue::count)return(nullptr); + + return Queue::items[n]; + } + };//template class QueueObject +}//namespace hgl +#include +#endif//HGL_QUEUE_INCLUDE diff --git a/inc/hgl/type/RectScope.cpp b/inc/hgl/type/RectScope.cpp new file mode 100644 index 0000000..2439deb --- /dev/null +++ b/inc/hgl/type/RectScope.cpp @@ -0,0 +1,80 @@ +#ifndef HGL_RECT_SCOPE_CPP +#define HGL_RECT_SCOPE_CPP + +#include +namespace hgl +{ + /** + * 本类构造函数 + */ + template + RectScope2::RectScope2() + { + Left=0; + Top=0; + Width=0; + Height=0; + } + + /** + * 本类构造函数 + * @param l 矩形最左边的坐标值 + * @param t 矩形最上边的坐标值 + * @param w 矩形的宽度 + * @param h 矩形的高度 + */ + template + RectScope2::RectScope2(T l,T t,T w,T h) + { + Left=l; + Top=t; + Width=w; + Height=h; + } + + template template + RectScope2::RectScope2(const RectScope2 &rs) + { + Left =rs.Left; + Top =rs.Top; + Width =rs.Width; + Height =rs.Height; + } + + /** + * 设置数据 + * @param l 矩形最左边的坐标值 + * @param t 矩形最上边的坐标值 + * @param w 矩形的宽度 + * @param h 矩形的高度 + */ + template + void RectScope2::Set(T l,T t,T w,T h) + { + Left=l; + Top=t; + Width=w; + Height=h; + } + + /** + * 求坐标点x,y,z是否在这个矩形内 + * @param x X坐标 + * @param y Y坐标 + * @return 点x,y,z是否在矩形范围内 + */ + template + bool RectScope2::PointIn(T x,T y) const + { + T pos; + + pos=x-Left; + if(pos<0||pos>=Width)return(false); + + pos=y-Top; + if(pos<0||pos>=Height)return(false); + + return(true); + } +}//namespace hgl +#endif//HGL_RECT_SCOPE_CPP diff --git a/inc/hgl/type/RectScope.h b/inc/hgl/type/RectScope.h new file mode 100644 index 0000000..84d5aa3 --- /dev/null +++ b/inc/hgl/type/RectScope.h @@ -0,0 +1,141 @@ +#ifndef HGL_RECTSCOPE_INCLUDE +#define HGL_RECTSCOPE_INCLUDE + +#include +namespace hgl +{ + /** + * 这个类用于描述和处理一个矩形范围 + */ + template class RectScope2 ///矩形范围类 + { + protected: + + T Left; ///<矩形左边所在的坐标 + T Top; ///<矩形上边所在的坐标 + T Width; ///<矩形的宽度 + T Height; ///<矩形的高度 + + public: + + T GetLeft ()const{return Left;} + T GetTop ()const{return Top;} + T GetWidth ()const{return Width;} + T GetHeight ()const{return Height;} + T GetBottom ()const{return Height+Top;} + T GetRight ()const{return Width+Left;} + + void SetLeft (T v){Left=v;} + void SetTop (T v){Top=v;} + void SetWidth (T v){Width=v;} + void SetHeight (T v){Height=v;} + void SetBottom (T v){Height=v-Top;} + void SetRight (T v){Width=v-Left;} + + T GetCenterX()const{return Left+(Width/2);} + T GetCenterY()const{return Top+(Height/2);} + + const vec2 GetLeftTop ()const{return vec2(Left, Top);} + const vec2 GetLeftBottom ()const{return vec2(Left, Top+Height);} + const vec2 GetRightTop ()const{return vec2(Left+Width, Top);} + const vec2 GetRightBottom()const{return vec2(Left+Width, Top+Height);} + + public: + + RectScope2(); + RectScope2(T,T,T,T); + template RectScope2(const RectScope2 &); + + void Clear() + { + Left=0; + Top=0; + Width=0; + Height=0; + } + + void Set(T,T,T,T); + + bool PointIn(T,T)const; + + bool PointIn(const Vector2f &v)const{return PointIn(v.x,v.y);} + bool PointIn(const Vector3f &v)const{return PointIn(v.x,v.y);} + + template + void operator = (const RectScope2 &rs) + { + Left =rs.Left; + Top =rs.Top; + Width =rs.Width; + Height =rs.Height; + } + + template + bool operator == (const RectScope2 &rs) const + { + if((Left ==rs.Left ) + &&(Top ==rs.Top ) + &&(Width ==rs.Width ) + &&(Height ==rs.Height ))return(true); + else + return(false); + } + + template + bool operator != (const RectScope2 &rs) const + { + return(!operator==(rs)); + } + + template + void operator += (const RectScope2 &rs) + { + const T r=hgl_max(GetRight(),rs.GetRight()); + const T b=hgl_max(GetBottom(),rs.GetBottom()); + + Left=hgl_min(Left,rs.Left); + Top =hgl_max(Top,rs.Top); + Width=r-Left; + Height=b-Top; + } + + template + RectScope2 operator + (const N &v) const + { + return RectScope2(Left+v[0],Top+v[1],Width,Height); + } + + template + RectScope2 operator - (const N &v) const + { + return RectScope2(Left+v[0],Top+v[1],Width,Height); + } + + template + RectScope2 &operator += (const N &v) + { + Left+=v[0]; + Top+=v[1]; + + return(*this); + } + + template + RectScope2 &operator -= (const N &v) + { + Left-=v[0]; + Top-=v[1]; + + return(*this); + } + };//class RectScope2 + + typedef RectScope2 RectScope2d; + typedef RectScope2 RectScope2f; + typedef RectScope2 RectScope2i; + typedef RectScope2 RectScope2ui; + typedef RectScope2 RectScope2s; + typedef RectScope2 RectScope2us; +}//namespace hgl +#include +#endif//HGL_RECTSCOPE_INCLUDE diff --git a/inc/hgl/type/ResManage.cpp b/inc/hgl/type/ResManage.cpp new file mode 100644 index 0000000..02f3659 --- /dev/null +++ b/inc/hgl/type/ResManage.cpp @@ -0,0 +1,160 @@ +#ifndef HGL_RES_MANAGE_CPP +#define HGL_RES_MANAGE_CPP + +#include +namespace hgl +{ + template + ResManage::~ResManage() + { + Clear(); + } + + template + void ResManage::Clear() + { + int n=items.GetCount(); + + while(n--) + { + ResItem *obj=items.GetItem(n); + + Clear(obj->right); + } + + items.Clear(); + } + + template + void ResManage::ClearFree() + { + int n=items.GetCount(); + + while(n--) + { + ResItem *obj=items.GetItem(n); + + if(obj->count<=0) + { + Clear(obj->right); + items.DeleteBySerial(n); + } + } + } + + template + bool ResManage::Add(const F &flag,T *obj) + { + if(!obj)return(false); + + if(items.KeyExist(flag)) + return(false); + + items.Add(flag,obj); + return(true); + } + + template + T *ResManage::Find(const F &flag) + { + int index=items.Find(flag); + + if(index==-1) + return(nullptr); + + T *result; + + if(items.Get(flag,result)) + return(result); + + return(nullptr); + } + + template + T *ResManage::Get(const F &flag) + { + int index=items.Find(flag); + + if(index!=-1) + { + ResItem *obj=items.GetItem(index); + + ++obj->count; + + return obj->right; + } + + return(nullptr); + } + + /** + * 确认指定数据是否存在 + */ + template + bool ResManage::ValueExist(T *value) + { + return(items.FindByValue(value)!=-1); + } + + /** + * 获取指定数据的Key和引用计数 + * @param value 数据 + * @param key Key存放地址 + * @param ref_count 引用计数存放地址 + * @param 是否增加引用计数 + */ + template + bool ResManage::GetKeyByValue(T *value,F *key,uint *ref_count,bool inc_ref_count) + { + int index=items.FindByValue(value); + + if(index==-1)return(false); + + ResItem *obj=items.GetItem(index); + + if(inc_ref_count) + ++obj->count; + + if(key) + *key=obj->left; + + if(ref_count) + *key=obj->count; + + return(true); + } + + template + void ResManage::ReleaseBySerial(int index,bool zero_clear) + { + if(index==-1) + { +// ErrorHint(u"所释放的资源不存在"); + return; + } + + ResItem *obj=items.GetItem(index); + + --obj->count; + + if(zero_clear&&obj->count==0) + { + Clear(obj->right); + + items.DeleteBySerial(index); + } + } + + template + void ResManage::Release(const F &flag,bool zero_clear) + { + ReleaseBySerial(items.Find(flag),zero_clear); + } + + template + void ResManage::Release(T *td,bool zero_clear) + { + ReleaseBySerial(items.FindByValue(td),zero_clear); + } +}//namespace hgl +#endif//HGL_RES_MANAGE_CPP diff --git a/inc/hgl/type/ResManage.h b/inc/hgl/type/ResManage.h new file mode 100644 index 0000000..081375e --- /dev/null +++ b/inc/hgl/type/ResManage.h @@ -0,0 +1,88 @@ +#ifndef HGL_RES_MANAGE_INCLUDE +#define HGL_RES_MANAGE_INCLUDE + +#include +namespace hgl +{ + template struct RefFlagData:public Pair + { + uint count; + + public: + + RefFlagData():Pair() + { + count=1; + } + }; + + /** + * 资源管理器,它没有缓冲管理,仅仅是管理数据,并保证不会被重复加载 + */ + template class ResManage + { + protected: + + using ResItem=RefFlagData ; + + _Map items; + + void ReleaseBySerial(int,bool); + + protected: + + virtual void Clear(T *obj){delete obj;} ///<资源释放虚拟函数(缺省为直接delete对象) + + public: + + virtual ~ResManage(); + + virtual void Clear(); ///<清除所有数据 + virtual void ClearFree(); ///<清除所有没有用到的数据 + + const int GetCount()const{return items.GetCount();} ///<取得数据数量 + + virtual bool Add(const F &,T *); ///<添加一个数据 + virtual T * Find(const F &); ///<查找一个数据 + virtual T * Get(const F &); ///<取得一个数据 + + virtual bool ValueExist(T *); ///<确认这个数据是否存在 + virtual bool GetKeyByValue(T *,F *,uint *,bool inc_ref_count=false); ///<取得一个数据的Key和引用次数 + + virtual void Release(const F &,bool zero_clear=false); ///<释放一个数据 + virtual void Release(T *,bool zero_clear=false); ///<释放一个数据 + };//template class ResManage + + /** + * 使用int类做数标致的资源管理器 + */ + template class IDResManage:public ResManage + { + F id_count=0; + + public: + + using ResManage::ResManage; + virtual ~IDResManage()=default; + + virtual F Add(T *value) + { + if(!value)return(-1); + + { + F key; + uint count; + + if(ResManage::GetKeyByValue(value,&key,&count,true)) + return key; + } + + if(!ResManage::Add(id_count,value)) + return(-1); + + return id_count++; + } + };//template class IDResManage:public ResManage +}//namespace hgl +#include +#endif//HGL_RES_MANAGE_INCLUDE diff --git a/inc/hgl/type/ResPoolManage.h b/inc/hgl/type/ResPoolManage.h new file mode 100644 index 0000000..b6eb7c4 --- /dev/null +++ b/inc/hgl/type/ResPoolManage.h @@ -0,0 +1,34 @@ +#ifndef HGL_RES_POOL_MANAGE_INCLUDE +#define HGL_RES_POOL_MANAGE_INCLUDE + +#include +#include + +namespace hgl +{ + /** + * 资源池是Pool/ResManage两个模板的组合应用 + */ + template class ResPoolManage:public ResManage + { + protected: + + ObjectPool data_pool; + + public: + + virtual T *Create(const I &flag){return data_pool.Acquire();} + virtual void Clear(T *obj){data_pool.Release(obj);} + + public: + + virtual ~ResPoolManage()=default; + + virtual void Clear() + { + this->items.Clear(); + data_pool.ClearAll(); + } + };//template class ResPoolManage:public ResManage +}//namespace hgl +#endif//HGL_RES_POOL_MANAGE_INCLUDE diff --git a/inc/hgl/type/Set.cpp b/inc/hgl/type/Set.cpp new file mode 100644 index 0000000..393a2a5 --- /dev/null +++ b/inc/hgl/type/Set.cpp @@ -0,0 +1,365 @@ +#ifndef HGL_TYPE_SET_CPP +#define HGL_TYPE_SET_CPP + +#include +namespace hgl +{ + /** + * 查找数据是否存在 + * @param flag 数据 + * @return 数据所在索引,-1表示不存在 + */ + template + const int Set::Find(const T &flag)const + { + int left=0,right=data_list.GetCount()-1; //使用left,right而不使用min,max是为了让代码能够更好的阅读。 + int mid; + + T *data_array=data_list.GetData(); + + while(left<=right) + { + if(data_array[left ]==flag)return(left); + if(data_array[right]==flag)return(right); + + mid=(right+left)>>1; + + if(data_array[mid]==flag)return(mid); + + if(data_array[mid]>flag) + { + left++; + right=mid-1; + } + else + { + right--; + left=mid+1; + } + } + + return(-1); + } + + template + bool Set::FindPos(const T &flag,int &pos)const + { + int left=0,right=data_list.GetCount()-1; + int mid; + + T *data_array=data_list.GetData(); + + while(left<=right) + { + if(data_array[left]>flag) + { + pos=left; + return(false); + } + else + if(data_array[left]==flag) + { + pos=left; + return(true); + } + + if(data_array[right]>1; + + if(data_array[mid]==flag) + { + pos=mid; + return(true); + } + + if(data_array[mid]>flag) + { + if(data_array[mid-1]flag) + { + pos=mid+1; + return(false); + } + else + if(data_array[mid+1]==flag) + { + pos=mid+1; + return(true); + } + + --right; + left=mid+1; + } + } + + return(false); + } + + /** + * 添加一个数据 + * @param data 数据 + * @return 位置 + */ + template + int Set::Add(const T &data) + { + if(data_list.GetCount()<=0) + { + data_list.Add(data); + + return 0; + } + else + { + int pos; + + if(FindPos(data,pos)) + return(-1); //数据已存在 + + data_list.Insert(pos,data); + + return(pos); + } + } + + /** + * 添加一批数据 + * @param dp 数据指针 + * @param count 数据个数 + * @return 成功加入的数据个数 + */ + template + int Set::Add(const T *dp,const int count) + { + int total=0; + + for(int i=0;i + bool Set::Update(const T &data) + { + if(data_list.GetCount()<=0) + return(false); + + int pos; + + if(!FindPos(data,pos)) + return(false); + + data_list.Set(pos,data); + return(true); + } + + /** + * 删除一个数据 + * @param pos 索引编号 + */ + template + bool Set::DeleteBySerial(int pos) + { + if(pos<0||pos>=data_list.GetCount())return(false); + + return data_list.DeleteMove(pos); + } + + /** + * 删除一个数据 + * @param data 数据 + */ + template + bool Set::Delete(const T &data) + { + int pos=Find(data); + + if(pos==-1)return(false); + + return DeleteBySerial(pos); + } + + /** + * 删除一批数据 + * @param dp 数据指针 + * @param count 数据个数 + * @return 成功删除的数据个数 + */ + template + int Set::Delete(T *dp,const int count) + { + int total=0; + int pos; + + for(int i=0;i + void Set::Clear() + { + data_list.Clear(); + } + + /** + * 清除所有数据,但不释放内存 + */ + template + void Set::ClearData() + { + data_list.ClearData(); + } + + /** + * 随机取得一个数据 + */ + template + bool Set::Rand(T &result)const + { + return data_list.Rand(result); + } + + /** + * 求当前合集与另一个数据集的交集 + * @param result 结果存放合集 + * @param list 要计算交集的数据集 + * @return 交集数量 + */ + template + int Set::Intersection(Set &result,const Set &list) + { + if(data_list.GetCount()<=0) + return(0); + + if(list.GetCount()<=0) + return(0); + + data_list.Enum([&](T &obj) + { + if(list->IsMember(obj)) + result.Add(obj); + }); + + return result.GetCount(); + } + + template + int Set::Intersection(const Set &list) + { + if(data_list.GetCount()<=0) + return(0); + + if(list.GetCount()<=0) + return(0); + + int count=0; + + T *obj=data_list.GetData(); + for(int i=0;i + int Set::Intersection(Set &result,const Set &il,const Set &cl) + { + if(data_list.GetCount()<=0) + return(0); + + if(il.GetCount()<=0) + return(0); + + T *obj=data_list.GetData(); + for(int i=0;i + int Set::Difference(const Set &is) + { + if(data_list.GetCount()<=0) + return(is.GetCount()); + + if(is.GetCount()<=0) + return(data_list.GetCount()); + + int count=0; + + T *obj=data_list.GetData(); + for(int i=0;i +namespace hgl +{ + /** + * 集合数据列表中不允许数据出现重复性,同时它会将数据排序,所以也可以当做有序列表使用 + */ + template class Set + { + protected: + + List data_list; + + bool FindPos(const T &,int &)const; ///<查找数据如果插入后,会所在的位置,返回是否存在这个数据 + int FindPos(const T &flag)const{int pos;FindPos(flag,pos);return(pos);} ///<查找数据如果插入后,会所在的位置 + + public: //属性 + + List & GetList ()const{return data_list;} ///<取得数据原始列表 + T * GetData ()const{return data_list.GetData();} ///<取得数据指针 + int GetCount ()const{return data_list.GetCount();} ///<取得数据总量 + + public: + + Set()=default; + virtual ~Set()=default; + + void SetCount (int count){data_list.SetCount(count);} ///<指定数据数量,一般用于批量加载前的处理 + void PreMalloc (int count){data_list.PreMalloc(count);} ///<预分配指定数量的数据空间 + + const int Find (const T &)const; ///<查找数据位置,不存在返回-1 + const bool IsMember (const T &v)const{return(Find(v)!=-1);} ///<确认是否成员 + int Add (const T &); ///<添加一个数据,返回索引号,返回-1表示数据已存在 + int Add (const T *,const int); ///<添加一批数据 + int Add (const Set &s){return Add(s.GetData(),s.GetCount());} ///<添加一批数据 + bool Update (const T &); ///<更新一个数据 + bool Delete (const T &); ///<删除一个数据 + int Delete (T *,const int); ///<删除一批数据 + bool DeleteBySerial (int); ///<删除一个数据,使用序号 + void Clear (); ///<清除数据 + void ClearData (); ///<清除数据,但不释放内存 + void DeleteClear (){data_list.DeleteClear();} ///<清除所有数据并全部调用delete + + bool Get (const int index,T &data) + { + if(index<0||index>=data_list.GetCount()) + return(false); + + data=*(data_list.GetData()+index); + return(true); + } + + int Intersection (Set &result,const Set &set); ///<取得与指定合集的交集 + int Intersection (const Set &set); ///<取得与指定合集的交集数量 + + /** + * 取得与指定交集is的合集,但排斥cs合集中的数据 + * @param result 结果合集 + * @param is 求交集的合集 + * @param cs 求排斥的合集 + * @return 结果数量 + */ + int Intersection (Set &result,const Set &is,const Set &cs); + + int Difference (const Set &is); ///<求差集数量 + + void operator =(const Set &set){data_list=set.data_list;} ///<等号操作符重载 + + bool Rand (T &)const; ///<随机取得一个 + + virtual void Enum (void (*enum_func)(T &)){data_list.Enum(enum_func);} ///<枚举所有数据成员 + };//template class Set +}//namespace hgl +#include +#endif//HGL_TYPE_SET_INCLUDE diff --git a/inc/hgl/type/Smart.h b/inc/hgl/type/Smart.h new file mode 100644 index 0000000..1184f1f --- /dev/null +++ b/inc/hgl/type/Smart.h @@ -0,0 +1,537 @@ +#ifndef HGL_SMART_INCLUDE +#define HGL_SMART_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 + + template class AutoDelete + { + T *obj; + + public: + + AutoDelete(T *o) + { + obj=o; + } + + ~AutoDelete() + { + if(obj) + delete obj; + } + + void operator = (T *o) + { + obj=o; + } + + T *operator -> (){return obj;} + + operator T *(){return obj;} + operator const T *()const{return obj;} + + void Clear() + { + obj=nullptr; + } + + T *Finish() + { + T *reuslt=obj; + + obj=nullptr; + + return reuslt; + } + };//template class AutoDelete + + template class AutoDeleteArray + { + T *obj; + + public: + + AutoDeleteArray(T *o) + { + obj=o; + } + + ~AutoDeleteArray() + { + if(obj) + delete[] obj; + } + + void operator = (T *o) + { + obj=o; + } + + T *operator -> (){return obj;} + + operator T *(){return obj;} + operator const T *()const{return obj;} + + T &operator[](int index){return obj[index];} + const T &operator[](int index)const{return obj[index];} + + void Clear() + { + obj=nullptr; + } + };//template class AutoDeleteArray +}//namespace hgl +#endif//HGL_SMART_INCLUDE diff --git a/inc/hgl/type/Stack.cpp b/inc/hgl/type/Stack.cpp new file mode 100644 index 0000000..9126ba7 --- /dev/null +++ b/inc/hgl/type/Stack.cpp @@ -0,0 +1,261 @@ +#ifndef HGL_STACK_CPP +#define HGL_STACK_CPP + +#include +namespace hgl +{ + /** + * 本类构造函数 + * @param m 如果m的值不为0,则表示使用固定的堆栈大小。固定大小的堆栈会在一开始即分配好内存。 + */ + template + Stack::Stack(int m) + { + count=0; + + if(m) + { + max_count=m; + + items=hgl_aligned_malloc(max_count); + } + else + max_count=0; + + mem_count=max_count; + } + + template + Stack::~Stack() + { + if(count||max_count)hgl_free(items); + } + + /** + * 修改堆栈的最大值 + */ + template + void Stack::SetMax(int m) + { + if(m<=0)return; + + if(mem_count==0) + { + mem_count=power_to_2(m); + items=hgl_aligned_malloc(mem_count); + } + else + if(mem_count=max_count)count=max_count-1; + } + + template + bool Stack::SetCount(int c) + { + if(c<0)return(false); + + if(c>max_count) + return(false); + + count=c; + return(true); + } + + /** + * 清除堆栈中的所有数据 + */ + template + void Stack::Clear() + { + if(max_count==0) + if(count) + { + hgl_free(items); + mem_count=0; + } + + count=0; + } + + template + bool Stack::GetItem(int n,T &data) + { + if(n<0||n>=count) + { + LOG_ERROR(OS_TEXT("从堆栈中按索引<") + OSString(n) + OS_TEXT(">取数据,超出正常范围<")+OSString(count) + OS_TEXT(">")); + + return(false); + } + + data=items[n]; + return(true); + } + + /** + * 访问堆栈中的一个数据,但不清除它 + * @param t 取出的数据保存地 + * @return 是否成功取出数据 + */ + template + bool Stack::Peek(T &t) + { + if(count) + { + memcpy(&t,items+(count-1),sizeof(T)); +// t=items[count-1]; + return(true); + } + else + return(false); + } + + /** + * 从堆栈中取出一个数据 + * @param t 取出的数据保存地 + * @return 是否成功取出数据 + */ + template + bool Stack::Pop(T &t) + { + if(count) + { +// t=items[--count]; + count--; + memcpy(&t,items+count,sizeof(T)); + + if(max_count==0) + { + if(count==0) + { + hgl_free(items); + + mem_count=0; + } + //else + //items=(T *)hgl_realloc(items,count*sizeof(T)); + } + + return(true); + } + else + return(false); + } + + /** + * 向堆栈中放入一个数据 + * @param data 要放入的数据指针 + * @return true 放入数据成功 + * @return false 放入数据失败 + */ + template + bool Stack::Push(T &data) + { + if(max_count) + { + if(count>=max_count)return(false); + } + else + { + if(count) + { + if(count+1>mem_count) + { + mem_count=power_to_2(count+1); + + items=(T *)hgl_realloc(items,mem_count*sizeof(T)); + } + } + else + { + items=hgl_aligned_malloc(1); + + mem_count=1; + } + } + +// items[count++]=data; + memcpy(items+count,&data,sizeof(T)); + count++; + + return(true); + } + + /** + * 向堆栈中放入多个数据 + * @param data 要放入的数据 + * @param data_count 要放入的数据个数 + * @return true 放入数据成功 + * @return false 放入数据失败 + */ + template + bool Stack::MultiPush(T *data,int data_count) + { + if(max_count) + { + if(count>=max_count)return(false); + } + else + { + if(count) + { + if(count+data_count>mem_count) + { + mem_count=power_to_2(count+data_count); + + items=(T *)hgl_realloc(items,mem_count*sizeof(T)); + } + } + else + { + items=hgl_aligned_malloc(data_count); + + mem_count=data_count; + } + } + + memcpy(items+count,data,data_count*sizeof(T)); + count+=data_count; + + return(true); + } + + template + void Stack::operator =(const Stack &ori) + { + if(ori.count==0)return; + + Clear(); + + max_count=ori.count; + count=ori.count; + + if(max_count==0) + mem_count=count; + else + mem_count=max_count; + + items=hgl_aligned_malloc(mem_count); + + memcpy(items,ori.items,mem_count*sizeof(T)); + } +}//namespace hgl + +namespace hgl +{ + template + void StackObject::Clear() + { + for(int i=0;icount;i++) + delete this->items[i]; + + Stack::Clear(); + } +}//namespace hgl +#endif//HGL_STACK_CPP diff --git a/inc/hgl/type/Stack.h b/inc/hgl/type/Stack.h new file mode 100644 index 0000000..8d3926c --- /dev/null +++ b/inc/hgl/type/Stack.h @@ -0,0 +1,59 @@ +#ifndef HGL_STACK_INCLUDE +#define HGL_STACK_INCLUDE + +#include +namespace hgl +{ + /** + * Stack模板类用于保存一个先进后出、后进先出的数据堆栈 + * + * 注:这个类还在测试中,请不要修改这个类的源代码,如有修改意见,请致电作者。 + */ + template class Stack ///堆栈顺序数据访问类 + { + protected: + + int max_count; + int mem_count; + int count; + T *items; + + public: //属性 + + int GetCount() const{return count;} ///<取得堆栈中数据的个数 + bool SetCount(int c); ///<直接设置堆栈中数据的个数 + + int GetMax () const{return max_count;} ///<取得堆栈中的最大数据个数 + void SetMax (int); ///<设置堆栈中的最大数据个数 + + T * GetData () {return items;} ///<取得原始数据 + + public: //方法 + + Stack(int=0); + virtual ~Stack(); + + bool Peek(T &); ///<尝试访问一个数据 + virtual bool Pop(T &); ///<弹出一个数据 + bool Push(T &); ///<压入一个数据 + bool MultiPush(T *,int); ///<放入多个数据 + + virtual void Clear(); ///<清除所有数据 + + bool GetItem(int,T &); + + virtual void operator =(const Stack &); + };//template class Stack + + template class StackObject:public Stack ///堆栈对象 + { + public: + + using Stack::Stack; + virtual ~StackObject(){Clear();}; + + void Clear(); + };//template class StackObject +}//namespace hgl +#include +#endif//HGL_STACK_INCLUDE diff --git a/inc/hgl/type/StdString.h b/inc/hgl/type/StdString.h new file mode 100644 index 0000000..40f99d8 --- /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) +{ + hgl::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(),int(str.size())); +} + diff --git a/inc/hgl/type/StrChar.h b/inc/hgl/type/StrChar.h new file mode 100644 index 0000000..614ed47 --- /dev/null +++ b/inc/hgl/type/StrChar.h @@ -0,0 +1,2593 @@ +#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; + } + + /** + * 复制一个字符串,并将字符串全部转换成小写 + */ + template + uint lower_cpy(T *target,const T *source) + { + if(!target||!source)return 0; + uint count=0; + + while(*source) + { + if(*source>='A'&&*source<='Z') + *target=*source+32; + else + *target=*source; + + ++target; + ++source; + ++count; + } + + *target=0; + return count; + } + + /** + * 复制一个字符串,并将字符串全部转换成大写 + */ + template + uint upper_cpy(T *target,const T *source) + { + if(!target||!source)return 0; + uint count=0; + + while(*source) + { + if(*source>='a'&&*source<='z') + *target=*source-32; + else + *target=*source; + + ++target; + ++source; + ++count; + } + + *target=0; + return count; + } + + /** + * 复制一个字符串,并将字符串全部转换成小写 + */ + template + uint lower_cpy(T *target,const T *source,int source_max) + { + if(!target||!source)return 0; + uint count=0; + + while(*source&&source_max>0) + { + if(*source>='A'&&*source<='Z') + *target=*source+32; + else + *target=*source; + + ++target; + ++source; + ++count; + --source_max; + } + + *target=0; + + return count; + } + + /** + * 复制一个字符串,并将字符串全部转换成大写 + */ + template + uint upper_cpy(T *target,const T *source,int source_max) + { + if(!target||!source)return 0; + uint count=0; + + while(*source&&source_max>0) + { + if(*source>='a'&&*source<='z') + *target=*source-32; + else + *target=*source; + + ++target; + ++source; + ++count; + --source_max; + } + + *target=0; + return count; + } + + /** + * 复制一个字符串,将字符串全部转换成小写,同时清空字符串中的空格 + */ + template + uint lower_clip_cpy(T *target,const T *source) + { + if(!target||!source)return 0; + uint count=0; + + while(*source) + { + if(*source!=' ') + { + if(*source>='A'&&*source<='Z') + *target=*source+32; + else + *target=*source; + + ++target; + ++count; + } + + ++source; + } + + *target=0; + + return count; + } + + /** + * 复制一个字符串,并将字符串全部转换成大写,同时清空字符串中的空格 + */ + template + uint upper_clip_cpy(T *target,const T *source) + { + if(!target||!source)return 0; + uint count=0; + + while(*source) + { + if(*source!=' ') + { + if(*source>='a'&&*source<='z') + *target=*source-32; + else + *target=*source; + + ++target; + ++count; + } + + ++source; + } + + *target=0; + return count; + } + + /** + * 复制一个字符串,将字符串全部转换成小写,同时清空字符串中的空格 + */ + template + uint lower_clip_cpy(T *target,const T *source,int source_max) + { + if(!target||!source)return 0; + uint count=0; + + while(*source&&source_max>0) + { + if(*source!=' ') + { + if(*source>='A'&&*source<='Z') + *target=*source+32; + else + *target=*source; + + ++target; + ++count; + } + + ++source; + --source_max; + } + + *target=0; + + return count; + } + + /** + * 复制一个字符串,并将字符串全部转换成大写,同时清空字符串中的空格 + */ + template + uint upper_clip_cpy(T *target,const T *source,int source_max) + { + if(!target||!source)return 0; + uint count=0; + + while(*source&&source_max>0) + { + if(*source!=' ') + { + if(*source>='a'&&*source<='z') + *target=*source-32; + else + *target=*source; + + ++target; + ++count; + } + + ++source; + --source_max; + } + + *target=0; + return count; + } + + /** + * 统计在字符串中某个字符的出现次数 + * @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/type/StringInstance.h b/inc/hgl/type/StringInstance.h new file mode 100644 index 0000000..8ca170a --- /dev/null +++ b/inc/hgl/type/StringInstance.h @@ -0,0 +1,500 @@ +#ifndef HGL_TYPE_STRING_INSTANCE_INCLUDE +#define HGL_TYPE_STRING_INSTANCE_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/StringList.h b/inc/hgl/type/StringList.h new file mode 100644 index 0000000..70cffa0 --- /dev/null +++ b/inc/hgl/type/StringList.h @@ -0,0 +1,712 @@ +#ifndef HGL_STRINGLIST_INCLUDE +#define HGL_STRINGLIST_INCLUDE + +#include +#include +#include +#include +#include + +namespace hgl +{ + class HAC; + + /** + * 字符串列表处理类,用于保存字符串列表。 + */ + template class StringList ///字符串列表处理类 + { + static T NullString; + + protected: + + ObjectList Items; + + public: //属性 + + T **GetDataList()const{return Items.GetData();} ///<取得字符串列表指针数据 + const int GetCount()const{return Items.GetCount();} ///<字符串列表行数虚拟变量 + + public: //操作符重载 + + T &operator[](int n)const + { + if(n<0||n>=Items.GetCount()) + return NullString; + + T *result=Items[n]; + + if(result) + return(*result); + else + return NullString; + } + + StringList &operator = (const StringList &sl) + { + Clear(); + + const int n=sl.GetCount(); + T *str; + + for(int i=0;iAdd(*str); + } + + return(*this); + } + + public: //方法 + + StringList()=default; ///<本类构造函数 + //注:这里不要实现StringList(T &)或StringList(T *)之类 + virtual ~StringList(){Clear();} ///<本类析构函数 + + /** + * 增加一行字符串到当前列表中 + * @param str 要增加的字符串 + * @return 增加字符串成功后的索引 + */ + int Add(const T &str){return Items.Add(new T(str));} ///<添加字符串 + + /** + * 增加一个字符串列表到当前字符串列表中 + * @param sl 要增加的字符串列表 + */ + int Add(const StringList &sl) ///<添加字符串 + { + const int count=sl.GetCount(); + + for(int i=0;iComp(str)==0) + { + Items.Delete(count); + result++; + } + } + + return(result); + } + + /** + * 查找字符串 + * @param str 要查找的字符串 + * @return 查找到的字符串的索引,未找到返回-1 + */ + int Find(const T &str) const ///<查找字符串,未找到返回-1 + { + const int count=Items.GetCount(); + + for(int i=0;iComp(str)==0) + return(i); + + return(-1); + } + + /** + * 查找字符串,英文无视大小写 + * @param str 要指找的字符串 + * @return 查找到的字符串的索引,未找到返回-1 + */ + int CaseFind(const T &str) const ///<查找字符串,英文无视大小写,未找到返回-1 + { + const int count=Items.GetCount(); + + for(int i=0;iCaseComp(str)==0) + return(i); + + return(-1); + } + + /** + * 查找字符串,并指定最大比较长度 + * @param str 要查找的字符串 + * @param cn 限定的要查找字符串的最大长度 + * @return 查找到的字符串的索引,未找到返回-1 + */ + int Find(const T &str,const int cn) const ///<查找字符串,未找到返回-1 + { + const int count=Items.GetCount(); + + for(int i=0;iComp(str,cn)==0) + return(i); + + return(-1); + } + + /** + * 查找字符串,英文无视大小写,并指定最大比较长度 + * @param str 要指找的字符串 + * @param cn 限定的要查找字符串的最大长度 + * @return 查找到的字符串的索引,未找到返回-1 + */ + int CaseFind(const T &str,const int cn) const ///<查找字符串,英文无视大小写,未找到返回-1 + { + const int count=Items.GetCount(); + + for(int i=0;iCaseComp(str,cn)==0) + return(i); + + return(-1); + } + + /** + * 在指定位置插入一个字符串 + * @param index 要插入字符串的位置 + * @param str 要插入的字符串 + */ + void Insert(int index,const T &str) ///<在指定位置插入一个字符串 + { + if(index::Insert(index,new T(str)); + } + + /** + * 交换两个字符串的位置 + * @param index1 第一个字符串的位置 + * @param index2 第二个字符串的位置 + */ + void Exchange(int index1,int index2) ///<交换两行字符串 + { + Items.Exchange(index1,index2); + } + + T &GetString(int n)const{return *(Items[n]);} ///<取得指定行字符串 + };//template class StringList + + template T StringList::NullString; ///<空字符串实例 + + /** + * 以不可打印字符为分隔拆解一个字符串到一个字符串列表 + * @param sl 字符串列表处理类 + * @param str 字符串 + * @param size 字符串长度 + * @return 字符串行数 + */ + template int SplitToStringListBySpace(StringList > &sl,const T *str,int size) + { + if(!str||size<=0)return(-1); + + int count=0; + const T *p,*sp; + + sp=p=str; + + while(size>0) + { + if(!(*p)) + { + if(p>sp) + { + sl.Add(BaseString(sp,p-sp)); + ++count; + } + + --size; + return count; + } + + if(isspace(*p)) + { + if(p>sp) + { + sl.Add(BaseString(sp,p-sp)); + ++count; + } + + sp=p+1; ///<跳过分割符 + } + + ++p; + --size; + } + + if(p>sp) + { + sl.Add(BaseString(sp,p-sp)); + ++count; + } + + return count; + }//int SplitToStringList + + /** + * 以指定字符为分隔拆解一个字符串到一个字符串列表 + * @param sl 字符串列表处理类 + * @param str 字符串 + * @param size 字符串长度 + * @param split_char 分隔字符 + * @return 字符串行数 + */ + template int SplitToStringList(StringList > &sl,const T *str,int size,const T &split_char) + { + if(!str||size<=0)return(-1); + + int count=0; + const T *p,*sp; + + sp=p=str; + + while(size>0) + { + if(!(*p)) + { + if(p>sp) + { + sl.Add(BaseString(sp,p-sp)); + ++count; + } + + --size; + return count; + } + + if(*p==split_char) + { + if(p>sp) + { + sl.Add(BaseString(sp,p-sp)); + ++count; + } + + sp=p+1; ///<跳过分割符 + } + + ++p; + --size; + } + + if(p>sp) + { + sl.Add(BaseString(sp,p-sp)); + ++count; + } + + return count; + }//int SplitToStringList + + template int SplitToStringListFromString(StringList > &sl,const BaseString &str,const T &split_char) + { + return SplitToStringList(sl,str.c_str(),str.Length(),split_char); + } + + /** + * 以指定字符为分隔拆解一个字符串到一个字符串列表 + * @param sl 字符串列表处理类 + * @param str 字符串 + * @param size 字符串长度 + * @param split_char 分隔字符 + * @param maxSize 最多执行次数 + * @return 字符串行数 + */ + template int SplitToStringList(StringList > &sl,const T *str,int size,const T &split_char,int maxSize) + { + if(!str||size<=0)return(-1); + + int count=0; + const T *p,*sp; + + sp=p=str; + + while(size>0) + { + if(!(*p)) + { + if(p>sp) + { + sl.Add(BaseString(sp,p-sp)); + ++count; + } + + --size; + return count; + } + + if(*p==split_char) + { + if(p>sp) + { + sl.Add(BaseString(sp,p-sp)); + ++count; + } + + sp=p+1; ///<跳过分割符 + if(maxSize >0 && count >=maxSize-1) + { + ++p; + --size; + if(size > 0) + { + sl.Add(BaseString(sp,size)); + ++count; + } + + return count; + } + } + + ++p; + --size; + } + + if(p>sp) + { + sl.Add(BaseString(sp,p-sp)); + ++count; + } + + return count; + }//int SplitToStringList + + template int SplitToStringList(StringList > &sl,const BaseString &str,const T &split_char,int maxSize) + { + return SplitToStringList(sl,str.c_str(),str.Length(),split_char,maxSize); + } + + /** + * 拆解一个多行字符串到一个字符串列表 + * @param sl 字符串列表处理类 + * @param str 字符串 + * @param size 字符串长度 + * @return 字符串行数 + */ + template int SplitToStringListByEnter(StringList > &sl,const T *str,int size) + { + if(!str||size<=0)return(-1); + + int count=0; + const T *p,*sp; + + sp=p=str; + + while(size>0) + { + if(!(*p)) + { + if(p>sp) + { + sl.Add(BaseString(sp,p-sp)); + ++count; + } + + --size; + return count; + } + + if(*p==0x0D) // \r + { + sl.Add(BaseString(sp,p-sp)); + ++count; + + ++p; + --size; + + if(*p==0x0A) // \r\n,Windows下的断行是(\r\n)0x0D+0x0A,而其它系统是仅有一个 + { + ++p; + --size; + } + + sp=p; + } + else + if(*p==0x0A) // \n + { + sl.Add(BaseString(sp,p-sp)); + ++count; + + ++p; + --size; + + sp=p; + } + else + { + ++p; + --size; + } + } + + if(p>sp) + { + sl.Add(BaseString(sp,p-sp)); + ++count; + } + + return count; + }//int SplitToStringList + + template int SplitToStringList(StringList > &sl,const BaseString &str) + { + return SplitToStringList(sl,str.c_str(),str.Length()); + } + + /** + * 拆解一个多行字符串到多个字符串列表 + * @param sl 字符串列表处理类 + * @param slc 字符串列表处理类个数 + * @param str 字符串 + * @param size 字符串长度 + * @return 字符串行数 + */ + template int SplitToMultiStringList(StringList > **sl,int slc,const T *str,int size) + { + if(!str||size<=0)return(-1); + if(slc<=0)return(-1); + + int index=0; + int count=0; + const T *p,*sp; + + sp=p=str; + + while(size>0) + { + if(!(*p)) + { + if(p>sp) + { + sl[index]->Add(BaseString(sp,p-sp)); + if(++index==slc)index=0; + ++count; + } + + --size; + return count; + } + + if(*p==0x0D) // \r + { + sl[index]->Add(BaseString(sp,p-sp)); + if(++index==slc)index=0; + + ++count; + + ++p; + --size; + + if(*p==0x0A) // \r\n,Windows下的断行是(\r\n)0x0D+0x0A,而其它系统是仅有一个 + { + ++p; + --size; + } + + sp=p; + } + else + if(*p==0x0A) // \n + { + sl[index]->Add(BaseString(sp,p-sp)); + if(++index==slc)index=0; + + ++count; + + ++p; + --size; + + sp=p; + } + else + { + ++p; + --size; + } + } + + if(p>sp) + { + sl[index]->Add(BaseString(sp,p-sp)); + ++count; + } + + return count; + }//int SplitToStringList + + template int SplitToMultiStringList(StringList > **sl,int slc,const BaseString &str) + { + if(!sl||slc<=0)return(false); + + if(slc==1) + return SplitToStringList(**sl,str.c_str(),str.Length()); + else + return SplitToMultiStringList(sl,slc,str.c_str(),str.Length()); + } + + using UTF8StringList =StringList; + using UTF16StringList =StringList; + using UTF32StringList =StringList; + using AnsiStringList =StringList; + using WideStringList =StringList; + using OSStringList =StringList; + + template struct ReadStringFromDIS + { + bool ReadString(io::DataInputStream *dis,T &str); + }; + + template struct ReadStringFromDIS + { + bool ReadString(io::DataInputStream *dis,T &str) + { + return dis->ReadUTF8String(str); + } + }; + + template struct ReadStringFromDIS + { + bool ReadString(io::DataInputStream *dis,T &str) + { + return dis->ReadUTF16LEString(str); + } + }; + + template struct ReadStringFromDIS + { + bool ReadString(io::DataInputStream *dis,T &str) + { + return dis->ReadUTF16BEString(str); + } + }; + + /** + * 从DataInputStream流中读取一个字符串列表 + * @param sl 字符串列表处理类 + * @param dis 数据输入流 + * @return 字符串行数 + */ + template int LoadStringList(StringList > &sl,io::DataInputStream *dis) + { + if(!dis)return(-1); + + int count; + int result=0; + + if(!dis->ReadInt32(count)) + return(-2); + + ReadStringFromDIS,bom> rsfd; + + BaseString str; + + for(int i=0;i(sl,dis);} + inline int LoadUTF16LEStringList (UTF16StringList & sl,io::DataInputStream *dis){return LoadStringList(sl,dis);} + inline int LoadUTF16BEStringList (UTF16StringList & sl,io::DataInputStream *dis){return LoadStringList(sl,dis);} + + int LoadStringListFromText(UTF8StringList &sl,void *data,const int size,const CharSet &default_charset=UTF8CharSet); ///<从文件加载一个文本块到UTF8StringList + int LoadStringListFromText(UTF16StringList &sl,void *data,const int size,const CharSet &default_charset=UTF16LECharSet); ///<从文件加载一个文本块到UTF16StringList + + int LoadStringListFromTextFile(UTF8StringList &sl,const OSString &filename,const CharSet &default_charset=UTF8CharSet); ///<从文件加载一个文本文件到UTF8StringList + int LoadStringListFromTextFile(UTF16StringList &sl,const OSString &filename,const CharSet &default_charset=UTF16LECharSet); ///<从文件加载一个文本文件到UTF16StringList + + template struct WriteStringToDOS + { + bool WriteString(io::DataOutputStream *dos,const T &str); + }; + + template struct WriteStringToDOS + { + bool WriteString(io::DataOutputStream *dos,const T &str) + { + return dos->WriteUTF8String(str); + } + }; + + template struct WriteStringToDOS + { + bool WriteString(io::DataOutputStream *dos,const T &str) + { + return dos->WriteUTF16LEString(str); + } + }; + + template struct WriteStringToDOS + { + bool WriteString(io::DataOutputStream *dos,const T &str) + { + return dos->WriteUTF16BEString(str); + } + }; + + template int WriteStringList(io::DataOutputStream *dos,const StringList &sl) + { + WriteStringToDOS wtd; + + const int32 count=sl.GetCount(); + int result=0; + + if(!dos->WriteInt32(count)) + return(-2); + + for(int32 i=0;i int SaveUTF8StringList(io::DataOutputStream *dos,const StringList &sl) + { + return WriteStringList(dos,sl); + } + + template int SaveUTF16LEStringList(io::DataOutputStream *dos,const StringList &sl) + { + return WriteStringList(dos,sl); + } + + template int SaveUTF16BEStringList(io::DataOutputStream *dos,const StringList &sl) + { + return WriteStringList(dos,sl); + } +}//namespace hgl +#endif//HGL_STRINGLIST_INCLUDE diff --git a/inc/hgl/type/Vertex2.cpp b/inc/hgl/type/Vertex2.cpp new file mode 100644 index 0000000..a63d7c4 --- /dev/null +++ b/inc/hgl/type/Vertex2.cpp @@ -0,0 +1,147 @@ +#ifndef HGL_VERTEX_2_CPP +#define HGL_VERTEX_2_CPP + +#include +#include + +namespace hgl +{ + template + void Vertex2::Scale(double vx,double vy,double scale) + { + x=vx+(x-vx)*scale; + y=vy+(y-vy)*scale; + } + + template + void Vertex2::Scale(double vx,double vy,double sx,double sy) + { + x=vx+(x-vx)*sx; + y=vy+(y-vy)*sy; + } + + template template + void Vertex2::Scale(const Vertex2 &v,double scale) + { + x=v.x+(x-v.x)*scale; + y=v.y+(y-v.y)*scale; + } + + template template + void Vertex2::Scale(const Vertex2 &v,double sx,double sy) + { + x=v.x+(x-v.x)*sx; + y=v.y+(y-v.y)*sy; + } + + template + void Vertex2::Rotate(double vx,double vy,double ang) + { + double as,ac; + double nx,ny; + + as=sin(ang*HGL_PI/180.0f); + ac=cos(ang*HGL_PI/180.0f); + + nx=vx+((x-vx)*ac-(y-vy)*as); + ny=vy+((x-vx)*as+(y-vy)*ac); + + x=nx;y=ny; + } + + template + float Vertex2::Length() const + { + return sqrt(x*x+y*y); + } + + template + float Vertex2::Length(float vx,float vy) const + { + float w=x-vx; + float h=y-vy; + + return float(sqrt(double(w*w+h*h))); + } + + template + float Vertex2::Angle(float vx,float vy) const + { + if(vx==x) + { + if(vy>y)return(90); + else return(270); + } + + if(vy==y) + { + if(vx>x)return(0); + else return(180); + } + + // asin 参数范围必须在 -1 到 +1 之间,否则会报错 + // + + double xx=vx-x; + double yy=vy-y; + + double ang = atan(yy/xx)/HGL_PI*180.0f; + + if(xx<0) + return(ang+180); + else + { + if(yy<0) + return(ang+360); + else + return(ang); + } + } + + template template + Vertex2 Vertex2::To(const Vertex2 &target,double pos)const + { + if(pos==0)return(*this);else + if(pos==1)return(target);else + { + Vertex2 result; + + result.x=x+(target.x-x)*pos; + result.y=y+(target.y-y)*pos; + + return(result); + } + } + + template + void Vertex2::Normalize() + { + double size=sqrt(x*x+y*y); + + if(size>0) + { + x/=size; + y/=size; + } + + x=0;y=0; + } + + template template + Vertex2 Vertex2::ResizeLength(const Vertex2 &target,double scale)const + { + Vertex2 result; + + result.x=target.x+(x-target.x)*scale; + result.y=target.y+(y-target.y)*scale; + + return(result); + } + + template template + Vertex2 Vertex2::ToLength(const Vertex2 &target,double new_length)const + { + return ResizeLength(target,new_length/Length(target)); + } +}//namespace hgl +#endif//HGL_VERTEX_2_CPP diff --git a/inc/hgl/type/Vertex2.h b/inc/hgl/type/Vertex2.h new file mode 100644 index 0000000..1c5ce34 --- /dev/null +++ b/inc/hgl/type/Vertex2.h @@ -0,0 +1,113 @@ +#ifndef HGL_VERTEX_2_INCLUDE +#define HGL_VERTEX_2_INCLUDE + +#include +#include +namespace hgl +{ + /** + * 2D顶点坐标类模板 + */ + template class Vertex2 ///XY 2D顶点坐标类模板 + { + public: + + T x,y; ///<坐标值 + + public: + + Vertex2(){x=y=0;} ///<本类构造函数 + Vertex2(T nx,T ny){x=nx,y=ny;} ///<本类构造函数 + template + Vertex2(const Vertex2 &v){x=v.x,y=v.y;} ///<本类构造函数 + + void Zero(){x=0,y=0;} ///<将x和y全清为0 + void One(){x=1,y=1;} ///<将x和y全清为1 + + void Set(float nx,float ny){x=nx,y=ny;} ///<设置坐标值为nx,ny + + void Flip(float vx,float vy){FlipX(vy);FlipY(vx);} ///<对应vx,vy做翻转 + template void Flip(const Vertex2 &v){Flip(v.x,v.y);} ///<对应v做翻转 + + void FlipX(){y=-y;} ///<对应X轴翻转 + void FlipY(){x=-x;} ///<对应Y轴翻转 + void FlipX(float v){y=v-(y-v);} ///<对应指定X轴做翻转 + void FlipY(float v){x=v-(x-v);} ///<对应指定Y轴做翻转 + + void Scale(double,double,double); ///<相对某一点做缩放 + void Scale(double,double,double,double); ///<相对某一点做缩放 + template void Scale(const Vertex2 &,double); ///<相对某一点做缩放 + template void Scale(const Vertex2 &,double,double); ///<相对某一点做指定比例的缩放 + + void Rotate(double,double,double); ///<绕指定坐标旋转指定角度 + template void Rotate(const Vertex2 &v,double ang){Rotate(v.x,v.y,ang);} ///<绕指定坐标旋转指定角度 + + void Move(float vx,float vy){x+=vx;y+=vy;} ///<移动 + template + void Scale(const Vertex2 &v,const Vertex2 &l){Scale(v,l.x,l.y);} ///<相对某一点做指定比例的缩放 + + float Length()const; ///<计算当前点与零点之间的距离 + float Length(float vx,float vy)const; ///<计算当前点与指定点之间的距离 + float Angle(float vx,float vy)const; ///<计算当前点与指定点之间的角度 + + template float Length(const Vertex2 &v)const{return(Length(v.x,v.y));} ///<计算当前点与指定点之间的距离 + template float Angle(const Vertex2 &v)const{return(Angle(v.x,v.y));} ///<计算当前点与指定点之间的角度 + void Normalize(); + + template Vertex2 ResizeLength(const Vertex2 &,double)const; ///<调整这个方向上两点的距离 + template Vertex2 ToLength(const Vertex2 &,double)const; ///<按这个方向将两点的距离调到指定长度 + + template Vertex2 To(const Vertex2 &,double)const; + + public: //操作符重载 + + template bool operator == (const Vertex2 &v)const + { + if(x!=v.x)return(false); + if(y!=v.y)return(false); + return(true); + } + + template bool operator != (const Vertex2 &v)const + { + if(x!=v.x)return(true); + if(y!=v.y)return(true); + return(false); + } + + Vertex2 &operator = (const float *v){x=*v++;y=*v;return *this;} + + template Vertex2 &operator +=(const Vertex2 &v){x+=v.x;y+=v.y;return *this;} + template Vertex2 &operator -=(const Vertex2 &v){x-=v.x;y-=v.y;return *this;} + template Vertex2 &operator *=(const Vertex2 &v){x*=v.x;y*=v.y;return *this;} + template Vertex2 &operator /=(const Vertex2 &v){x/=v.x;y/=v.y;return *this;} + + Vertex2 &operator *=(const float v){x*=v;y*=v;return *this;} + Vertex2 &operator /=(const float v){x/=v;y/=v;return *this;} + + template Vertex2 operator + (const Vertex2 &v)const{return(Vertex2(x+v.x,y+v.y));} + template Vertex2 operator - (const Vertex2 &v)const{return(Vertex2(x-v.x,y-v.y));} + template Vertex2 operator * (const Vertex2 &v)const{return(Vertex2(x*v.x,y*v.y));} + template Vertex2 operator / (const Vertex2 &v)const{return(Vertex2(x/v.x,y/v.y));} + + Vertex2 operator * (const float v)const{return(Vertex2(x*v,y*v));} + Vertex2 operator / (const float v)const{return(Vertex2(x/v,y/v));} + + Vertex2 operator - () const {return(Vertex2(-x,-y));} + + operator T *() const {return(( T *)this);} ///<使得本类可以直接当做T *使用 + operator const T *() const {return((const T *)this);} ///<使得本类可以直接当做const T *使用 + };//class Vertex2 + + typedef Vertex2 Vertex2i; + typedef Vertex2 Vertex2ui; + typedef Vertex2 Vertex2f; + typedef Vertex2 Vertex2d; + + typedef Vertex2 Vertex2b; + typedef Vertex2 Vertex2ub; + typedef Vertex2 Vertex2s; + typedef Vertex2 Vertex2us; +}//namespace hgl +#include +#endif//HGL_VERTEX_2_INCLUDE diff --git a/inc/hgl/type/_Object.h b/inc/hgl/type/_Object.h new file mode 100644 index 0000000..5252593 --- /dev/null +++ b/inc/hgl/type/_Object.h @@ -0,0 +1,36 @@ +#ifndef HGL__OBJECT_INCLUDE +#define HGL__OBJECT_INCLUDE + +namespace hgl +{ + /** + * 最终基类 + */ + class _Object ///最终基类 + { + public: + + virtual ~_Object()=default; ///<本类析构函数 + };//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 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..994a9c8 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,64 @@ +file(GLOB TYPE_TEMPLATE_HEADER ${CMCORE_ROOT_INCLUDE_PATH}/hgl/type/*.h) +file(GLOB TYPE_TEMPLATE_SOURCE ${CMCORE_ROOT_INCLUDE_PATH}/hgl/type/*.cpp) + +SET(SYSTEM_INFO_SOURCE SystemInfo.cpp) + +SET(BASE_TYPE_SOURCE +# DataType/Info.cpp +# DataType/BitArray.cpp + DataType/Color.cpp + DataType/Color3f.cpp + DataType/Color4f.cpp +# DataType/FontInfo.cpp + DataType/StringList.cpp + DataType/Endian.cpp) + +SOURCE_GROUP("DataType\\Template\\Header Files" FILES ${TYPE_TEMPLATE_HEADER}) +SOURCE_GROUP("DataType\\Template\\Source Files" FILES ${TYPE_TEMPLATE_SOURCE}) +SOURCE_GROUP("DataType" FILES ${BASE_TYPE_SOURCE}) + +SET(BASE_IO_SOURCE + IO/DataInputStream.cpp + IO/DataOutputStream.cpp + IO/FileAccess.cpp + IO/FileInputStream.cpp + IO/FileOutputStream.cpp + IO/IOType.cpp + IO/RandomAccessFile.cpp + IO/TextOutputStream.cpp) + +SOURCE_GROUP("IO" FILES ${BASE_IO_SOURCE}) + +SET(BASE_FILE_SYSTEM_SOURCE + FileSystem/FileSystem.cpp + FileSystem/EnumFile.cpp) + +SOURCE_GROUP("FileSystem" FILES ${BASE_FILE_SYSTEM_SOURCE}) + +SET(BASE_OTHER_SOURCE + Other/CodePage.cpp + Other/DateTime.cpp +# Other/ExpendString.cpp + Other/ThreadFunc.cpp + Other/TimeCount.cpp + Other/TimeVal.cpp) + +SOURCE_GROUP("Other" FILES ${BASE_OTHER_SOURCE}) + +SET(BASE_PLUG_IN_SOURCE + PlugIn/ExternalModule.cpp +# PlugIn/PlugIn.cpp +) + +SOURCE_GROUP("PlugIn" FILES ${BASE_PLUG_IN_SOURCE}) + +add_library(CMCore STATIC #${SYSTEM_INFO_SOURCE} + ${TYPE_TEMPLATE_HEADER} + ${TYPE_TEMPLATE_SOURCE} + ${BASE_TYPE_SOURCE} + ${BASE_IO_SOURCE} + ${BASE_FILE_SYSTEM_SOURCE} + ${BASE_OTHER_SOURCE} + ${BASE_PLUG_IN_SOURCE}) + +set_property(TARGET CMCore PROPERTY FOLDER "CM/Core") diff --git a/src/DataType/Color.cpp b/src/DataType/Color.cpp new file mode 100644 index 0000000..dbec16f --- /dev/null +++ b/src/DataType/Color.cpp @@ -0,0 +1,228 @@ +#include + +namespace hgl +{ + #undef DEF_COLOR + #define DEF_COLOR(eng_name,red,green,blue,chs_name) { \ + red, \ + green, \ + blue, \ + int(double(red)*0.299+double(green)*0.587+double(blue)*0.114), \ + \ + float(double(red)/255.0f), \ + float(double(green)/255.0f), \ + float(double(blue)/255.0f), \ + float((double(red)*0.299+double(green)*0.587+double(blue)*0.114)/255.0f),\ + \ + #eng_name, \ + U16_TEXT(chs_name) \ + }, + + COLOR_DEF prv_color[ceEnd+1]= + { + DEF_COLOR(None, 0, 0, 0,"") + + DEF_COLOR(AliceBlue, 240,248,255,"艾利斯兰") + DEF_COLOR(AndroidGreen, 164,198, 57,"安卓绿") + DEF_COLOR(AntiqueWhite, 250,235,215,"古董白") + DEF_COLOR(AppleGreen, 141,182, 0,"苹果绿") + DEF_COLOR(Aqua, 0,255,255,"浅绿色") + DEF_COLOR(AquaMarine, 127,255,212,"碧绿色") + + DEF_COLOR(ArdenRed, 202, 23, 36,"雅顿红") //取自美国官网LOGO图片 + + DEF_COLOR(Azure, 240,255,255,"天蓝色") + DEF_COLOR(BananaMania, 250,231,181,"香蕉黄(芯)") + DEF_COLOR(BananaYellow, 255,225, 53,"香蕉黄(皮)") + DEF_COLOR(Beige, 245,245,220,"米色") + DEF_COLOR(Bisque, 255,228,196,"桔黄色") + DEF_COLOR(Black, 0, 0, 0,"黑色") + DEF_COLOR(BlanchedAlmond, 255,235,205,"白杏色") + DEF_COLOR(Blue, 0, 0,255,"蓝色") + DEF_COLOR(BlueViolet, 138, 43,226,"紫罗兰蓝") + DEF_COLOR(Brown, 165, 42, 42,"褐色") + DEF_COLOR(BurlyWood, 222,184,135,"实木色") + DEF_COLOR(CadetBlue, 95,158,160,"军兰色") + DEF_COLOR(CaribbeanGreen, 0,204,153,"加勒比海绿") + DEF_COLOR(Chartreuse, 127,255, 0,"黄绿色") + DEF_COLOR(CherryBlossomPink, 255,183,197,"樱桃花粉") + DEF_COLOR(Chocolate, 210,105, 30,"巧克力色") + DEF_COLOR(Coral, 255,127, 80,"珊瑚色") + DEF_COLOR(CornflowerBlue, 100,149,237,"菊花兰") + DEF_COLOR(Cornsilk, 255,248,220,"米绸色") + DEF_COLOR(Crimson, 220, 20, 60,"暗深红") + DEF_COLOR(Cyan, 0,255,255,"青色") + DEF_COLOR(DarkBlue, 0, 0,139,"暗蓝色") + DEF_COLOR(DarkCyan, 0,139,139,"暗青色") + DEF_COLOR(DarkGoldenrod, 184,134, 11,"暗金黄") + DEF_COLOR(DarkGray, 169,169,169,"暗灰色") + DEF_COLOR(DarkGreen, 0,100, 0,"暗绿色") + DEF_COLOR(DarkGrey, 169,169,169,"暗白色") + DEF_COLOR(DarkKhaki, 189,183,107,"暗黄褐色") + DEF_COLOR(DarkMagenta, 139, 0,139,"暗洋红") + DEF_COLOR(DarkOliveGreen, 85,107, 47,"暗橄榄绿") + DEF_COLOR(DarkOrange, 255,140, 0,"暗桔黄") + DEF_COLOR(DarkOrchid, 153, 50,204,"暗紫色") + DEF_COLOR(DarkRed, 139, 0, 0,"暗红色") + DEF_COLOR(DarkSalmon, 233,150,122,"暗肉色") + DEF_COLOR(DarkSeaGreen, 143,188,143,"暗海兰") + DEF_COLOR(DarkSlateBlue, 72, 61,139,"暗灰兰") + DEF_COLOR(DarkSlateGray, 47, 79, 79,"墨绿色") + DEF_COLOR(DarkSlateGrey, 47, 79, 79,"暗灰绿") + DEF_COLOR(DarkTurquoise, 0,206,209,"暗宝石绿") + DEF_COLOR(DarkViolet, 148, 0,211,"暗紫罗兰") + DEF_COLOR(DeepPink, 255, 20,147,"深粉红") + DEF_COLOR(DeepSkyBlue, 0,191,255,"深天蓝") + DEF_COLOR(DimGray, 105,105,105,"暗灰色") + DEF_COLOR(DimGrey, 105,105,105,"暗灰白") + DEF_COLOR(DodgerBlue, 30,144,255,"闪兰色") + DEF_COLOR(FireBrick, 178, 34, 34,"火砖色") + DEF_COLOR(FloralWhite, 255,250,240,"花白色") + DEF_COLOR(ForestGreen, 34,139, 34,"森林绿") + DEF_COLOR(FrenchBeige, 166,123, 91,"法国米色") + DEF_COLOR(FrenchBlue, 0,114,187,"法国兰") + DEF_COLOR(FrenchLilac, 134, 96,142,"法国丁香色") + DEF_COLOR(Fuchsia, 255, 0,255,"紫红色") + DEF_COLOR(Gainsboro, 220,220,220,"淡灰色") + DEF_COLOR(GhostWhite, 248,248,255,"幽灵白") + DEF_COLOR(Gold, 255,215, 0,"金色") + DEF_COLOR(Goldenrod, 218,165, 32,"金麒麟色") + DEF_COLOR(GoldenYellow, 255,223, 0,"金黄") + DEF_COLOR(Gray, 128,128,128,"灰色") + DEF_COLOR(Green, 0,128, 0,"绿色") + DEF_COLOR(GreenYellow, 173,255, 47,"蓝绿色") + DEF_COLOR(Grey, 128,128,128,"灰白色") + DEF_COLOR(HollywoodCerise, 244, 0,161,"好莱坞樱桃红") + DEF_COLOR(Honeydew, 240,255,240,"蜜色") + DEF_COLOR(HotPink, 255,105,180,"火热粉") + DEF_COLOR(HunterGreen, 53, 94, 59,"猎人绿") + DEF_COLOR(IndianGreen, 19,136, 8,"印度绿") + DEF_COLOR(IndianRed, 205, 92, 92,"印度红") + DEF_COLOR(IndianYellow, 227,168, 87,"印度黄") + DEF_COLOR(Indigo, 75, 0,130,"靛青色") + DEF_COLOR(Ivory, 255,255,240,"象牙白") + DEF_COLOR(Khaki, 240,230,140,"黄褐色") + DEF_COLOR(Lavender, 230,230,250,"淡紫色") + DEF_COLOR(LavenderBlush, 255,240,245,"淡紫红") + DEF_COLOR(LawnGreen, 124,252, 0,"草绿色") + DEF_COLOR(Lemon, 255,247, 0,"柠檬色") + DEF_COLOR(LemonYellow, 255,244, 79,"柠檬黄") + DEF_COLOR(LemonChiffon, 255,250,205,"柠檬绸") + DEF_COLOR(LightBlue, 173,216,230,"亮蓝色") + DEF_COLOR(LightCoral, 240,128,128,"亮珊瑚色") + DEF_COLOR(LightCyan, 224,255,255,"亮青色") + DEF_COLOR(LightGoldenrodYellow, 250,250,210,"亮金黄") + DEF_COLOR(LightGray, 211,211,211,"亮灰色") + DEF_COLOR(LightGreen, 144,238,144,"亮绿色") + DEF_COLOR(LightGrey, 211,211,211,"亮灰白") + DEF_COLOR(LightPink, 255,182,193,"亮粉红") + DEF_COLOR(LightSalmon, 255,160,122,"亮肉色") + DEF_COLOR(LightSeaGreen, 32,178,170,"亮海蓝") + DEF_COLOR(LightSkyBlue, 135,206,250,"亮天蓝") + DEF_COLOR(LightSlateGray, 119,136,153,"亮蓝灰") + DEF_COLOR(LightSlateGrey, 119,136,153,"亮蓝白") + DEF_COLOR(LightSteelBlue, 176,196,222,"亮钢兰") + DEF_COLOR(LightYellow, 255,255,224,"亮黄色") + DEF_COLOR(Lime, 0,255, 0,"酸橙色") + DEF_COLOR(LimeGreen, 50,205, 50,"橙绿色") + DEF_COLOR(Linen, 250,240,230,"亚麻色") + DEF_COLOR(Lion, 193,154,107,"獅子棕") + DEF_COLOR(Magenta, 255, 0,255,"红紫色") + DEF_COLOR(Maroon, 128, 0, 0,"粟色") + DEF_COLOR(MediumAquamarine, 102,205,170,"间绿色") + DEF_COLOR(MediumBlue, 0, 0,205,"间兰色") + DEF_COLOR(MediumOrchid, 186, 85,211,"间淡紫") + DEF_COLOR(MediumPurple, 147,112,219,"间紫色") + DEF_COLOR(MediumSeaGreen, 60,179,113,"间海蓝") + DEF_COLOR(MediumSlateBlue, 123,104,238,"间暗蓝") + DEF_COLOR(MediumSpringGreen, 0,250,154,"间春绿") + DEF_COLOR(MediumTurquoise, 72,209,204,"间绿宝石") + DEF_COLOR(MediumVioletRed, 199, 21,133,"间紫罗兰") + DEF_COLOR(MidNightBlue, 25, 25,112,"中灰蓝") + DEF_COLOR(Mint, 62,180,137,"薄荷色") + DEF_COLOR(MintCream, 245,255,250,"薄荷霜") + DEF_COLOR(MintGreen, 152,255,152,"薄荷绿") + DEF_COLOR(MistyRose, 255,228,225,"浅玫瑰") + DEF_COLOR(Moccasin, 255,228,181,"鹿皮色") + + DEF_COLOR(MozillaBlue, 0, 83,159,"火狐蓝") + DEF_COLOR(MozillaCharcoal, 77, 78, 83,"谋智炭") + DEF_COLOR(MozillaLightBlue, 0,150,221,"火狐亮蓝") + DEF_COLOR(MozillaLightOrange, 255,149, 0,"火狐亮橙") + DEF_COLOR(MoziilaNightBlue, 0, 33, 71,"谋智暗夜蓝") + DEF_COLOR(MozillaOrange, 230, 96, 0,"火狐橙") + DEF_COLOR(MozillaRed, 193, 56, 50,"谋智红") + DEF_COLOR(MozillaSand, 215,211,200,"谋智沙") + DEF_COLOR(MozillaYellow, 255,203, 0,"火狐黄") + + DEF_COLOR(NavajoWhite, 255,222,173,"纳瓦白") + DEF_COLOR(Navy, 0, 0,128,"海军色") + + DEF_COLOR(NiveaBlue, 0, 19,111,"妮维雅蓝") //取自妮维雅蓝国际官网 + + DEF_COLOR(NokiaBlue, 18, 65,145,"诺基亚蓝") //取自诺基亚官网 + + DEF_COLOR(OldLace, 253,245,230,"老花色") + DEF_COLOR(Olive, 128,128, 0,"橄榄色") + DEF_COLOR(Olivedrab, 107,142, 35,"深绿褐色") + DEF_COLOR(Orange, 255,165, 0,"橙色") + DEF_COLOR(OrangeRed, 255, 69, 0,"红橙色") + DEF_COLOR(Orchid, 218,112,214,"淡紫色") + DEF_COLOR(PaleGoldenrod, 238,232,170,"苍麒麟色") + DEF_COLOR(PaleGreen, 152,251,152,"苍绿色") + DEF_COLOR(PaleTurquoise, 175,238,238,"苍宝石绿") + DEF_COLOR(PaleVioletRed, 219,112,147,"苍紫罗兰色") + DEF_COLOR(Papayawhip, 255,239,213,"番木色") + DEF_COLOR(Peachpuff, 255,218,185,"桃色") + DEF_COLOR(Pear, 209,226, 49,"梨色") + DEF_COLOR(Peru, 205,133, 63,"秘鲁色") + DEF_COLOR(Pink, 255,192,203,"粉红色") + + DEF_COLOR(PlayStationBlue, 0, 55,145,"PlayStation蓝") + DEF_COLOR(PlayStationLightBlue, 0,120,200,"PlayStation亮蓝") + + DEF_COLOR(Plum, 221,160,221,"洋李色") + DEF_COLOR(PowderBlue, 176,224,230,"粉蓝色") + DEF_COLOR(Purple, 128, 0,128,"紫色") + DEF_COLOR(Red, 255, 0, 0,"红色") + DEF_COLOR(Rose, 255, 0,127,"玫瑰红") + DEF_COLOR(RosyBrown, 188,143,143,"褐玫瑰红") + DEF_COLOR(RoyalBlue, 65,105,225,"皇家蓝") + DEF_COLOR(Ruby, 224, 17, 95,"宝石红") + DEF_COLOR(SaddleBrown, 139, 69, 19,"重褐色") + DEF_COLOR(Salmon, 250,128,114,"鲜肉色") + + DEF_COLOR(SamsungBlue, 20, 40,160,"三星蓝") //取自三星官网 + + DEF_COLOR(SandyBrown, 244,164, 96,"沙褐色") + DEF_COLOR(SeaGreen, 46,139, 87,"海绿色") + DEF_COLOR(SeaShell, 255,245,238,"海贝色") + DEF_COLOR(Sienna, 160, 82, 45,"赭色") + DEF_COLOR(Silver, 192,192,192,"银色") + DEF_COLOR(SkyBlue, 135,206,235,"天蓝色") + DEF_COLOR(SlateBlue, 106, 90,205,"石蓝色") + DEF_COLOR(SlateGray, 112,128,144,"灰石色") + DEF_COLOR(SlateGrey, 112,128,144,"白灰石色") + DEF_COLOR(Snow, 255,250,250,"雪白色") + DEF_COLOR(SpringGreen, 0,255,127,"春绿色") + DEF_COLOR(SteelBlue, 70,130,180,"钢兰色") + DEF_COLOR(Tan, 210,180,140,"茶色") + DEF_COLOR(Teal, 0,128,128,"水鸭色") + DEF_COLOR(Thistle, 216,191,216,"蓟色") + + DEF_COLOR(TiffanyBlue, 129,216,208,"蒂芙尼蓝") //取自zh.wikipedia.org/zh-cn/蒂芙尼蓝 + + DEF_COLOR(Tomato, 255, 99, 71,"西红柿色") + DEF_COLOR(Turquoise, 64,224,208,"青绿色") + DEF_COLOR(Violet, 238,130,238,"紫罗兰色") + DEF_COLOR(Wheat, 245,222,179,"浅黄色") + DEF_COLOR(White, 255,255,255,"白色") + DEF_COLOR(WhiteSmoke, 245,245,245,"烟白色") + DEF_COLOR(Yellow, 255,255, 0,"黄色") + DEF_COLOR(YellowGreen, 154,205, 50,"黄绿色") + + DEF_COLOR(End, 0 ,0 ,0,"") + }; + + #undef DEF_COLOR +}//namespace hgl diff --git a/src/DataType/Color3f.cpp b/src/DataType/Color3f.cpp new file mode 100644 index 0000000..b21dad7 --- /dev/null +++ b/src/DataType/Color3f.cpp @@ -0,0 +1,75 @@ +#include +namespace hgl +{ + void Color3f::Use(COLOR_ENUM ce) + { + r=prv_color[ce].r; + g=prv_color[ce].g; + b=prv_color[ce].b; + } + + void Color3f::Clamp() + { + if(r<0)r=0;if(r>1)r=1; + if(g<0)g=0;if(g>1)g=1; + if(b<0)b=0;if(b>1)b=1; + } + //-------------------------------------------------------------------------------------------------- + /** + * 求当前颜色过渡到另一颜色时某一比例时的颜色 + * @param nr,ng,nb 新的颜色 + * @param pos 过渡比例,0时为当前的颜色,1时为nr,ng,nb + */ + void Color3f::To(float nr,float ng,float nb,float pos) + { + if(pos==0)return; + if(pos==1) + { + r=nr; + g=ng; + b=nb; + return; + } + + r+=(nr-r)*pos; + g+=(ng-g)*pos; + b+=(nb-b)*pos; + } +//-------------------------------------------------------------------------------------------------- + void Color3f::Grey(float v1,float v2,float v3) + { + float lum=v1*0.299+v2*0.587+v3*0.114; + + r=lum; + g=lum; + b=lum; + } + //-------------------------------------------------------------------------------------------------- + void Color3f::Grey() + { + float lum=r*0.299+g*0.587+b*0.114; + + r=lum; + g=lum; + b=lum; + } + //-------------------------------------------------------------------------------------------------- + bool Color3f::operator == (const Color3f &v) + { + if(r!=v.r)return(false); + if(g!=v.g)return(false); + if(b!=v.b)return(false); + + return(true); + } + //-------------------------------------------------------------------------------------------------- + bool Color3f::operator != (const Color3f &v) + { + if(r!=v.r)return(true); + if(g!=v.g)return(true); + if(b!=v.b)return(true); + + return(false); + } + //-------------------------------------------------------------------------------------------------- +} diff --git a/src/DataType/Color4f.cpp b/src/DataType/Color4f.cpp new file mode 100644 index 0000000..99734ab --- /dev/null +++ b/src/DataType/Color4f.cpp @@ -0,0 +1,70 @@ +#include +namespace hgl +{ + void Color4f::Use(COLOR_ENUM ce,float ta) + { + r=prv_color[ce].r; + g=prv_color[ce].g; + b=prv_color[ce].b; + a=ta; + } + + void Color4f::Clamp() + { + if(r<0)r=0;if(r>1)r=1; + if(g<0)g=0;if(g>1)g=1; + if(b<0)b=0;if(b>1)b=1; + if(a<0)a=0;if(a>1)a=1; + } + //-------------------------------------------------------------------------------------------------- + /** + * 求当前颜色过渡到另一颜色时某一比例时的颜色 + * @param nr,ng,nb 新的颜色 + * @param pos 过渡比例,0时为当前的颜色,1时为nr,ng,nb + */ + void Color4f::To(float nr,float ng,float nb,float pos) + { + if(pos==0)return; + if(pos==1) + { + r=nr; + g=ng; + b=nb; + return; + } + + r+=(nr-r)*pos; + g+=(ng-g)*pos; + b+=(nb-b)*pos; + } + //-------------------------------------------------------------------------------------------------- + void Color4f::Grey() + { + float lum=r*0.299+g*0.587+b*0.114; + + r=lum; + g=lum; + b=lum; + } + //-------------------------------------------------------------------------------------------------- + bool Color4f::operator == (const Color4f &v) + { + if(r!=v.r)return(false); + if(g!=v.g)return(false); + if(b!=v.b)return(false); + if(a!=v.a)return(false); + + return(true); + } + //-------------------------------------------------------------------------------------------------- + bool Color4f::operator != (const Color4f &v) + { + if(r!=v.r)return(true); + if(g!=v.g)return(true); + if(b!=v.b)return(true); + if(a!=v.a)return(true); + + return(false); + } + //-------------------------------------------------------------------------------------------------- +} diff --git a/src/DataType/Endian.cpp b/src/DataType/Endian.cpp new file mode 100644 index 0000000..ae8c500 --- /dev/null +++ b/src/DataType/Endian.cpp @@ -0,0 +1,15 @@ +#include + +namespace hgl +{ + bool CheckSystemEndian() + { + constexpr uint16 db=0xABCD; + + #if HGL_ENDIAN == HGL_BIG_ENDIAN + return(*(uint8 *)&db==0xAB); + #else + return(*(uint8 *)&db==0xCD); + #endif//HGL_BIG_ENDIAN + } +}//namespace hgl diff --git a/src/DataType/StringList.cpp b/src/DataType/StringList.cpp new file mode 100644 index 0000000..d65d957 --- /dev/null +++ b/src/DataType/StringList.cpp @@ -0,0 +1,182 @@ +#include +#include +namespace hgl +{ + /** + * 加载一个原始文本块到UTF8StringList + */ + int LoadStringListFromText(UTF8StringList &sl,uchar *data,const int size,const CharSet &cs) + { + char *str=nullptr; + + int line_count; + int char_count; + + if(size>=3&&data[0]==0xEF&&data[1]==0xBB&&data[2]==0xBF) //utf8 + line_count=SplitToStringListByEnter(sl,(char *)(data+3),size-3); + else + if(cs==UTF8CharSet) + line_count=SplitToStringListByEnter(sl,(char *)data,size); + else + { + if(size>=2) + { + int u16_count; + + if(data[0]==0xFF&&data[1]==0xFE) //LE + { + if(size>=4&&data[2]==0&&data[3]==0) //utf32-le + { + u16_count=(size-4)>>2; + u16char *u16str=new u16char[u16_count]; + + LittleToCurrentEndian(u16str,(uint32 *)(data+4),u16_count); + + str=u16_to_u8(u16str,u16_count,char_count); + delete[] u16str; + } + else //utf16-le + { + u16_count=(size-2)>>1; + LittleToCurrentEndian((u16char *)(data+2),u16_count); + str=u16_to_u8((u16char *)(data+2),u16_count,char_count); + } + } + else + if(data[0]==0&&data[1]==0&&data[2]==0xFE&&data[3]==0xFF) //utf32-be + { + u16_count=(size-4)>>2; + u16char *u16str=new u16char[u16_count]; + + BigToCurrentEndian(u16str,(uint32 *)(data+4),u16_count); + + str=u16_to_u8(u16str,u16_count,char_count); + delete[] u16str; + } + else + if(data[0]==0xFE&&data[1]==0xFF) //utf16-be + { + u16_count=(size-2)>>1; + BigToCurrentEndian((u16char *)(data+2),u16_count); + str=u16_to_u8((u16char *)(data+2),u16_count,char_count); + } + } + + if(!str) +#ifdef __ANDROID__ + return 0; +#else + char_count=to_utf8(cs,&str,(char *)data,size); +#endif// + + line_count=SplitToStringListByEnter(sl,str,char_count); + + delete[] str; + } + + delete[] data; + return line_count; + } + + /** + * 加载一个原始文本块到UTF16StringList + */ + int LoadStringListFromText(UTF16StringList &sl,uchar *data,const int size,const CharSet &cs) + { + u16char *str=nullptr; + + int char_count=0; + int line_count; + + if(size>=2) + { + if(data[0]==0xFF&&data[1]==0xFE) //LE + { + if(size>=4&&data[2]==0&&data[3]==0) //utf32-le + { + str=(u16char *)data; //32->16使用原缓冲区覆盖 + char_count=(size-4)>>2; + LittleToCurrentEndian(str,(uint32 *)(data+4),char_count); + } + else //utf16-le + { + str=(u16char *)(data+2); + char_count=(size-2)>>1; + LittleToCurrentEndian(str,char_count); + } + } + else + if(data[0]==0&&data[1]==0&&data[2]==0xFE&&data[3]==0xFF) //utf32-be + { + str=(u16char *)data; ////32->16使用原缓冲区覆盖 + char_count=(size-4)>>2; + BigToCurrentEndian(str,(uint32 *)(data+4),char_count); + } + else + if(data[0]==0xFE&&data[1]==0xFF) //utf16-be + { + str=(u16char *)(data+2); + char_count=(size-2)>>1; + BigToCurrentEndian(str,char_count); + } + } + + if((uchar *)str>=data&&(uchar *)str<=data+size) //如果str的地址在data的范围内 + { + line_count=SplitToStringListByEnter(sl,str,char_count); + } + else + { + if(size>=3&&data[0]==0xEF&&data[1]==0xBB&&data[2]==0xBF) //utf8 + str=u8_to_u16((char *)(data+3),size-3,char_count); + else + if(cs==UTF8CharSet) + str=u8_to_u16((char *)data,size,char_count); + else + { +#ifdef __ANDROID__ + return 0; +#else + char_count=to_utf16(cs,&str,(char *)data,size); +#endif// + } + + line_count=SplitToStringListByEnter(sl,str,char_count); + + delete[] str; + } + + delete[] data; + return line_count; + } + + /** + * 加载一个原始文本文件到UTF8StringList + */ + int LoadStringListFromTextFile(UTF8StringList &sl,const OSString &filename,const CharSet &cs) + { + uchar *data; + + const int size=filesystem::LoadFileToMemory(filename,(void **)&data); + + if(size<=0) + return size; + + return LoadStringListFromText(sl,data,size,cs); + } + + /** + * 加载一个原始文本文件到UTF16StringList + */ + int LoadStringListFromTextFile(UTF16StringList &sl,const OSString &filename,const CharSet &cs) + { + uchar *data; + + const int size=filesystem::LoadFileToMemory(filename,(void **)&data); + + if(size<=0) + return size; + + return LoadStringListFromText(sl,data,size,cs); + } +}//namespace hgl diff --git a/src/FileSystem/EnumFile.cpp b/src/FileSystem/EnumFile.cpp new file mode 100644 index 0000000..f483045 --- /dev/null +++ b/src/FileSystem/EnumFile.cpp @@ -0,0 +1,42 @@ +#include + +namespace hgl +{ + namespace filesystem + { + namespace + { + class OnlyFileEnum:public EnumFile + { + protected: + + List *fi_list; + + public: + + OnlyFileEnum(List *lfi) + { + fi_list=lfi; + } + + void ProcFile(struct EnumFileConfig *efc,hgl::filesystem::FileInfo &fi) override + { + fi_list->Add(fi); + } + };//class OnlyFileEnum:public EnumFile + }//namespace + + int GetFileInfoList(List &fi_list,const OSString &folder_name,bool proc_folder,bool proc_file,bool sub_folder) + { + EnumFileConfig efc(folder_name); + + efc.proc_folder = proc_folder; + efc.proc_file = proc_file; + efc.sub_folder = sub_folder; + + OnlyFileEnum ofe(&fi_list); + + return ofe.Enum(&efc); + } + }//namespace filesystem +}//namespace hgl diff --git a/src/FileSystem/FileSystem.cpp b/src/FileSystem/FileSystem.cpp new file mode 100644 index 0000000..20c368c --- /dev/null +++ b/src/FileSystem/FileSystem.cpp @@ -0,0 +1,315 @@ +#include +#include +#include +#include + +#include +#include +#include + +namespace hgl +{ + namespace filesystem + { + constexpr int FILE_PROC_BUF_SIZE=HGL_SIZE_1MB; + + /** + * 比较两个文件是否一样 + * @param filename1 第一个文件的名称 + * @param filename2 第二个文件的名称 + * @return 文件是否一样 + */ + bool FileComp(const OSString &filename1,const OSString &filename2) + { + io::FileInputStream fp1,fp2; + int64 fs1,fs2; + + if(!fp1.Open(filename1))return(false); + if(!fp2.Open(filename2))return(false); + + fs1=fp1.GetSize(); + fs2=fp2.GetSize(); + + if(fs1!=fs2) + return(false); + + int64 pos=0,size; + char *data1,*data2; + + data1=new char[FILE_PROC_BUF_SIZE]; + data2=new char[FILE_PROC_BUF_SIZE]; + + while(posfs1)size=fs1-pos; + + fp1.Read(data1,size); + fp2.Read(data2,size); + + if(memcmp(data1,data2,size)==0) + { + pos+=size; + continue; + } + else + { + delete[] data1; + delete[] data2; + return(false); + } + }; + + delete[] data1; + delete[] data2; + return(true); + } + + /** + * 加载一个文件到内存,文件数据请自己delete[]掉 + * @param filename 要载入的文件名称 + * @param buf 用来保存数据的内存指针的指针 + * @return 文件长度 + */ + int64 LoadFileToMemory(const OSString &filename,void **buf) + { + io::FileInputStream fs; + + if(!fs.Open(filename)) + return(-1); + + const int64 size=fs.GetSize(); + + char *fb=new char[size]; + + if(fs.Read(fb,size)==size) + { + *buf=fb; + return(size); + } + + delete[] fb; + return(-1); + } + + /** + * 保存一块内存成文件 + * @param filename 要保存的文件名称 + * @param buf 要保存的内存指针 + * @param size 要保存的内存数据长度 + * @return 成功写入的字节数 + * @return -1 失败 + */ + int64 SaveMemoryToFile(const OSString &filename,const void *buf,const int64 &size) + { + io::FileOutputStream fs; + + if(!fs.CreateTrunc(filename)) + return(-1); + + return fs.Write(buf,size); + } + + /** + * 保存多块内存成文件 + * @param filename 要保存的文件名称 + * @param buf_list 要保存的内存块指针列表 + * @param buf_size 要保存的内存块数据长度列表 + * @param buf_count 要保存的内存块数量 + * @return 成功写入的字节数 + * @return -1 失败 + */ + int64 SaveMemoryToFile(const OSString &filename,void **buf_list,const int64 *buf_size,const int &buf_count) + { + io::FileOutputStream fs; + + if(!fs.CreateTrunc(filename)) + return(-1); + + int64 total=0; + int64 result; + + for(int i=0;ifile_length) + { + LOG_PROBLEM(OS_TEXT("读取文件<")+filename+OS_TEXT("><")+OSString(offset)+OS_TEXT(",")+OSString(length)+OS_TEXT(">超出了范围,文件长度为<")+OSString(file_length)); + return(nullptr); + } + + char *fb; + + if(buf) + fb=(char *)buf; + else + fb=new char[length]; + + if(fs.Read(offset,fb,length)==length) + { + LOG_INFO(OS_TEXT("加载文件<")+filename+OS_TEXT("><")+OSString(offset)+OS_TEXT(",")+OSString(length)+OS_TEXT(">到缓冲区成功.")); + + return(buf); + } + else + { + if(fb!=buf) + delete[] fb; + + return(nullptr); + } + } + + /** + * 保存内存中的数据到文件中 + * @param filename 文件名 + * @param offset 起始地址 + * @param length 数据长度 + * @param data 数据长度 + * @return 是否成功 + */ + bool SaveMemoryToFile(const OSString &filename,int64 offset,const void *data,int64 length) + { + io::FileOutputStream fs; + + if(!fs.Open(filename)) + return(false); + + return fs.Write(offset,data,length); + } + + bool GetFileInfo(const os_char *filename,struct FileInfo &fi) + { + if(!filename||!*filename) + return(false); + + struct_stat64 file_state; + + memset(&file_state,0,sizeof(struct_stat64)); + + if(hgl_lstat64(filename,&file_state)==-1) + return(false); + + memset(&fi,0,sizeof(FileInfo)); + + if(file_state.st_mode&S_IFREG) + fi.is_file=true; + + if(file_state.st_mode&S_IFDIR) + fi.is_directory=true; + + if (file_state.st_mode&S_IREAD) + fi.can_read = true; + + if (file_state.st_mode&S_IWRITE) + fi.can_write = true; + +#if HGL_OS != HGL_OS_Windows + if(file_state.st_mode&S_IFLNK) + fi.is_link=true; +#endif//HGL_OS != HGL_OS_Windows + + fi.size=file_state.st_size; + + return(true); + } + }//namespace filesystem +}//namespace hgl diff --git a/src/IO/DataInputStream.cpp b/src/IO/DataInputStream.cpp new file mode 100644 index 0000000..03cfa5a --- /dev/null +++ b/src/IO/DataInputStream.cpp @@ -0,0 +1,248 @@ +#include +#include + +namespace hgl +{ + namespace io + { + template + bool ReadUTF16Chars(u16char *str,DataInputStream *dis,uint count) + { + if(dis->ReadArrays(str,count)!=count) + return(false); + + EndianSwap(str,count); + str[count]=0; + + return(true); + } + + template<> + bool ReadUTF16Chars(u16char *str,DataInputStream *dis,uint count) + { + return(dis->ReadArrays(str,count)==count); + } + + bool DataInputStream::ReadUTF16LEChars(u16char *u16str,uint count) + { + if(!in||!u16str||!count)return(false); + + return ReadUTF16Chars(u16str,this,count); + } + + bool DataInputStream::ReadUTF16BEChars(u16char *u16str,uint count) + { + if(!in||!u16str||!count)return(false); + + return ReadUTF16Chars(u16str,this,count); + } + + template + bool ReadUTF8String(char *buf,uint max_len,DataInputStream *dis) + { + if(!buf||!max_len||!dis) + return(false); + + T str_len; + + if(!dis->ReadNumber(str_len)) + return(false); + + if(str_len<=0) + { + *buf=0; + return(true); + } + + if(max_len>=str_len) + { + if(dis->ReadArrays(buf,str_len)!=str_len) + return(false); + + if(max_len>str_len) + buf[str_len]=0; + + return(true); + } + + if(dis->ReadArrays(buf,max_len)!=max_len) + return(false); + + dis->Skip(str_len-max_len); + + return(true); + } + + bool DataInputStream::ReadUTF8String (char *u8str,uint max_len){return hgl::io::ReadUTF8String(u8str,max_len,this);} + bool DataInputStream::ReadUTF8ShortString (char *u8str,uint max_len){return hgl::io::ReadUTF8String(u8str,max_len,this);} + bool DataInputStream::ReadUTF8TinyString (char *u8str,uint max_len){return hgl::io::ReadUTF8String(u8str,max_len,this);} + + template + bool ReadUTF8String(UTF8String &u8str,uint max_len,DataInputStream *dis) + { + if(!max_len||!dis) + return(false); + + T str_len; + + if(!dis->ReadNumber(str_len)) + return(false); + + if(str_len==0) + { + u8str.Clear(); + return(true); + } + + const uint count=(max_len>str_len?str_len:max_len); + + char *utf8_str=dis->ReadArrays(count); + + if(!utf8_str) + return(false); + + if(countSkip(str_len-count); + + u8str.Set(utf8_str,count,true); + return(true); + } + + bool DataInputStream::ReadUTF8String (UTF8String &u8str,uint max_len){return hgl::io::ReadUTF8String(u8str,max_len,this);} + bool DataInputStream::ReadUTF8ShortString (UTF8String &u8str,uint max_len){return hgl::io::ReadUTF8String(u8str,max_len,this);} + bool DataInputStream::ReadUTF8TinyString (UTF8String &u8str,uint max_len){return hgl::io::ReadUTF8String(u8str,max_len,this);} + + template + bool ReadUTF8String(UTF16String &u16str,uint max_len,DataInputStream *dis) + { + if(!max_len||!dis) + return(false); + + T str_len; + + if(!dis->ReadNumber(str_len)) + return(false); + + if(str_len==0) + { + u16str.Clear(); + return(true); + } + + const uint count=(max_len>str_len?str_len:max_len); + + char *utf8_str=dis->ReadArrays(count); + + if(!utf8_str) + return(false); + + if(countSkip(str_len-count); + + int wide_count; + + u16char *wide_str=u8_to_u16(utf8_str,count,wide_count); + + u16str.Set(wide_str,wide_count,true); + + delete[] utf8_str; + return(true); + } + + bool DataInputStream::ReadUTF8String (UTF16String &u16str,uint max_len){return hgl::io::ReadUTF8String(u16str,max_len,this);} + bool DataInputStream::ReadUTF8ShortString (UTF16String &u16str,uint max_len){return hgl::io::ReadUTF8String(u16str,max_len,this);} + bool DataInputStream::ReadUTF8TinyString (UTF16String &u16str,uint max_len){return hgl::io::ReadUTF8String(u16str,max_len,this);} + + template + bool ReadUTF16String(u16char *str,uint max_len,DataInputStream *dis) + { + if(!dis)return(false); + if(!str||!max_len)return(false); + + T count; + + if(!dis->ReadNumber(count)) + return(false); + + if(count<=0) + { + *str=0; + return(true); + } + + if(max_len>=count) + { + if(dis->ReadArrays(str,count)!=count) + return(false); + + if(max_len>count) + str[count]=0; + } + else + { + if(dis->ReadArrays(str,max_len)!=max_len) + return(false); + + dis->Skip((count-max_len)*sizeof(u16char)); + + count=max_len; + } + + UTF16CharConvert::convert(str,count); + return(true); + } + + bool DataInputStream::ReadUTF16LEString (u16char *u16str,uint max_len){return ReadUTF16String(u16str,max_len,this);} + bool DataInputStream::ReadUTF16LEShortString(u16char *u16str,uint max_len){return ReadUTF16String(u16str,max_len,this);} + bool DataInputStream::ReadUTF16LETinyString (u16char *u16str,uint max_len){return ReadUTF16String(u16str,max_len,this);} + + bool DataInputStream::ReadUTF16BEString (u16char *u16str,uint max_len){return ReadUTF16String(u16str,max_len,this);} + bool DataInputStream::ReadUTF16BEShortString(u16char *u16str,uint max_len){return ReadUTF16String(u16str,max_len,this);} + bool DataInputStream::ReadUTF16BETinyString (u16char *u16str,uint max_len){return ReadUTF16String(u16str,max_len,this);} + + template + bool ReadUTF16String(UTF16String &str,DataInputStream *dis,uint max_len) + { + if(!dis||!max_len)return(false); + + T count; + + if(!dis->ReadNumber(count)) + return(false); + + if(count<0) + return(false); + + if(max_len>0) + { + if(count>max_len) + return(false); + } + + if(count==0) + { + str.Clear(); + return(true); + } + + u16char *utf16_str=dis->ReadArrays(count); + + if(!utf16_str) + return(false); + + UTF16CharConvert::convert(utf16_str,count); + + str.Set(utf16_str,count,true); + + return(true); + } + + bool DataInputStream::ReadUTF16LEString (UTF16String &u16str,uint max_len){return ReadUTF16String(u16str,this,max_len);} + bool DataInputStream::ReadUTF16LEShortString(UTF16String &u16str,uint max_len){return ReadUTF16String(u16str,this,max_len);} + bool DataInputStream::ReadUTF16LETinyString (UTF16String &u16str,uint max_len){return ReadUTF16String(u16str,this,max_len);} + + bool DataInputStream::ReadUTF16BEString (UTF16String &u16str,uint max_len){return ReadUTF16String(u16str,this,max_len);} + bool DataInputStream::ReadUTF16BEShortString(UTF16String &u16str,uint max_len){return ReadUTF16String(u16str,this,max_len);} + bool DataInputStream::ReadUTF16BETinyString (UTF16String &u16str,uint max_len){return ReadUTF16String(u16str,this,max_len);} + }//namespace io +}//namespace hgl diff --git a/src/IO/DataOutputStream.cpp b/src/IO/DataOutputStream.cpp new file mode 100644 index 0000000..5ed2702 --- /dev/null +++ b/src/IO/DataOutputStream.cpp @@ -0,0 +1,185 @@ +#include + +namespace hgl +{ + namespace io // write utf8 chars + { + template<> bool DataOutputStream::WriteUTF8Chars (const char *str,uint size) + { + if(!out)return(false); + if(size==0)return(true); + + if(!str||!*str)return(false); + + return(WriteArrays(str,size)==size); + } + + template<> bool DataOutputStream::WriteUTF8Chars (const u16char *str,uint size) + { + if(!out)return(false); + if(size==0)return(true); + + if(!str||!*str)return(false); + + return WriteUTF8Chars(to_u8(str,size)); + } + } + + namespace io //write utf8 string + { + template bool DataOutputStream::WriteUTF8StringWithLength(const char *str,const uint length) + { + if(!out)return(false); + + if(length&&!str)return(false); + + if(!WriteNumber(length)) + return(false); + + if(!length) + return(true); + + return WriteUTF8Chars(str,length); + } + + template bool DataOutputStream::WriteUTF8StringWithLength(const UTF16String &str) + { + if(!out)return(false); + + int utf8_count; + char *utf8_str=u16_to_u8(str.c_str(),str.Length(),utf8_count); + + const bool result=WriteUTF8StringWithLength(utf8_str,utf8_count); + + delete[] utf8_str; + + return result; + } + } + + namespace io //write utf16 chars + { + template //非特例化版本,用于需要swap的 + bool WriteUTF16Chars(DataOutputStream *dos,const u16char *str,uint count) + { + SharedArray swap_str=new u16char[count]; + + EndianSwap(swap_str,str,count); + + return(dos->WriteArrays(swap_str,count)==count); + } + + template<> //特例化版本,用于直接写入的 + bool WriteUTF16Chars(DataOutputStream *dos,const u16char *str,uint count) + { + return(dos->WriteArrays(str,count)==count); + } + } + + namespace io //write utf16-le chars + { + template<> bool DataOutputStream::WriteUTF16LEChars(const char *str,uint length) + { + if(length==0)return(true); + if(!out||!str||!*str)return(false); + + UTF16String u16_str=to_u16(str); + + return WriteUTF16Chars(this,u16_str.c_str(),u16_str.Length()); + } + + template<> bool DataOutputStream::WriteUTF16LEChars(const u16char *str,uint length) + { + if(length==0)return(true); + if(!out||!str||!*str)return(false); + + return WriteUTF16Chars(this,str,length); + } + } + + namespace io //write utf16-be chars + { + template<> bool DataOutputStream::WriteUTF16BEChars(const char *str,uint length) + { + if(length==0)return(true); + if(!out||!str||!*str)return(false); + + UTF16String u16_str=to_u16(str,length); + + return WriteUTF16Chars(this,u16_str.c_str(),u16_str.Length()); + } + + template<> bool DataOutputStream::WriteUTF16BEChars(const u16char *str,uint length) + { + if(length==0)return(true); + if(!out||!str||!*str)return(false); + + return WriteUTF16Chars(this,str,length); + } + }//namespace io + + namespace io //write utf16 string + { + template bool DataOutputStream::WriteUTF16StringWithLength(const u16char *str,const uint len) + { + if(!out)return(false); + if(len&&!str)return(false); + + if(!WriteNumber(len)) + return(false); + + if(!len)return(true); + + return WriteUTF16Chars(this,str,len); + } + }//namespace io + + namespace io + { + bool DataOutputStream::WriteUTF8String (const char *str,uint length){return WriteUTF8StringWithLength(str, length);} ///<按utf16-le格式写入字符串(前置4字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF8String (const char *str ){return WriteUTF8StringWithLength(str, hgl::strlen(str));} ///<按utf8格式写入字符串(前置4字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF8String (const UTF8String &str ){return WriteUTF8StringWithLength(str.c_str(), str.Length());} ///<按utf8格式写入字符串(前置4字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF8String (const UTF16String &str ){return WriteUTF8StringWithLength(str);} ///<按utf8格式写入字符串(前置4字节字符串长度,再写入字符阵列) + + bool DataOutputStream::WriteUTF16LEString (const u16char *str,uint len){return WriteUTF16StringWithLength(str, len);} ///<按utf16-le格式写入字符串(前置4字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF16BEString (const u16char *str,uint len){return WriteUTF16StringWithLength(str, len);} ///<按utf16-be格式写入字符串(前置4字节字符串长度,再写入字符阵列) + + bool DataOutputStream::WriteUTF16LEString (const UTF16String &str ){return WriteUTF16StringWithLength(str.c_str(),str.Length());} ///<按utf16-le格式写入字符串(前置4字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF16BEString (const UTF16String &str ){return WriteUTF16StringWithLength(str.c_str(),str.Length());} ///<按utf16-be格式写入字符串(前置4字节字符串长度,再写入字符阵列) + + bool DataOutputStream::WriteUTF16LEString (const u16char *str ){return WriteUTF16StringWithLength(str, hgl::strlen(str));} ///<按utf16-le格式写入字符串(前置4字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF16BEString (const u16char *str ){return WriteUTF16StringWithLength(str, hgl::strlen(str));} ///<按utf16-be格式写入字符串(前置4字节字符串长度,再写入字符阵列) + + + + bool DataOutputStream::WriteUTF8ShortString (const char *str,uint length){return WriteUTF8StringWithLength(str, length);} ///<按utf16-le格式写入字符串(前置2字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF8ShortString (const char *str ){return WriteUTF8StringWithLength(str, hgl::strlen(str));} ///<按utf8格式写入字符串(前置2字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF8ShortString (const UTF8String &str ){return WriteUTF8StringWithLength(str.c_str(), str.Length());} ///<按utf8格式写入字符串(前置2字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF8ShortString (const UTF16String &str ){return WriteUTF8StringWithLength(str);} ///<按utf8格式写入字符串(前置2字节字符串长度,再写入字符阵列) + + bool DataOutputStream::WriteUTF16LEShortString(const u16char *str,uint len){return WriteUTF16StringWithLength(str, len);} ///<按utf16-le格式写入字符串(前置2字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF16BEShortString(const u16char *str,uint len){return WriteUTF16StringWithLength(str, len);} ///<按utf16-be格式写入字符串(前置2字节字符串长度,再写入字符阵列) + + bool DataOutputStream::WriteUTF16LEShortString(const UTF16String &str ){return WriteUTF16StringWithLength(str.c_str(),str.Length());} ///<按utf16-le格式写入字符串(前置2字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF16BEShortString(const UTF16String &str ){return WriteUTF16StringWithLength(str.c_str(),str.Length());} ///<按utf16-be格式写入字符串(前置2字节字符串长度,再写入字符阵列) + + bool DataOutputStream::WriteUTF16LEShortString(const u16char *str ){return WriteUTF16StringWithLength(str, hgl::strlen(str));} ///<按utf16-le格式写入字符串(前置2字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF16BEShortString(const u16char *str ){return WriteUTF16StringWithLength(str, hgl::strlen(str));} ///<按utf16-be格式写入字符串(前置2字节字符串长度,再写入字符阵列) + + + + bool DataOutputStream::WriteUTF8TinyString (const char *str,uint length){return WriteUTF8StringWithLength(str, length);} ///<按utf16-le格式写入字符串(前置1字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF8TinyString (const char *str ){return WriteUTF8StringWithLength(str, hgl::strlen(str));} ///<按utf8格式写入字符串(前置1字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF8TinyString (const UTF8String &str ){return WriteUTF8StringWithLength(str.c_str(), str.Length());} ///<按utf8格式写入字符串(前置1字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF8TinyString (const UTF16String &str ){return WriteUTF8StringWithLength(str);} ///<按utf8格式写入字符串(前置1字节字符串长度,再写入字符阵列) + + bool DataOutputStream::WriteUTF16LETinyString (const u16char *str,uint len){return WriteUTF16StringWithLength(str, len);} ///<按utf16-le格式写入字符串(前置1字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF16BETinyString (const u16char *str,uint len){return WriteUTF16StringWithLength(str, len);} ///<按utf16-be格式写入字符串(前置1字节字符串长度,再写入字符阵列) + + bool DataOutputStream::WriteUTF16LETinyString (const UTF16String &str ){return WriteUTF16StringWithLength(str.c_str(), str.Length());} ///<按utf16-le格式写入字符串(前置1字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF16BETinyString (const UTF16String &str ){return WriteUTF16StringWithLength(str.c_str(), str.Length());} ///<按utf16-be格式写入字符串(前置1字节字符串长度,再写入字符阵列) + + bool DataOutputStream::WriteUTF16LETinyString (const u16char *str ){return WriteUTF16StringWithLength(str, hgl::strlen(str));} ///<按utf16-le格式写入字符串(前置1字节字符串长度,再写入字符阵列) + bool DataOutputStream::WriteUTF16BETinyString (const u16char *str ){return WriteUTF16StringWithLength(str, hgl::strlen(str));} ///<按utf16-be格式写入字符串(前置1字节字符串长度,再写入字符阵列) + }//namespace io +}//namespace hgl diff --git a/src/IO/FileAccess.cpp b/src/IO/FileAccess.cpp new file mode 100644 index 0000000..2d33cd8 --- /dev/null +++ b/src/IO/FileAccess.cpp @@ -0,0 +1,174 @@ +#include +#include +#include + +#if HGL_OS != HGL_OS_Windows +#include +#else +#include +#endif//HGL_OS!=HGL_OS_Windows +namespace hgl +{ + namespace io + { + FileAccess::FileAccess() + { + fp=-1; + mode=fomNone; + } + + FileAccess::~FileAccess() + { + Close(); + } + + int OpenFile(const os_char *fn,FileOpenMode fom); + + bool FileAccess::Open(const OSString &fn,FileOpenMode fom) + { + Close(); + + if(fn.IsEmpty()) + { + LOG_ERROR(OS_TEXT("Error,filename is NULL")); + return(false); + } + + fp=OpenFile(fn.c_str(),fom); + + if(fp==-1) + { + LOG_ERROR(OS_TEXT("open file error,filename: ")+fn); + return(false); + } + + filename=fn; + mode=fom; + return(true); + } + + void CloseFile(int fp); + + void FileAccess::Close() + { + if(fp==-1)return; + + CloseFile(fp); + + fp=-1; + mode=fomNone; + } + + void FileAccess::CloseRead() + { + if(fp==-1)return; + + if(!CanWrite()) + Close(); + + mode=fomOnlyWrite; + } + + void FileAccess::CloseWrite() + { + if(fp==-1)return; + + if(!CanRead()) + Close(); + + mode=fomOnlyRead; + } + + bool FileAccess::CanRead() const + { + if(fp==-1)return(false); + + if(mode==fomOnlyWrite)return(false); + + return true; + } + + bool FileAccess::CanWrite() const + { + if(fp==-1)return(false); + + if(mode==fomOnlyRead)return(false); + + return(true); + } + + bool FileAccess::CanSeek() const + { + if(fp==-1)return(false); + if(mode=fomAppend)return(false); + + return(true); + } + + int64 FileAccess::Seek(int64 offset,SeekOrigin orign) + { + if(!CanSeek())return(-1); + + return hgl_lseek64(fp,offset,(int)orign); + } + + int64 FileAccess::Tell()const + { + if(fp==-1)return(-1); + + return hgl_tell64(fp); + } + + int64 FileAccess::GetSize() + { + if(!CanSize())return(-1); + + hgl_fstat64(fp,&file_state); + return(file_state.st_size); + } + + int64 FileAccess::AvailableRead() + { + if(fp==-1)return(-1); + + if(mode!=fomOnlyRead + &&mode!=fomReadWrite) + return(-1); + + return GetSize()-Tell(); + } + + bool FileAccess::Restart() + { + if(!CanRestart())return(false); + + return(Seek(0,SeekOrigin::Begin)==0); + } + + int64 FileAccess::Read(void *buf,int64 size) + { + if(!CanRead())return(-1); + + return hgl_read64(fp,buf,size); + } + + int64 FileAccess::Peek(void *buf,int64 size) + { + if(!CanPeek())return(-1); + + int result=hgl_read64(fp,buf,size); + + if(result>0) + hgl_lseek64(fp,-result,(int)SeekOrigin::Current); //回移这个长度 + + return result; + } + + int64 FileAccess::Write(const void *buf,int64 size) + { + if(!CanWrite())return(-1); + + return hgl_write64(fp,buf,size); + } + }//namespace io +}//namespace hgl diff --git a/src/IO/FileInputStream.cpp b/src/IO/FileInputStream.cpp new file mode 100644 index 0000000..ab54e0e --- /dev/null +++ b/src/IO/FileInputStream.cpp @@ -0,0 +1,65 @@ +#include +namespace hgl +{ + namespace io + { + FileInputStream::FileInputStream() + { + } + + FileInputStream::FileInputStream(SharedPtr &fa) + { + file=fa; + } + + FileInputStream::~FileInputStream() + { + Close(); + } + + bool FileInputStream::Open(const OSString &filename) + { + Close(); + + if(filename.IsEmpty()) + return(false); + + file=new FileAccess(); + + if(!file->Open(filename,fomOnlyRead)) + { + file=nullptr; + return(false); + } + + return(true); + } + + void FileInputStream::Close() + { + if(file) + { + file->Close(); + file=nullptr; + } + } + + int64 FileInputStream::Read (void *buf,int64 size) {return file?file->Read(buf,size):-1;} + int64 FileInputStream::Peek (void *buf,int64 size) {return file?file->Peek(buf,size):-1;} + + bool FileInputStream::CanSeek ()const {return file?file->CanSeek():false;} + bool FileInputStream::CanRestart ()const {return file?file->CanRestart():false;} + bool FileInputStream::CanSize ()const {return file?file->CanSize():false;} + bool FileInputStream::CanPeek ()const {return file?file->CanPeek():false;} + + int64 FileInputStream::Skip (int64 bytes) {return file?file->Seek(bytes,SeekOrigin::Current):-1;} + int64 FileInputStream::Tell ()const {return file?file->Tell():-1;} + int64 FileInputStream::GetSize ()const {return file?file->GetSize():-1;} + bool FileInputStream::Restart () {return file?file->Restart():false;} + int64 FileInputStream::Seek (int64 off,SeekOrigin so) {return file?file->Seek(off,so):-1;} + + int64 FileInputStream::Available ()const {return file?file->AvailableRead():-1;} + + int64 FileInputStream::Read (int64 off,void *buf,int64 size){return file?file->Read(off,buf,size):-1;} + }//namespace io +}//namespace hgl diff --git a/src/IO/FileOutputStream.cpp b/src/IO/FileOutputStream.cpp new file mode 100644 index 0000000..128084e --- /dev/null +++ b/src/IO/FileOutputStream.cpp @@ -0,0 +1,60 @@ +#include +namespace hgl +{ + namespace io + { + FileOutputStream::FileOutputStream() + { + } + + FileOutputStream::FileOutputStream(SharedPtr &fa) + { + file=fa; + } + + FileOutputStream::~FileOutputStream() + { + Close(); + } + + bool FileOutputStream::OpenFile(const OSString &filename,FileOpenMode mode) + { + Close(); + + if(filename.IsEmpty()) + return(false); + + file=new FileAccess(); + + if(!file->Open(filename,mode)) + { + file=nullptr; + return(false); + } + + return(true); + } + + void FileOutputStream::Close() + { + if(file) + { + file->CloseWrite(); + file=nullptr; + } + } + + int64 FileOutputStream::Write (const void *buf,int64 size) {return file?file->Write(buf,size):-1;} + + bool FileOutputStream::CanSeek ()const {return file?file->CanSeek():false;} + bool FileOutputStream::CanRestart()const {return file?file->CanRestart():false;} + bool FileOutputStream::CanSize ()const {return file?file->CanSize():false;} + + int64 FileOutputStream::Tell ()const {return file?file->Tell():-1;} + int64 FileOutputStream::GetSize ()const {return file?file->GetSize():-1;} + bool FileOutputStream::Restart () {return file?file->Restart():false;} + int64 FileOutputStream::Seek (int64 off,SeekOrigin so) {return file?file->Seek(off,so):-1;} + + int64 FileOutputStream::Write (int64 off,const void *buf,int64 size) {return file?file->Write(off,buf,size):-1;} + }//namespace io +}//namespace hgl diff --git a/src/IO/IOType.cpp b/src/IO/IOType.cpp new file mode 100644 index 0000000..b39d876 --- /dev/null +++ b/src/IO/IOType.cpp @@ -0,0 +1,37 @@ +#include +#include +#include +namespace hgl +{ + namespace io + { +#define IO_TYPE_DEFINE(small,large) typedef io_type io##large; \ + \ + template<> bool io_type::Read(hgl::io::DataInputStream *dis) \ + { \ + if(!dis)return(false); \ + return dis->Read##large(value); \ + } \ + \ + template<> bool io_type::Write(hgl::io::DataOutputStream *dos)const \ + { \ + if(!dos)return(false); \ + return dos->Write##large(value); \ + } + + IO_TYPE_DEFINE(int8,Int8); + IO_TYPE_DEFINE(int16,Int16); + IO_TYPE_DEFINE(int32,Int32); + IO_TYPE_DEFINE(int64,Int64); + + IO_TYPE_DEFINE(uint8,Uint8); + IO_TYPE_DEFINE(uint16,Uint16); + IO_TYPE_DEFINE(uint32,Uint32); + IO_TYPE_DEFINE(uint64,Uint64); + + IO_TYPE_DEFINE(bool,Bool); + IO_TYPE_DEFINE(float,Float); + IO_TYPE_DEFINE(double,Double); +#undef IO_TYPE_DEFINE + }//namespace io +}//namespace hgl diff --git a/src/IO/RandomAccessFile.cpp b/src/IO/RandomAccessFile.cpp new file mode 100644 index 0000000..7feda48 --- /dev/null +++ b/src/IO/RandomAccessFile.cpp @@ -0,0 +1,60 @@ +#include +#include +#include + +namespace hgl +{ + namespace io + { + RandomAccessFile::RandomAccessFile() + { + file=nullptr; + } + + RandomAccessFile::RandomAccessFile(SharedPtr &f) + { + file=f; + } + + RandomAccessFile::~RandomAccessFile() + { + Close(); + } + + bool RandomAccessFile::Open(const OSString &filename) + { + Close(); + + file=new FileAccess(); + + if(!file->Open(filename,fomReadWrite)) + { + file=nullptr; + return(false); + } + + return(true); + } + + void RandomAccessFile::Close() + { + if(file) + file=nullptr; + } + + int64 RandomAccessFile::Read (void *buf,int64 size) {return file?file->Read(buf,size):-1;} + int64 RandomAccessFile::Write (const void *buf,int64 size) {return file?file->Write(buf,size):-1;} + + bool RandomAccessFile::CanSeek ()const {return file?file->CanSeek():false;} + bool RandomAccessFile::CanRestart()const {return file?file->CanRestart():false;} + bool RandomAccessFile::CanSize ()const {return file?file->CanSize():false;} + + int64 RandomAccessFile::Tell ()const {return file?file->Tell():-1;} + int64 RandomAccessFile::GetSize () {return file?file->GetSize():-1;} + bool RandomAccessFile::Restart () {return file?file->Restart():false;} + int64 RandomAccessFile::Seek (int64 off,SeekOrigin so) {return file?file->Seek(off,so):-1;} + + int64 RandomAccessFile::Read (int64 off,void *buf,int64 size) {return file?file->Read(off,buf,size):-1;} + int64 RandomAccessFile::Write (int64 off,const void *buf,int64 size) {return file?file->Write(off,buf,size):-1;} + }//namespace io +}//namespace hgl diff --git a/src/IO/TextOutputStream.cpp b/src/IO/TextOutputStream.cpp new file mode 100644 index 0000000..65560e5 --- /dev/null +++ b/src/IO/TextOutputStream.cpp @@ -0,0 +1,47 @@ +#include +#include +namespace hgl +{ + namespace io + { + template<> EndianTextOutputStream::EndianTextOutputStream(OutputStream *os):TextOutputStream(bomUTF8,new DirectDataOutputStream(os)){} + template<> EndianTextOutputStream::EndianTextOutputStream(OutputStream *os):TextOutputStream(bomUTF16LE,new LEDataOutputStream(os)){} + template<> EndianTextOutputStream::EndianTextOutputStream(OutputStream *os):TextOutputStream(bomUTF16BE,new BEDataOutputStream(os)){} + + template<> TextOutputStream *CreateTextOutputStream(OutputStream *os){return(new UTF8TextOutputStream(os));} + template<> TextOutputStream *CreateTextOutputStream(OutputStream *os){return(new UTF16LETextOutputStream(os));} + }//namespace io + + namespace io //WriteChars函数 + { + template<> bool EndianTextOutputStream::WriteChars(const char *str,int64 size) + { + return out?out->WriteUTF8Chars(str,size):false; + } + + template<> bool EndianTextOutputStream::WriteChars(const u16char *str,int64 size) + { + return out?out->WriteUTF8Chars(str,size):false; + } + + template<> bool EndianTextOutputStream::WriteChars(const char *str,int64 size) + { + return out?out->WriteUTF16LEChars(str,size):false; + } + + template<> bool EndianTextOutputStream::WriteChars(const u16char *str,int64 size) + { + return out?out->WriteUTF16LEChars(str,size):false; + } + + template<> bool EndianTextOutputStream::WriteChars(const char *str,int64 size) + { + return out?out->WriteUTF16BEChars(str,size):false; + } + + template<> bool EndianTextOutputStream::WriteChars(const u16char *str,int64 size) + { + return out?out->WriteUTF16BEChars(str,size):false; + } + }//namespace io +}//namespace hgl diff --git a/src/Other/CodePage.cpp b/src/Other/CodePage.cpp new file mode 100644 index 0000000..b104a24 --- /dev/null +++ b/src/Other/CodePage.cpp @@ -0,0 +1,267 @@ +#include + +namespace hgl +{ + CharSet DefaultCharSet(); + + CharSet UTF8CharSet (ccpUTF8, utf8_charset ); + CharSet UTF16LECharSet (ccpUTF16LE,utf16le_charset ); + CharSet UTF16BECharSet (ccpUTF16BE,utf16be_charset ); + + int u16_to_u8(char *dst,int dst_size,const u16char *src,const int src_size) + { + if(src_size<=0||!src||!*src) + { + if(dst&&dst_size>0) + *dst=0; + + return(0); + } + + if(!dst||dst_size<=0) + return(-1); + + const u16char *sp=src; + uint8 *tp=(uint8 *)dst; + + while(*sp&&(int(tp-(uint8 *)dst)> 6)&0x1F); + *tp++=0x80|((*sp )&0x3F); + } + else // U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx + { + *tp++=0xE0|((*sp>>12)&0x0F); + *tp++=0x80|((*sp>> 6)&0x3F); + *tp++=0x80|((*sp )&0x3F); + } + + sp++; + } + +// *tp=0; + + return int(tp-(uint8 *)dst); + } + + int u8_to_u16(u16char *dst,int dst_size,const char *src,const int src_size) + { + if(src_size<=0||!src||!*src) + { + if(dst&&dst_size>0) + *dst=0; + + return(0); + } + + if(!dst||dst_size<=0) + return(-1); + + const uint8 *sp=(uint8 *)src; + u16char *tp=dst; + + while(*sp&&(int(tp-dst)=0xC0)&&(*sp<0xE0)) // U-00000080 - U-000007FF: 110xxxxx 10xxxxxx + { + *tp =((*sp++)&0x1F)<<6; + *tp|=((*sp++)&0x3F); + } + else if((*sp>=0xE0)&&(*sp<0xF0)) // U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx + { + *tp =((*sp++)&0x0F)<<12; + *tp|=((*sp++)&0x3F)<<6; + *tp|=((*sp++)&0x3F); + } + else if((*sp>=0xF0)&&(*sp<0xF8)) // U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + { + sp+=4; //不解析 + } + else if((*sp>=0xF8)&&(*sp<0xFC)) // U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + { + sp+=5; //不解析 + } + else if((*sp>=0xFC)) // U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + { + sp+=6; //不解析 + } + else + { + *tp=0; + break; + } + + tp++; + } + +// *tp=0; + + return int(tp-dst); + } + + /** + * 转换u16char *字符串到utf8格式char *字符串 + * @param src 源字符串 + * @param src_size 源字符串字符数 + * @param dst_size 结果字符串字符数 + * @return 转换结果,需自行delete[] + */ + char *u16_to_u8(const u16char *src,const int src_size,int &dst_size) + { + if(src_size<=0||!src||!*src) + { + dst_size=0; + return(nullptr); + } + + const u16char *sp=src; + dst_size=0; + + while(*sp&&(sp-src=0xC0)&&(*sp<0xE0)) // U-00000080 - U-000007FF: 110xxxxx 10xxxxxx + { + sp+=2; + dst_size++; + } + else if((*sp>=0xE0)&&(*sp<0xF0)) // U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx + { + sp+=3; + dst_size++; + } + else if((*sp>=0xF0)&&(*sp<0xF8)) // U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + { + sp+=4; //不解析 + } + else if((*sp>=0xF8)&&(*sp<0xFC)) // U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + { + sp+=5; //不解析 + } + else if((*sp>=0xFC)) // U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + { + sp+=6; //不解析 + } + else + { + break; + } + } + + if(dst_size<=0) + return(nullptr); + + u16char *dst=new u16char[dst_size+1]; + + dst[dst_size]=0; //为防止内存检测工具报错,所以提前赋0 + + u8_to_u16(dst,dst_size,src,src_size); + + return dst; + } + + /** + * 分析这个unicode文本文件的字节序 + * @param input 输入数据 + * @return 字节序 + */ + const BOMFileHeader *ParseBOM(const void *input) + { + if(!input)return(nullptr); + + const BOMFileHeader *bfh=BOMData+bomUTF8; + + for(uint i=bomUTF8;idata,bfh->size)==0) + return bfh; + + ++bfh; + } + + return nullptr; + } + + /** + * 转换BOM数据到CharSet结构 + * @param bom BOM数据 + * @param cs 字符集数据结构 + * @return 是否转换成功 + */ + bool BOM2CharSet(CharSet *cs,const BOMFileHeader *bom) + { + if(!cs)return(false); + if(!bom)return(false); + + if(bom->bom<=bomNone||bom->bom>=bomEnd)return(false); + + cs->codepage=bom->code_page; + memcpy(cs->charset,bom->char_set,sizeof(CharSetName)); + return(true); + } +}//namespace hgl diff --git a/src/Other/DateTime.cpp b/src/Other/DateTime.cpp new file mode 100644 index 0000000..f278240 --- /dev/null +++ b/src/Other/DateTime.cpp @@ -0,0 +1,348 @@ +#include +#include + +#include +#include + +#include + +#include + +namespace hgl +{ + bool Time::SaveToStream(io::DataOutputStream *str) const + { + if(!str)return(false); + + if(!str->WriteInt8(hours))return(false); + if(!str->WriteInt8(minutes))return(false); + if(!str->WriteInt8(seconds))return(false); + if(!str->WriteInt32(micro_seconds))return(false); + if(!str->WriteInt32(gmt_off))return(false); + + return(true); + } + + bool Time::LoadFromStream(io::DataInputStream *str) + { + if(!str)return(false); + + if(!str->ReadInt8(hours))return(false); + if(!str->ReadInt8(minutes))return(false); + if(!str->ReadInt8(seconds))return(false); + if(!str->ReadInt32(micro_seconds))return(false); + if(!str->ReadInt32(gmt_off))return(false); + + return(true); + } + + Time::Time() + { + hours=0; + minutes=0; + seconds=0; + micro_seconds=0; + } + + Time::Time(const double t) + { + Sync(t); + } + + Time::Time(int h,int m,int s,int ms) + { + hours=h; + minutes=m; + seconds=s; + micro_seconds=ms; + } + + Time::Time(const Time &t) + { + operator = (t); + } + + /** + * 设置时间 + * @param h 小时 + * @param m 分 + * @param s 秒 + * @param ms 微秒(百分分之一秒) + */ + void Time::Set(int h,int m,int s,int ms,int wd) + { + hours=h; + minutes=m; + seconds=s; + micro_seconds=ms; + week_day=wd; + } + + Time &Time::operator=(const Time &t) + { + hours =t.hours; + minutes =t.minutes; + seconds =t.seconds; + micro_seconds =t.micro_seconds; + + return(*this); + } + + const int Time::Comp(const Time &t)const + { + if(hours!=t.hours) + return hours-t.hours; + + if(minutes!=t.minutes) + return minutes-t.minutes; + + if(seconds!=t.seconds) + return seconds-t.seconds; + + return micro_seconds-t.micro_seconds; + } + + void Time::SetHour(int h) + { + if(h<0) + { + while(h<0) + h+=HGL_HOUR_ONE_DAY; + } + else if(h>0) + { + while(h>(HGL_HOUR_ONE_DAY-1)) + h-=HGL_HOUR_ONE_DAY; + } + + hours=h; + } + + void Time::SetMinute(int m) + { + int h=hours; + + if(m<0) + { + while(m<0) + { + m+=HGL_TIME_ONE_MINUTE; + h--; + } + } + else if(m>0) + { + while(m>(HGL_TIME_ONE_MINUTE-1)) + { + m-=HGL_TIME_ONE_MINUTE; + h++; + } + } + + minutes=m; + SetHour(h); + } + + void Time::SetSecond(int s) + { + int m=minutes; + + if(s<0) + { + while(s<0) + { + s+=HGL_TIME_ONE_MINUTE; + m--; + } + } + else if(s>0) + { + while(s>(HGL_TIME_ONE_MINUTE-1)) + { + s-=HGL_TIME_ONE_MINUTE; + m++; + } + } + + seconds=s; + SetMinute(m); + } + + void Time::SetMicroSecond(int ms) + { + int s=seconds; + + if(ms<0) + { + while(ms<0) + { + ms-=HGL_MICRO_SEC_PER_SEC; + s--; + } + } + else if(ms>0) + { + while(ms>(HGL_MICRO_SEC_PER_SEC-1)) + { + ms-=HGL_MICRO_SEC_PER_SEC; + s++; + } + } + + micro_seconds=ms; + SetSecond(s); + } +}//namespace hgl +//-------------------------------------------------------------------------------------------------- +namespace hgl +{ + Date::Date(const double t) + { + Sync(t); + } + + Date::Date(const Date &t) + { + operator = (t); + } + + Date &Date::operator=(const Date &t) + { + year =t.year; + month =t.month; + day =t.day; + max_days_per_month=t.max_days_per_month; + week_day=t.week_day; + year_day=t.year_day; + + return(*this); + } + + const int Date::Comp(const Date &t)const + { + if(year!=t.year) + return year-t.year; + + if(month!=t.month) + return month-t.month; + + return day-t.day; + } + + bool Date::SaveToStream(io::DataOutputStream *str) const + { + if(!str)return(false); + + if(!str->WriteInt32(year))return(false); + if(!str->WriteInt8(month))return(false); + if(!str->WriteInt8(day))return(false); + if(!str->WriteInt8(max_days_per_month))return(false); + if(!str->WriteInt8(week_day))return(false); + if(!str->WriteInt16(year_day))return(false); + + return(true); + } + + bool Date::LoadFromStream(io::DataInputStream *str) + { + if(!str)return(false); + + if(!str->ReadInt32(year))return(false); + if(!str->ReadInt8(month))return(false); + if(!str->ReadInt8(day))return(false); + if(!str->ReadInt8(max_days_per_month))return(false); + if(!str->ReadInt8(week_day))return(false); + if(!str->ReadInt16(year_day))return(false); + + return(true); + } + + Date::Date() + { + year=2000; + month=1; + day=1; + week_day=0; + year_day=0; + max_days_per_month=0; + } + + Date::Date(int y,int m,int d) + { + Set(y,m,d); + } + + void Date::Set(int y,int m,int d,int wd,int yd) + { + day=d; + month=m; + year=y; + week_day=wd; + year_day=yd; + max_days_per_month=0; + } + + void Date::SetMonth(int m) + { + if(m<1) + { + while(m<1) + { + m+=HGL_MONTH_ONE_YEAR; + year--; + } + } + else + { + while(m>HGL_MONTH_ONE_YEAR) + { + m-=HGL_MONTH_ONE_YEAR; + year++; + } + } + + month=m; + + const int md[HGL_MONTH_ONE_YEAR]={31,0,31,30,31,30,31,31,30,31,30,31}; + + if(month==2) + max_days_per_month=((year%4)?28:29); + else + max_days_per_month=md[month-1]; + } + + void Date::SetDay(int d) + { + int m=month; + + if(d<1) + { + while(d<1) + { + d+=max_days_per_month; + m--; + } + } + else + { + while(d>max_days_per_month) + { + d-=max_days_per_month; + m++; + } + } + + day=d; + SetMonth(m); + } +}//namespace hgl + +namespace hgl +{ + double FromDateTime(const Date &d,const Time &t) + { + return FromDateTime(d.GetYear(),d.GetMonth(),d.GetDay(), + t.GetHour(),t.GetMinute(),t.GetSecond(),t.GetMicroSecond(), + t.GetGMT()); + } +}//namespace hgl diff --git a/src/Other/ExpendString.cpp b/src/Other/ExpendString.cpp new file mode 100644 index 0000000..879df02 --- /dev/null +++ b/src/Other/ExpendString.cpp @@ -0,0 +1,120 @@ +#include +#include +#include + +namespace hgl +{ + Map ExpendString; + + void SetExpendString(const OSString &flag,const OSString &str) + { + OSString flag_string=flag; + + flag_string.LowerCase(); + + ExpendString.Add(flag_string,str); + } + + void ClearExpendString(const OSString &flag) + { + OSString flag_string=flag; + + flag_string.LowerCase(); + + ExpendString.DeleteByKey(flag_string); + } + + bool GetExpendString(const OSString &flag,OSString &str) + { + struct + { + os_char flag[16]; + HGLFlagString index; + } + FlagStringIndex[]= + { + {OS_TEXT("CMGDK" ), hfsCMGDKPath }, + {OS_TEXT("PlugIn" ), hfsPlugInPath }, + {OS_TEXT("GUI" ), hfsGUIPath }, + {OS_TEXT("Start" ), hfsStartPath }, + + {OS_TEXT("OS" ), hfsOSPath }, + {OS_TEXT("Desktop" ), hfsUserDesktopPath }, + {OS_TEXT("CommonDesktop"), hfsCommonDesktopPath}, + {OS_TEXT("Temp" ), hfsTempPath }, + {OS_TEXT("Data" ), hfsUserDataPath }, + {OS_TEXT("Program" ), hfsUserProgramPath }, + + {OS_TEXT("" ), hfsEnd }, + }; + + HGLFlagString index=hfsNone; + + for(int i=0;;i++) + { + if(FlagStringIndex[i].index==hfsEnd) + break; + + if(flag==FlagStringIndex[i].flag) + { + index=FlagStringIndex[i].index; + break; + } + } + + if(index!=hfsNone) + { + str=GetString(index); + return(true); + } + + OSString flag_string=flag; + + flag_string.LowerCase(); + + return ExpendString.Get(flag_string,str); + } + + /** + * 转换特殊扩展字符串 + * @param source 原始字符串 + * @param target 转换后的字符串 + */ + bool ConvertExpendString(const OSString &source,OSString &target) + { + target=source; + + while(true) + { + const os_char *str=target.c_str(); + const os_char *start=hgl::strchr(str,'$'); + const os_char *end; + + if(!start)return(true); + + if(*(start+1)!='(')return(true); + + end=hgl::strchr(start+2,')'); + + if(!end)return(true); + + OSString flag(start+2,end-start-2); + OSString flag_string; + + if(!GetExpendString(flag,flag_string)) + { + LOG_ERROR(OS_TEXT("无法识别的标识串:")+flag); + + return(false); + } + + OSString new_str(str,start-str); + + new_str+=flag_string; + + new_str+=(end+1); + + target=new_str; + } + } +}//namespace hgl diff --git a/src/Other/ThreadFunc.cpp b/src/Other/ThreadFunc.cpp new file mode 100644 index 0000000..137ae11 --- /dev/null +++ b/src/Other/ThreadFunc.cpp @@ -0,0 +1,44 @@ +#include +#include + +namespace hgl +{ + /** + * tips: PTHREAD_CREATE_DETACHED 方式创建的线程,在退出时,自动清除线程。无法使用pthread_join函数获取运行状态,pthread_join会返回22号错误 + * PTHREAD_CREATE_JOINABLE 方式创建的线程,在退出时,不会清除线程,必使使用pthread_join函数获取。或是在退出时使用pthread_detach(pthread_self())。 + */ + + /** + * 线程具体执行函数,会依操作系统的不同而有所差别 + */ + THREAD_FUNC ThreadFunc(Thread *tc) + { + tc->live_lock.Lock(); + + if(tc->ProcStartThread()) + { + while(tc->Execute()) + { + if(tc->exit_lock.TryLock()) + { + tc->exit_lock.Unlock(); + break; + } + } + + tc->ProcEndThread(); + } + + if(tc->IsExitDelete()) + { + tc->live_lock.Unlock(); + + HGL_THREAD_DETACH_SELF + delete tc; + } + else + tc->live_lock.Unlock(); + + return(0); + } +}//namespace hgl diff --git a/src/Other/TimeCount.cpp b/src/Other/TimeCount.cpp new file mode 100644 index 0000000..07f6695 --- /dev/null +++ b/src/Other/TimeCount.cpp @@ -0,0 +1,57 @@ +#include + +namespace hgl +{ + long GetGMTOff(); + + namespace + { + uint64 program_start_time=0; + + long gmt_off=0; //windows下为long + + struct TimeInit + { + TimeInit() + { + program_start_time=GetMicroTime(); + + gmt_off=GetGMTOff(); + } + };//struct TimeInit + + static TimeInit time_init; + }//namespace + + /** + * 返回时区时差 + */ + int GetTimeZone() + { + return gmt_off; + } + + /** + * 取得本地当前时间(双精度) + * @return 当前时间(单位:秒) + */ + double GetLocalDoubleTime() + { + return GetDoubleTime()+GetTimeZone(); + } + + uint64 GetMilliStartTime() + { + return program_start_time/1000; + } + + uint64 GetMicroStartTime() + { + return program_start_time; + } + + double GetDoubleStartTime() + { + return double(program_start_time)/HGL_MICRO_SEC_PER_SEC; + } +}//namespace hgl diff --git a/src/Other/TimeVal.cpp b/src/Other/TimeVal.cpp new file mode 100644 index 0000000..7187e44 --- /dev/null +++ b/src/Other/TimeVal.cpp @@ -0,0 +1,14 @@ +#include + +#if HGL_OS_BSD +#include +#endif// + +namespace hgl +{ + void SetTimeVal(timeval &tv,const double t_sec) + { + tv.tv_sec=t_sec; + tv.tv_usec=(t_sec-(double)tv.tv_sec)*HGL_MICRO_SEC_PER_SEC; + } +}//namespace hgl diff --git a/src/PlugIn/ExternalModule.cpp b/src/PlugIn/ExternalModule.cpp new file mode 100644 index 0000000..7a5b350 --- /dev/null +++ b/src/PlugIn/ExternalModule.cpp @@ -0,0 +1,93 @@ +#include +#include + +namespace hgl +{ + ExternalModule::ExternalModule() + { + fp=nullptr; + } + + ExternalModule::ExternalModule(ExternalModulePointer emp) + { + fp=emp; + } + + ExternalModule::~ExternalModule() + { + Clear(); + } + + void ExternalModule::Clear() + { + if(fp) + { + pi_close(fp); + + fp=nullptr; + } + } + + void *ExternalModule::GetFunc(const char *name) + { + if(fp) + { + void *func=pi_get(fp,name); + + if(!func) + LOG_ERROR("don't find "+UTF8String(name)); + + return(func); + } + else + { + LOG_ERROR("Get func <"+UTF8String(name)+"> error: no load module!"); + + return(nullptr); + } + } + + void *ExternalModule::FindFunc(const char *name) + { + if(fp) + { + void *func=pi_get(fp,name); + + if(func)return(func); + + char _name[HGL_MAX_PATH]; + + _name[0]='_'; + strcpy(_name+1,HGL_MAX_PATH-1,name); + + func=pi_get(fp,_name); + + if(func)return(func); + } + + return(nullptr); + } + + /** + * 读取函数列表 + * @return 成功加载的函数数量 + */ + int ExternalModule::Get(FuncLoad *flp) + { + if(!flp)return(-1); + + int count=0; + + while(flp->func_name[0]) + { + (*(flp->func_pointer))=GetFunc(flp->func_name); + + if(*(flp->func_pointer)) + ++count; + + ++flp; + } + + return(count); + } +}//namespace hgl diff --git a/src/SystemInfo.cpp b/src/SystemInfo.cpp new file mode 100644 index 0000000..0e52f69 --- /dev/null +++ b/src/SystemInfo.cpp @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include + +namespace hgl +{ + using namespace filesystem; + + MemInfo::MemInfo() + { + memset(this,0,sizeof(MemInfo)); + } + + SystemInfo::SystemInfo() + { + memset(os_name,0,sizeof(os_name)); + } + + bool GetSystemPath(OSString &); + void GetOSPath(SystemPath &cp); + + bool CheckEnginePath(OSString &cur_path, + const OSString &work, + const OSString &start, + const OSString &cm, + const OSString &sub) + { + cur_path=MergeFilename(work,sub); + + if(IsDirectory(cur_path)) + return(true); + + if(work!=start) + { + cur_path=MergeFilename(start,sub); + + if(IsDirectory(cur_path)) + return(true); + } + + if(work!=cm) + { + cur_path=MergeFilename(cm,sub); + + if(IsDirectory(cur_path)) + return(true); + } + + OSString out_str=OS_TEXT("Don't find <")+sub+OS_TEXT("> folder from : \"")+work+OS_TEXT("\""); + + if(work!=start) out_str+=(OS_TEXT(",\"")+start +OS_TEXT("\"")); + if(work!=cm) out_str+=(OS_TEXT(",\"")+cm +OS_TEXT("\"")); + + LOG_INFO(out_str); + + return(false); + } + + void GetSystemPath(SystemPath &cp) + { + OSString cur_prog; + OSString cur_path; + + hgl::GetCurrentPath(cp.start); + + if(!GetSystemPath(cp.cm)) + cp.cm=cp.start; //如果没有找到CMGDK系统变量 + + hgl::GetCurrentProgram(cur_prog); + + cur_path=cur_prog; + + const int end_index=cur_path.FindRightChar(HGL_DIRECTORY_SEPARATOR); + + cur_path.ClipLeft(end_index); + + CheckEnginePath(cp.gui, cp.start,cur_path,cp.cm,OS_TEXT("gui")); + CheckEnginePath(cp.plug_ins, cp.start,cur_path,cp.cm,OS_TEXT("plug-in") + OSString(HGL_DIRECTORY_SEPARATOR_STR) + HGL_PLATFORM_STRING); //HGL_PLATFORM_STRING在CMAKE中定义 + + GetOSPath(cp); + + hgl::info::SetString(hfsCMGDKPath, cp.engine ); + hgl::info::SetString(hfsPlugInPath, cp.plug_ins ); + hgl::info::SetString(hfsStartPath, cp.start ); + hgl::info::SetString(hfsOSPath, cp.os ); + hgl::info::SetString(hfsOSLibraryPath, cp.library ); + hgl::info::SetString(hfsUserDesktopPath, cp.mydesktop); + hgl::info::SetString(hfsCommonDesktopPath, cp.desktop ); + hgl::info::SetString(hfsTempPath, cp.temp ); + hgl::info::SetString(hfsUserDataPath, cp.mydata ); + hgl::info::SetString(hfsUserProgramPath, cp.myprogram); + + hgl::info::SetString(hfsAppFileName, cur_prog ); + + LOG_INFO( OS_TEXT(" current program: ")+cur_prog +OS_TEXT("\n\n") + OS_TEXT(" program start folder: ")+cp.start +OS_TEXT("\n\n") + + OS_TEXT("operator system folder: ")+cp.os +OS_TEXT("\n") + OS_TEXT(" os fonts folder: ")+cp.osfont +OS_TEXT("\n") + OS_TEXT(" common library folder: ")+cp.library +OS_TEXT("\n\n") + + OS_TEXT(" common data folder: ")+cp.common_data +OS_TEXT("\n") + OS_TEXT(" local data folder: ")+cp.local_data +OS_TEXT("\n") + OS_TEXT(" user data folder: ")+cp.mydata +OS_TEXT("\n\n") + + OS_TEXT(" temp file folder: ")+cp.temp +OS_TEXT("\n") + OS_TEXT(" user menu folder: ")+cp.myprogram +OS_TEXT("\n") + OS_TEXT(" user desktop folder: ")+cp.mydesktop +OS_TEXT("\n") + OS_TEXT(" common desktop folder: ")+cp.desktop +OS_TEXT("\n\n") + + OS_TEXT(" Engine folder: ")+cp.engine +OS_TEXT("\n") + OS_TEXT(" Engine Plug-in folder: ")+cp.plug_ins +OS_TEXT("\n")); + } + + struct CheckInterface + { + void (*Check)(SystemInfo *); + }; + + void SystemCheck(SystemInfo *si) + { + PlugIn *pi=LoadPlugIn(OS_TEXT("SystemCheck")); + + if(!pi)return; + + CheckInterface ci; + + pi->GetInterface(2,&ci); + + ci.Check(si); + + UnloadPlugIn(pi); + } +}//namespace hgl