Files
TAIXIN/sdk/lib/common/string.c

638 lines
14 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.

#include "basic_include.h"
#include "lib/heap/sysheap.h"
#ifndef PRINT_LEVEL_DEFAULT
#define PRINT_LEVEL_DEFAULT (6)
#endif
#ifndef PRINT_BUFF_SIZE
#define PRINT_BUFF_SIZE (256)
#endif
#define LOWCASE(c) (((c)>='A'&&(c) <= 'Z')?(c)+32:(c))
#define _PRINT_DISABLED_ (BIT(0))
#define _PRINT_COLOR_DISABLED_ (BIT(1))
#define _PRINT_TIME_DISABLED_ (BIT(2))
#define _PRINT_TIME_NTP_ (BIT(3))
#define _PRINT_REDIRECT_DUAL_ (BIT(4))
__bobj static osprint_hook __print_hook;
__bobj static void *__print_hook_priv;
__bobj void *console_handle;
__bobj int8 __print_level__;
__bobj uint8 __print_ctrl__;
__bobj char _print_buff_p[PRINT_BUFF_SIZE];
static const char *__print_color__[] = {
"\e[40;35;7m", //KERN_EMERG : Red
"\e[40;35;7m", //KERN_ALERT : Red
"\e[40;35;7m", //KERN_CRIT : Red
"\e[40;31m", //KERN_ERR : Red
"\e[40;33m", //KERN_WARNING: Yellow
"\e[40;32m", //KERN_NOTICE : Green
"\e[40;34m", //KERN_INFO : Blue
"\e[40;30m", //KERN_DEBUG : Black/Default
"\e[0m", //END
};
int printf(const char *format, ...) __alias(hgprintf);
int puts(const char *s) __alias(hgputs);
int __wrap_printf(const char *format, ...) __alias(hgprintf);
int __cskyvprintfprintf(const char *format, ...) __alias(hgprintf);
////////////////////////////////////////////////////////////////////////
int32 hexchr2int(char c)
{
if (c >= '0' && c <= '9') {
return c - '0';
}
if (c >= 'a' && c <= 'f') {
return c - 'a' + 10;
}
if (c >= 'A' && c <= 'F') {
return c - 'A' + 10;
}
return -1;
}
int32 hex2char(char *hex_str)
{
int a, b;
a = hexchr2int(*hex_str++);
if (a < 0) {
return -1;
}
b = hexchr2int(*hex_str++);
if (b < 0) {
return -1;
}
return (a << 4) | b;
}
int32 hex2bin(char *hex_str, uint8 *bin, uint32 len)
{
uint32 i = 0;
uint32 str_len = 0;
int32 a;
char *ipos = hex_str;
uint8 *opos = bin;
if (!hex_str || !bin) {
return i;
}
str_len = os_strlen(hex_str);
for (i = 0; i < len && (i * 2) + 2 <= str_len; i++) {
a = hex2char(ipos);
if (a < 0) {
return i;
}
*opos++ = (uint8)a;
ipos += 2;
}
return i;
}
void str2mac(char *macstr, uint8 *mac)
{
mac[0] = hex2char(macstr);
mac[1] = hex2char(macstr + 3);
mac[2] = hex2char(macstr + 6);
mac[3] = hex2char(macstr + 9);
mac[4] = hex2char(macstr + 12);
mac[5] = hex2char(macstr + 15);
}
uint32 str2ip(char *ipstr)
{
char *ptr = ipstr;
uint32 ip = os_atoi(ipstr);
do {
if (*ptr == '.') {
ptr++;
ip = (ip << 8 | os_atoi(ptr));
}
ptr++;
} while (*ptr);
return os_htonl(ip);
}
uint64 _os_atoh(char *str, int8 count)
{
uint64 val = 0;
int32 s = 0;
int8 cnt = 1;
if (os_strlen(str) > 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
str += 2;
}
while (*str && cnt++ <= count) {
s = hexchr2int(*str);
if (s == -1) {
break;
}
val = (val << 4) + s;
str++;
}
return val;
}
uint32 os_atoh(char *str)
{
return (uint32)_os_atoh(str, 8);
}
uint64 os_atohl(char *str)
{
return _os_atoh(str, 16);
}
char *os_strdup(const char *s)
{
size_t len;
char *d;
if (s == NULL) {
return NULL;
}
len = strlen(s);
d = os_malloc(len + 1);
if (d == NULL) {
return NULL;
}
os_memcpy(d, s, len);
d[len] = '\0';
return d;
}
void print_redirect(osprint_hook print, void *priv, uint8 dual_out)
{
uint32 flag = disable_irq();
__print_hook = print;
__print_hook_priv = priv;
if(dual_out){
__print_ctrl__ |= _PRINT_REDIRECT_DUAL_;
} else {
__print_ctrl__ &= ~ _PRINT_REDIRECT_DUAL_;
}
enable_irq(flag);
}
void print_level(int8 level)
{
__print_level__ = level;
}
void disable_print(int8_t dis)
{
if(dis){
__print_ctrl__ |= _PRINT_DISABLED_;
}else{
__print_ctrl__ &= ~ _PRINT_DISABLED_;
}
}
void disable_print_color(int8_t dis)
{
if(dis){
__print_ctrl__ |= _PRINT_COLOR_DISABLED_;
}else{
__print_ctrl__ &= ~ _PRINT_COLOR_DISABLED_;
}
}
void disable_print_time(int8_t dis)
{
if(dis){
__print_ctrl__ |= _PRINT_TIME_DISABLED_;
}else{
__print_ctrl__ &= ~ _PRINT_TIME_DISABLED_;
}
}
void print_with_ntp(uint8 en)
{
if(en){
__print_ctrl__ |= _PRINT_TIME_NTP_;
}else{
__print_ctrl__ &= ~ _PRINT_TIME_NTP_;
}
}
static void hgprintf_uart(char *str, int32 len)
{
int32 off = 0;
if (len == 0) { len = os_strlen(str); }
while (off < len) {
uart_putc((struct uart_device *)console_handle, str[off++]);
}
}
void hgprintf_out(char *str, int32 len, uint8 level)
{
osprint_hook _print;
void *_print_priv;
uint8 color = 0;
uint32 flag = disable_irq();
_print_priv = __print_hook_priv;
_print = __print_hook;
enable_irq(flag);
if (__print_level__ && level > __print_level__) {
return;
}
if (level > 7)
level = 7;
if(level < 7 && !(__print_ctrl__ & _PRINT_COLOR_DISABLED_))
color = level;
if (_print) {
if (color) _print(_print_priv, (char *)__print_color__[color], 0);
_print(_print_priv, str, len);
if (color) _print(_print_priv, (char *)__print_color__[8], 0);
}
if(_print == NULL || (__print_ctrl__ & _PRINT_REDIRECT_DUAL_)){
if (color) hgprintf_uart((char *)__print_color__[color], 0);
hgprintf_uart(str, len);
if (color) hgprintf_uart((char *)__print_color__[8], 0);
}
if (color) sys_errlog_save((char *)__print_color__[color], 0, level);
sys_errlog_save(str, len, level);
if (color) sys_errlog_save((char *)__print_color__[8], 0, level);
}
void hgvprintf(const char *fmt, va_list ap)
{
int32 ret = 0;
int32 len = 0;
uint8 level = 7;
uint8 tick = 0;
struct timeval tv;
struct tm *tm_t;
if (__print_ctrl__ & _PRINT_DISABLED_) {
return;
}
if (fmt[0] == 2) {
tick = !(__print_ctrl__ & _PRINT_TIME_DISABLED_);
fmt++;
}
if (fmt[0] == 1) {
level = fmt[1] - '0';
fmt += 2;
}
if (__print_level__ && level > __print_level__) {
return;
}
if (tick) {
len = sprintf(_print_buff_p, "[%llu]", os_jiffies_to_msecs(os_jiffies()));
if (__print_ctrl__ & _PRINT_TIME_NTP_) {
gettimeofday(&tv, NULL);
if(tv.tv_sec > 1704038400){
tm_t = localtime((const time_t *)&tv.tv_sec);
len += sprintf(_print_buff_p + len, "[%02d/%02d %02d:%02d:%02d-%03llu]",
tm_t->tm_mon + 1, tm_t->tm_mday, tm_t->tm_hour,
tm_t->tm_min, tm_t->tm_sec, tv.tv_usec / 1000);
}
}
}
ret = vsnprintf(_print_buff_p + len, (PRINT_BUFF_SIZE - 2 - len), fmt, ap);
if (ret < 0 || ret > (PRINT_BUFF_SIZE - 2 - len)) {
len = PRINT_BUFF_SIZE - 1;
_print_buff_p[len - 1] = '\n';
_print_buff_p[len - 2] = '\r';
} else {
len += ret;
}
if (len > 0) {
if (_print_buff_p[len - 1] == '\n' && _print_buff_p[len - 2] != '\r') {
_print_buff_p[len - 1] = '\r';
_print_buff_p[len++] = '\n';
}
_print_buff_p[len] = 0;
hgprintf_out(_print_buff_p, len, level);
}
}
void hgprintf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
hgvprintf(fmt, ap);
va_end(ap);
}
int hgputs(const char *s)
{
hgprintf("%s", s);
return os_strlen(s) + 1;
}
void dump_hex(char *title, uint8 *data, uint32 len, int32 newline)
{
int i = 0;
if (data && len) {
_os_printf("[dump address: %p]\r\n", data);
if (title) _os_printf("%s", title);
for (i = 0; i < len; i++) {
if (i > 0 && newline) {
if ((i & 0x7) == 0) _os_printf(" ");
if ((i & 0xf) == 0) _os_printf("\r\n");
}
_os_printf("%02x ", data[i] & 0xFF);
}
_os_printf("\r\n");
}
}
void dump_memory(char *title, uint32 *data, uint32 len)
{
int i = 0;
if (data && len) {
if (title) _os_printf("%s", title);
for (i = 0; i < len; i++) {
if ((i & 0x7) == 0) _os_printf("0x%x: ", data+i);
if ((i & 0x7) == 7) _os_printf("\r\n");
_os_printf("%x ", data[i]);
}
_os_printf("\r\n");
}
}
void dump_key(char *str, uint8 *key, uint32 len, uint32 sp)
{
int32 i = 0;
if (key && len) {
if (str) _os_printf("%s", str);
for (i = 0; i < len; i++) {
if (sp) {
_os_printf("%02x ", key[i]);
} else {
_os_printf("%02x", key[i]);
}
}
_os_printf("\r\n");
}
}
// str_buf申请的空间需要比key_len多1bytesprintf会额外在字符串结束添加0
void key_str(uint8 *key, uint32 key_len, char *str_buf)
{
int32 i = 0;
for (i = 0; i < key_len; i++) {
os_sprintf(str_buf + i * 2, "%02x", key[i]);
}
}
void *_os_memcpy(void *str1, const void *str2, int32 n)
{
#ifdef MEM_TRACE
#ifdef PSRAM_HEAP
void *heap = IS_PSRAM_ADDR(str1) ? (void *)(&psram_heap) : (void *)(&sram_heap);
#else
void *heap = &sram_heap;
#endif
int32 ret = sysheap_of_check(heap, str1, n);
if (ret == 0) {
os_printf(KERN_WARNING"%s: memroy %p maybe overflow!!\r\n", __FUNCTION__, str1);
}
#endif
return memcpy(str1, str2, n);
}
char *_os_strcpy(char *dest, const char *src)
{
#ifdef MEM_TRACE
#ifdef PSRAM_HEAP
void *heap = IS_PSRAM_ADDR(dest) ? (void *)(&psram_heap) : (void *)(&sram_heap);
#else
void *heap = &sram_heap;
#endif
int32 n = strlen(src) + 1; // +'\0'
int32 ret = sysheap_of_check(heap, dest, n);
if (ret == 0) {
os_printf(KERN_WARNING"%s: memroy %p maybe overflow!!\r\n", __FUNCTION__, dest);
}
#endif
return strcpy(dest, src);
}
void *_os_memset(void *str, int c, int32 n)
{
#ifdef MEM_TRACE
#ifdef PSRAM_HEAP
void *heap = IS_PSRAM_ADDR(str) ? (void *)(&psram_heap) : (void *)(&sram_heap);
#else
void *heap = &sram_heap;
#endif
int32 ret = sysheap_of_check(heap, str, n);
if (ret == 0) {
os_printf(KERN_WARNING"%s: memroy %p maybe overflow!!\r\n", __FUNCTION__, str);
}
#endif
return memset(str, c, n);
}
void *_os_memmove(void *str1, const void *str2, size_t n)
{
#ifdef MEM_TRACE
#ifdef PSRAM_HEAP
void *heap = IS_PSRAM_ADDR(str1) ? (void *)(&psram_heap) : (void *)(&sram_heap);
#else
void *heap = &sram_heap;
#endif
int32 ret = sysheap_of_check(heap, str1, n);
if (ret == 0) {
os_printf(KERN_WARNING"%s: memroy %p maybe overflow!!\r\n", __FUNCTION__, str1);
}
#endif
return memmove(str1, str2, n);
}
char *_os_strncpy(char *dest, const char *src, int32 n)
{
#ifdef MEM_TRACE
#ifdef PSRAM_HEAP
void *heap = IS_PSRAM_ADDR(dest) ? (void *)(&psram_heap) : (void *)(&sram_heap);
#else
void *heap = &sram_heap;
#endif
int32 ret = sysheap_of_check(heap, dest, n);
if (ret == 0) {
os_printf(KERN_WARNING"%s: memroy %p maybe overflow!!\r\n", __FUNCTION__, dest);
}
#endif
return strncpy(dest, src, n);
}
int _os_sprintf(char *str, const char *format, ...)
{
#ifdef MEM_TRACE
int ret;
#ifdef PSRAM_HEAP
void *heap = IS_PSRAM_ADDR(str) ? (void *)(&psram_heap) : (void *)(&sram_heap);
#else
void *heap = &sram_heap;
#endif
#endif
int len;
va_list ap;
va_start(ap, format);
len = vsprintf(str, format, ap);
va_end(ap);
#ifdef MEM_TRACE
ret = sysheap_of_check(heap, str, len+1);
if (ret == 0) {
os_printf(KERN_WARNING"%s: memroy %p maybe overflow!!\r\n", __FUNCTION__, str);
}
#endif
return len;
}
int _os_vsnprintf(char *s, size_t n, const char *format, va_list arg)
{
#ifdef MEM_TRACE
#ifdef PSRAM_HEAP
void *heap = IS_PSRAM_ADDR(s) ? (void *)(&psram_heap) : (void *)(&sram_heap);
#else
void *heap = &sram_heap;
#endif
#endif
int len = vsnprintf(s, n, format, arg);
#ifdef MEM_TRACE
int check_len = (len < n) ? len + 1 : n;
int ret = sysheap_of_check(heap, s, check_len);
if (ret == 0) {
os_printf(KERN_WARNING"%s: memroy %p maybe overflow!!\r\n", __FUNCTION__, s);
}
#endif
return len;
}
int _os_snprintf(char *str, size_t size, const char *format, ...)
{
#ifdef MEM_TRACE
int ret;
#ifdef PSRAM_HEAP
void *heap = IS_PSRAM_ADDR(str) ? (void *)(&psram_heap) : (void *)(&sram_heap);
#else
void *heap = &sram_heap;
#endif
#endif
int len;
va_list ap;
va_start(ap, format);
len = vsnprintf(str, size, format, ap);
va_end(ap);
#ifdef MEM_TRACE
int check_len = (len < size) ? len + 1 : size;
ret = sysheap_of_check(heap, str, check_len);
if (ret == 0) {
os_printf(KERN_WARNING"%s: memroy %p maybe overflow!!\r\n", __FUNCTION__, str);
}
#endif
return len;
}
int32 os_strtok(char *str, char *separator, char *argv[], int argv_size)
{
int32 cnt = 0;
char *ptr = str;
if (str == NULL || separator == NULL || argv == NULL || argv_size <= 0) {
return 0;
}
argv[cnt++] = ptr;
ptr = os_strstr(ptr, separator);
while (ptr && cnt < argv_size) {
*ptr = 0;
ptr += os_strlen(separator);
if (os_strlen(ptr) == 0) {
break;
}
argv[cnt++] = ptr;
ptr = os_strstr(ptr, separator);
}
return cnt;
}
const char *os_strncasechr(const char *s, char c, int32 n)
{
if (!s) return NULL;
c = LOWCASE(c);
// strcasechr
if (n < 0) {
while (*s) {
if (LOWCASE(*s) == c) {
return s;
}
s++;
}
return NULL;
} else {
for (int32 i = 0; i < n; i++) {
if (s[i] == '\0') break;
if (LOWCASE(s[i]) == c) {
return &s[i];
}
}
return NULL;
}
}
const char *os_strncasestr(const char *str1, const char *str2, int32 n)
{
if (!str1 || !str2) return NULL;
if (str2[0] == '\0') return str1;
int32 len2 = 0;
while (str2[len2]) len2++;
int32 len1 = n;
if (n < 0) {
len1 = 0x7FFFFFFF;
}
if (len2 > len1) return NULL;
const char *p = str1;
while (*p && (p - str1) <= len1 - len2) {
if (LOWCASE(p[0]) == LOWCASE(str2[0])) {
if (os_strncasecmp(p, str2, len2) == 0) {
return p;
}
}
p++;
}
return NULL;
}