ULRE/inc/hgl/Str.h
2019-06-04 19:15:06 +08:00

2594 lines
59 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef HGL_STR_TEMPLATE_INCLUDE
#define HGL_STR_TEMPLATE_INCLUDE
#include<hgl/TypeFunc.h>
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表情<br>
* 参见https://unicode.org/Public/emoji/12.0/emoji-data.txt
*/
template<typename T>
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<typename T>
bool islower(const T ch)
{
return(ch>='a'&&ch<='z');
}
/**
* 测试当前字符是否为大写字母
*/
template<typename T>
bool isupper(const T ch)
{
return(ch>='A'&&ch<='Z');
}
/**
* 测试当前字符是否为字母
*/
template<typename T>
bool isalpha(const T ch)
{
return(islower(ch)||isupper(ch));
}
/**
* 测试当前字符是否为10进制数字
*/
template<typename T>
bool isdigit(const T ch)
{
return(ch>='0'&&ch<='9');
}
/**
* 测试当前字符串是否为10进制数字以及小数点、正负符号、指数字符
*/
template<typename T>
bool isfloat(const T ch)
{
return isdigit(ch)
||ch=='-'
||ch=='+'
||ch=='.'
||ch=='E'
||ch=='e';
}
template<typename T>
bool isinteger(const T ch)
{
return isdigit(ch)
||ch=='-'
||ch=='+';
}
/**
* 测试当前字符是否为16进制数用字符(0-9,A-F)
*/
template<typename T>
bool isxdigit(const T ch)
{
return((ch>='0'&&ch<='9')
||(ch>='a'&&ch<='f')
||(ch>='A'&&ch<='F'));
}
/**
* 测试当前字符串是否为16进制数用字符
* @param str 字符串
* @param length 字符串长度
*/
template<typename T>
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<typename T>
bool isspace(const T ch)
{
return(ch==' '||ch=='\t'||ch=='\r'||ch=='\f'||ch=='\v'||ch=='\n');
}
/**
* 测试当前字符是否为字母或数字
*/
template<typename T>
bool isalnum(const T ch)
{
return(isalpha(ch)||isdigit(ch));
}
/**
* 测试当前字符是否为代码可用字符(仅字母,数字,下划线,常用于文件名之类)
*/
template<typename T>
bool iscodechar(const T ch)
{
return(isalnum(ch)||ch=='_');
}
/**
* 测试当前字符是否为BASE64编码字符
*/
template<typename T>
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<typename T>
T tolower(const T ch)
{
if(ch>='A'&&ch<='Z')
return ch+('a'-'A');
else
return ch;
}
/**
* 如果当前字符为小写英文字符,则转换为大写
*/
template<typename T>
T toupper(const T ch)
{
if(ch>='a'&&ch<='z')
return ch+('A'-'a');
else
return ch;
}
/**
* 比较两个字符的大小(英文不区分大小写)
*/
template<typename S,typename D>
int chricmp(S src,D dst)
{
return tolower(src)-tolower(dst);
}
/**
* 对宽字符串计算字串长度
* @param str 要计算长度的字符串指针
* @return 字符串长度
*/
template<typename T>
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<typename T>
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<typename T>
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<typename T>
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<typename T1,typename T2>
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<typename T1,typename T2>
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<typename T>
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<typename T>
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<typename T>
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<typename TS,typename TC>
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<typename TS,typename TC>
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<typename TS,typename TC>
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<typename TS,typename TC>
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<typename TS,typename TC>
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<typename TS,typename TC>
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<typename TS,typename TC>
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<typename S,typename D>
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<typename S,typename D>
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<typename S,typename D>
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<typename S,typename D>
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<typename S,typename D>
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<typename S,typename D>
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<typename S,typename D>
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<typename T>
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<typename T>
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<typename T>
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<typename T>
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<typename T>
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<typename T>
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<typename T>
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<typename T>
void toupper(T *str)
{
if(!str)return;
while(*str)
{
if(*str>='a'&&*str<='z')
*str-=32;
++str;
}
}
/**
* 将一个字符串中的字母全部改为小写
* @param src 要处理的字符串
*/
template<typename T>
void tolower(T *str)
{
if(!str)return;
while(*str)
{
if(*str>='A'&&*str<='Z')
*str+=32;
++str;
}
}
/**
* 将一个字符串中的字母全部改为大写
* @param src 要处理的字符串
*/
template<typename T>
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<typename T>
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<typename T>
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<typename T>
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<typename T>
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<typename T>
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<typename T>
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<typename T>
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<typename T>
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<typename T>
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<typename T>
int stat_char(T *str,T ch)
{
if(!str)return(0);
int count=0;
while(*str)
{
if(*str==ch)
++count;
++str;
}
return(count);
}
/**
* 统计一个字符串的行数
*/
template<typename T>
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<typename R,typename S>
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<typename R,typename S>
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<typename R,typename S>
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<typename R,typename S>
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<typename R,typename S>
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<typename R,typename S>
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<typename R,typename S>
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<typename R,typename S>
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<typename R,typename S>
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<typename T>
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<typename T,typename I>
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<typename T,typename I>
T *itos(T *str,int size,const I num)
{
itos_rl(str,size,num);
return str;
}
/**
* 转换一个无符号整数到字符串
* @param str 转换后的字符串存放处
* @param size 存放处可容纳的字符数
* @param value 要转换的数值
* @return 转换后的字符串
*/
template<typename T,typename U>
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<typename T,typename U>
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<int BITS> struct htos_bits
{
template<typename T,typename U> static T *conv(T *str,int size,U value,bool upper);
};
template<> struct htos_bits<1>{template<typename T,typename U> 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<typename T,typename U> 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<typename T,typename U> 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<typename T,typename U> 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<typename T,typename U>
T *htos(T *str,int size,U value,bool upper=true)
{
return htos_bits<sizeof(U)>::template conv<T,U>(str,size,value,upper);
}
/**
* 转换一个无符号整数到字符串(以大写16进制表示)
* @param str 转换后的字符串存放处
* @param size 存放处可容纳的字符数
* @param value 要转换的数值
* @return 转换后的字符串
*/
template<typename T,typename U> T *htos_upper(T *str,int size,U value){return htos<T,U>(str,size,value,true);}
/**
* 转换一个无符号整数到字符串(以小写16进制表示)
* @param str 转换后的字符串存放处
* @param size 存放处可容纳的字符数
* @param value 要转换的数值
* @return 转换后的字符串
*/
template<typename T,typename U> T *htos_lower(T *str,int size,U value){return htos<T,U>(str,size,value,false);}
/**
* 转换一个浮点数到字符串
* @param str 字符串保存指针
* @param size 字符串保存空间长度
* @param fsize 小数部分保留长度
* @param value 要转换的值
*/
template<typename T,typename F>
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(value<min_value)
{
*p=0;
return(str);
}
*p++='.'; //加小数点
++len;
while(value>min_value&&len<size&&fsize--)
{
value*=10; //让最上一位变成个位数
*p++='0'+int(value);
value-=int(value); //减去整数部分
++len;
}
*p=0;
return(str);
}
template<typename T,typename F>
T *ftos(T *str,int size,F value)
{
return ftos(str,size,4,value);
}
/**
* 转换一个整数到计算机表示法
* @param str 字符串保存指针
* @param size 字符串保存空间长度
* @param value 要转换的值
* @return 是否转换成功
*/
template<typename T,typename V>
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<typename T>
int find_str_array(int count,const T **str_array,const T *str)
{
for(int i=1;i<count;i++)
if(stricmp<T>(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<typename T,typename I,bool (*IS_FUNC)(const T &),bool (*STOV)(const T *str,I &)>
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<typename T,typename I> 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<T,I,hgl::isfloat, hgl::etof>(str,result,max_count,end_char,end_pointer);}
template<typename T,typename I> 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<T,I,hgl::isinteger, hgl::stoi>(str,result,max_count,end_char,end_pointer);}
template<typename T,typename I> 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<T,I,hgl::isdigit, hgl::stou>(str,result,max_count,end_char,end_pointer);}
template<typename T,typename I> 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<T,I,hgl::isxdigit, hgl::xtou>(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<typename T,typename I,typename SET,bool (*IS_FUNC)(const T &),bool (*STOV)(const T *str,I &)>
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<typename T,typename I,typename SET> inline int parse_float_array (const T *str,const int len,SET &result_list){return parse_number_array<T,I,SET,hgl::isfloat, hgl::etof>(str,len,result_list);}
template<typename T,typename I,typename SET> inline int parse_int_array (const T *str,const int len,SET &result_list){return parse_number_array<T,I,SET,hgl::isinteger, hgl::stoi>(str,len,result_list);}
template<typename T,typename I,typename SET> inline int parse_uint_array (const T *str,const int len,SET &result_list){return parse_number_array<T,I,SET,hgl::isdigit, hgl::stou>(str,len,result_list);}
template<typename T,typename I,typename SET> inline int parse_xint_array (const T *str,const int len,SET &result_list){return parse_number_array<T,I,SET,hgl::isxdigit, hgl::xtou>(str,len,result_list);}
/**
* 按指定分隔符拆分字符串为多个字符串
* @param str 要拆分的字符串
* @param str_len 字符串长度
* @param sc 分隔字符
* @param result_list 拆分后的字符串保存的列表
* @return 拆分出来的字符串数量
* @return -1 出错
*/
template<typename T,typename S>
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<typename T> 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<typename T> 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<typename T> 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<uint NUM,typename T>
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<typename T>
inline void ParseHexStr(uint8 *dst,const T *src,const int size)
{
for(int i=0;i<size;i++)
{
*dst =parse_number_char<16,T>(*src)<<4;
++src;
*dst|=parse_number_char<16,T>(*src);
++src;
++dst;
}
}
/**
* 将一个16进制数值字符串转换成原始数据
* @param str 16进制数值字符串
* @param hc 解晰出来的原始数据存入处
*/
template<typename T,typename HC>
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<typename T>
void DataToHexStr(T *str,const uint8 *src,const int size,const char *hexstr,const T gap_char=0)
{
int i;
for(i=0;i<size;i++)
{
if(i&&gap_char)
{
*str=gap_char;
++str;
}
*str=hexstr[((*src)&0xF0)>>4];
++str;
*str=hexstr[ (*src)&0x0F ];
++str;
++src;
}
*str=0;
}
template<typename T> void DataToLowerHexStr(T *str,const uint8 *src,const int size,const T gap_char=0){DataToHexStr<T>(str,src,size,LowerHexChar,gap_char);}
template<typename T> void DataToUpperHexStr(T *str,const uint8 *src,const int size,const T gap_char=0){DataToHexStr<T>(str,src,size,UpperHexChar,gap_char);}
/**
* 将一串原始数据转转成16进制数值字符串
* @param str 16进制数值字符串存入处
* @param hc 原始的数据
* @param hexstr 用于转换的16进制字符
* @param gap_char 间隔字符
*/
template<typename T,typename HC>
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<typename T,typename HC> void ToUpperHexStr(T *str,const HC &hc,const T gap_char=0){DataToHexStr<T,HC>(str,hc,UpperHexChar,gap_char);}
template<typename T,typename HC> void ToLowerHexStr(T *str,const HC &hc,const T gap_char=0){DataToHexStr<T,HC>(str,hc,LowerHexChar,gap_char);}
template<typename T> void ToUpperHexStr(T *str,const void *data,const int size,const T gap_char=0){DataToHexStr<T>(str,(const uint8 *)data,size,UpperHexChar,gap_char);}
template<typename T> void ToLowerHexStr(T *str,const void *data,const int size,const T gap_char=0){DataToHexStr<T>(str,(const uint8 *)data,size,LowerHexChar,gap_char);}
}//namespace hgl
#endif//HGL_STR_TEMPLATE_INCLUDE