414 lines
8.5 KiB
C
414 lines
8.5 KiB
C
#include "string.h"
|
|
#include "cutil.h"
|
|
#include "va_list.h"
|
|
|
|
size_t cu_strlen(const char* str)
|
|
{
|
|
u32 len = 0;
|
|
while(*str++) len++;
|
|
return len;
|
|
}
|
|
|
|
void cu_strcpy(char* dst, const char* src)
|
|
{
|
|
while((*dst++ = *src++)){}
|
|
}
|
|
|
|
void cu_strncpy(char* dst, const char* src, size_t maxLen)
|
|
{
|
|
maxLen=-1;
|
|
while((*dst++ = *src++) && --maxLen){}
|
|
if(!maxLen) dst[maxLen] = '\0';
|
|
}
|
|
|
|
const char* cu_strchr(const char* src, char chr)
|
|
{
|
|
while(*src)
|
|
{
|
|
if(*src == chr) return src;
|
|
src++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
const char* cu_strrchr(const char* src, char chr)
|
|
{
|
|
const char* ptr;
|
|
|
|
ptr = src+cu_strlen(src)-1;
|
|
while(ptr != src)
|
|
{
|
|
if(*ptr == chr) return ptr;
|
|
ptr--;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int cu_strcmp(const char* src, const char* dst)
|
|
{
|
|
if(cu_strlen(src) != cu_strlen(dst)) return 1;
|
|
while(*src)
|
|
if(*src++ != *dst++) return 1;
|
|
return 0;
|
|
}
|
|
|
|
int cu_strncmp(const char* haystack, char* needle)
|
|
{
|
|
return !!cu_memcmp(haystack,needle,cu_strlen(needle));
|
|
}
|
|
|
|
int cu_strcasecmp(const char* src, const char* dst)
|
|
{
|
|
if(cu_strlen(src) != cu_strlen(dst)) return 1;
|
|
while(*src)
|
|
{
|
|
if(cu_tolower(*src++) != cu_tolower(*dst++))
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
char cu_toupper(char c)
|
|
{
|
|
if(c >= 0x61 && c <= 0x7A) return c&0xDF;
|
|
return c;
|
|
}
|
|
|
|
char cu_tolower(char c)
|
|
{
|
|
if(c >= 0x41 && c <= 0x5A) return c|(1<<5);
|
|
return c;
|
|
}
|
|
|
|
size_t cu_chrlen(char cchr)
|
|
{
|
|
u8 chr = (u8)cchr;
|
|
|
|
if(chr & 0b10000000)
|
|
{
|
|
if((chr>>5) == 0b110) return 2;
|
|
else if((chr>>4) == 0b1110) return 3;
|
|
else if((chr>>5) == 0b11110) return 4;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
dbcs_t cu_chr2dbcs(const char* ptr)
|
|
{
|
|
const u8* chr = (u8*)ptr;
|
|
|
|
switch(cu_chrlen(chr[0]))
|
|
{
|
|
case 1: return chr[0]&0x7F;
|
|
case 2: return ((chr[0]&0x1F)<<6)|(chr[1]&0x3F);
|
|
case 3: return ((chr[0]&0x0F)<<12)|((chr[1]&0x3F)<<6)|(chr[2]&0x3F);
|
|
default: return 0x003F;
|
|
}
|
|
}
|
|
|
|
size_t cu_dbcslen(dbcs_t chr)
|
|
{
|
|
if(chr > 0x7FF) return 3;
|
|
else if(chr > 0x7F) return 2;
|
|
return 1;
|
|
}
|
|
|
|
void cu_dbcs2str(dbcs_t* dbcs, char* str, size_t maxStr)
|
|
{
|
|
char* end = str + maxStr - 1;
|
|
dbcs_t wc;
|
|
|
|
while((wc = *dbcs++) && str != end)
|
|
{
|
|
size_t len = cu_dbcslen(wc);
|
|
if((str+len) >= end) break;
|
|
switch(len)
|
|
{
|
|
case 1:
|
|
*str++ = wc&0x7F;
|
|
break;
|
|
case 2:
|
|
*str++ = 0b11000000|((wc>>6)&0x1F);
|
|
*str++ = 0b10000000|((wc)&0x3F);
|
|
break;
|
|
case 3:
|
|
*str++ = 0b11100000|((wc>>12)&0x0F);
|
|
*str++ = 0b10000000|((wc>>6)&0x3F);
|
|
*str++ = 0b10000000|((wc)&0x3F);
|
|
break;
|
|
default: *str++ = '?';
|
|
}
|
|
}
|
|
*str++ = '\0';
|
|
}
|
|
|
|
static char* xnums = "0123456789ABCDEF";
|
|
|
|
void cu_iprints(char* outs, iword number)
|
|
{
|
|
//18446744073709551615
|
|
char num[32];
|
|
char* s = num;
|
|
int uns = 0;
|
|
|
|
if(number < 0)
|
|
{
|
|
uns = 1;
|
|
number *= -1;
|
|
}
|
|
while(number >= 10)
|
|
{
|
|
*s++ = '0'+(number%10);
|
|
number/=10;
|
|
}
|
|
*s++ = '0'+(number%10);
|
|
if(uns) *s++ = '-';
|
|
while(s >= num) *outs++ = *--s;
|
|
*outs++ = '\0';
|
|
}
|
|
|
|
void cu_uprints(char* outs, uword number)
|
|
{
|
|
//18446744073709551615
|
|
char num[32];
|
|
char* s = num;
|
|
while(number >= 10)
|
|
{
|
|
*s++ = '0'+(number%10);
|
|
number/=10;
|
|
}
|
|
*s++ = '0'+(number%10);
|
|
while(s >= num) *outs++ = *--s;
|
|
*outs++ = '\0';
|
|
}
|
|
|
|
void cu_xprints(char* outs, uword number)
|
|
{
|
|
//FFFFFFFFFFFFFFFF
|
|
char num[32];
|
|
char* s = num;
|
|
|
|
while(s-num < 15)
|
|
{
|
|
*s++ = xnums[(number%16)];
|
|
number/=16;
|
|
}
|
|
*s++ = xnums[(number%16)];
|
|
*s++ = 'x';
|
|
*s++ = '0';
|
|
while(s >= num) *outs++ = *--s;
|
|
*outs++ = '\0';
|
|
}
|
|
|
|
static iword _cu_atoi(char* str, int base, size_t len)
|
|
{
|
|
char* end;
|
|
iword i, pow;
|
|
iword num;
|
|
|
|
i = 0;
|
|
num = 0;
|
|
pow = 1;
|
|
end = str+len-1;
|
|
while(1)
|
|
{
|
|
if(*end == '-')
|
|
{
|
|
num *= -1;
|
|
break;
|
|
}
|
|
else if(*end == 'x') break;
|
|
for(i = 0; i < base; i++)
|
|
if(*end == xnums[i]) break;
|
|
num += i*pow;
|
|
pow *= base;
|
|
|
|
if(end == str) break;
|
|
end--;
|
|
}
|
|
|
|
return num;
|
|
}
|
|
|
|
static uword _cu_atou(char* str, int base, uword len)
|
|
{
|
|
char* end;
|
|
uword pow, num;
|
|
iword i;
|
|
|
|
i = 0;
|
|
num = 0;
|
|
pow = 1;
|
|
end = str+len-1;
|
|
while(1)
|
|
{
|
|
if(*end == 'x') break;
|
|
for(i = 0; i < base; i++)
|
|
if(*end == xnums[i]) break;
|
|
num += i*pow;
|
|
pow *= base;
|
|
|
|
if(end == str) break;
|
|
end--;
|
|
}
|
|
|
|
return num;
|
|
}
|
|
|
|
iword cu_atoi(char* str, int base)
|
|
{
|
|
return _cu_atoi(str, base, cu_strlen(str));
|
|
}
|
|
|
|
uword cu_atou(char* str, int base)
|
|
{
|
|
return _cu_atou(str, base, cu_strlen(str));
|
|
}
|
|
|
|
void cu_sprintf(char* dst, size_t maxLen, const char* fmt, ...)
|
|
{
|
|
cu_va_list ap;
|
|
cu_va_start(&ap);
|
|
|
|
uword idx;
|
|
char* cur,*end,c;
|
|
char numbuf[64];
|
|
#ifdef CU_ARCH_ARM
|
|
idx = 0;
|
|
#else
|
|
idx = 3;
|
|
#endif
|
|
cur = dst;
|
|
end = dst+maxLen;
|
|
while((c = *fmt++) && cur != end)
|
|
{
|
|
if(c == '%')
|
|
{
|
|
char* p = numbuf;
|
|
c = *fmt++;
|
|
if(c == 'd')
|
|
{
|
|
cu_iprints(numbuf,(iword)cu_va_arg(&ap,idx++));
|
|
while((*cur++ = *p++))
|
|
if(cur == end) break;
|
|
cur--;
|
|
}
|
|
else if(c == 'u')
|
|
{
|
|
cu_uprints(numbuf,(iword)cu_va_arg(&ap,idx++));
|
|
while((*cur++ = *p++))
|
|
if(cur == end) break;
|
|
cur--;
|
|
}
|
|
else if(c == 'p' || c == 'x')
|
|
{
|
|
cu_xprints(numbuf,(uword)cu_va_arg(&ap,idx++));
|
|
while((*cur++ = *p++))
|
|
if(cur == end) break;
|
|
cur--;
|
|
}
|
|
else if(c == 's')
|
|
{
|
|
const char* str = (const char*)cu_va_arg(&ap,idx++);
|
|
while((*cur++ = *str++))
|
|
if(cur == end) break;
|
|
cur--;
|
|
}
|
|
else if(c == '%')
|
|
{
|
|
if(cur != end) *cur++ = '%';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(cur == end) break;
|
|
*cur++ = c;
|
|
}
|
|
}
|
|
if(cur == end)
|
|
*(end-1) = '\0';
|
|
}
|
|
|
|
static uword _cu_strchr_delim(char* buf, u32 base)
|
|
{
|
|
uword i,len;
|
|
char c;
|
|
|
|
len = 0;
|
|
while(*buf)
|
|
{
|
|
c = *buf;
|
|
for(i = 0; i < base; i++)
|
|
{
|
|
if(c == xnums[i]) break;
|
|
}
|
|
if(i == base && c != '-') break;
|
|
buf++;
|
|
len++;
|
|
}
|
|
return len;
|
|
}
|
|
|
|
void cu_sscanf(char* buf, char* fmt, ...)
|
|
{
|
|
//ulong* argp;
|
|
cu_va_list ap;
|
|
cu_va_start(&ap);
|
|
|
|
uword idx;
|
|
uword len, maxLen;
|
|
union {
|
|
iword* iptr;
|
|
uword* uptr;
|
|
char* sptr;
|
|
} u;
|
|
char c,*stk;
|
|
#ifdef CU_ARCH_ARM
|
|
idx = 0;
|
|
#else
|
|
idx = 2;
|
|
#endif
|
|
while((c = *fmt))
|
|
{
|
|
//kprintf("%c %c\n",c,*buf);
|
|
if(c == '%')
|
|
{
|
|
c = *++fmt;
|
|
switch(c)
|
|
{
|
|
case 'u':
|
|
case 'd':
|
|
len = _cu_strchr_delim(buf,10);
|
|
u.iptr = (iword*)(cu_va_arg(&ap,idx++));
|
|
*u.iptr = _cu_atoi(buf,10,len);
|
|
buf += len; //we decrement because it will +1
|
|
break;
|
|
case 'p':
|
|
case 'x':
|
|
buf += 2; //Skip 0x part
|
|
len = _cu_strchr_delim(buf,16);
|
|
u.iptr = (iword*)(cu_va_arg(&ap,idx++));
|
|
*u.iptr = _cu_atoi(buf,16,len);
|
|
buf += len; //we decrement because it will +1
|
|
break;
|
|
case 's':
|
|
stk = (char*)cu_strchr(buf,*(fmt+1));
|
|
u.sptr = (char*)(cu_va_arg(&ap,idx++));
|
|
maxLen = (uword)(cu_va_arg(&ap,idx++));
|
|
if(!stk)
|
|
{
|
|
u.sptr[0] = '\0';
|
|
break;
|
|
}
|
|
len = (uword)stk-(uword)buf;
|
|
if(len > maxLen) len = maxLen;
|
|
cu_memcpy(u.sptr,buf,len);
|
|
u.sptr[len] = '\0';
|
|
buf += len;
|
|
break;
|
|
}
|
|
|
|
} else buf++;
|
|
fmt++;
|
|
}
|
|
}
|