/* 从rotpV3平台拷贝过来的函数,考虑到cpu特性和应用,没有全部拷贝过来,只拷贝了常用的几个函数 ** Description: 字符串相关的工具函数 ** */ #include #include #include "stdio.h" #include "string.h" #include "macro_common.h" /*lint -save -e713 -e715 -e732 -e737 -e415 -e661 -e530*/ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args); static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, const char *value, int flags, int min, int max); static void fmtint (char *buffer, size_t *currlen, size_t maxlen, long value, int base, int min, int max, int flags); static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c ); /* * dopr(): poor man's version of doprintf */ /* format read states */ #define DP_S_DEFAULT 0 #define DP_S_FLAGS 1 #define DP_S_MIN 2 #define DP_S_DOT 3 #define DP_S_MAX 4 #define DP_S_MOD 5 #define DP_S_CONV 6 #define DP_S_DONE 7 /* format flags - Bits */ #define DP_F_MINUS (1 << 0) #define DP_F_PLUS (1 << 1) #define DP_F_SPACE (1 << 2) #define DP_F_NUM (1 << 3) #define DP_F_ZERO (1 << 4) #define DP_F_UP (1 << 5) #define DP_F_UNSIGNED (1 << 6) /* Conversion Flags */ #define DP_C_SHORT 1 #define DP_C_LONG 2 #define char_to_int(p) (p - '0') #define chisdigit(ch) (((ch)>='0')&&((ch)<='9')) static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) { char ch; long value; char *strvalue; int min; int max; int state; int flags; int cflags; size_t currlen; state = DP_S_DEFAULT; currlen = flags = cflags = min = 0; max = -1; ch = *format++; while (state != DP_S_DONE) { if ((ch == '\0') || (currlen >= maxlen)) { state = DP_S_DONE; } switch(state) { case DP_S_DEFAULT: if (ch == '%') { state = DP_S_FLAGS; } else { dopr_outch (buffer, &currlen, maxlen, ch); } ch = *format++; break; case DP_S_FLAGS: switch (ch) { case '-': flags |= DP_F_MINUS; ch = *format++; break; case '+': flags |= DP_F_PLUS; ch = *format++; break; case ' ': flags |= DP_F_SPACE; ch = *format++; break; case '#': flags |= DP_F_NUM; ch = *format++; break; case '0': flags |= DP_F_ZERO; ch = *format++; break; default: state = DP_S_MIN; break; } break; case DP_S_MIN: if(chisdigit(ch)) { min = 10*min + char_to_int (ch); ch = *format++; } else if (ch == '*') { min = va_arg (args, int); ch = *format++; state = DP_S_DOT; } else { state = DP_S_DOT; } break; case DP_S_DOT: if (ch == '.') { state = DP_S_MAX; ch = *format++; } else { state = DP_S_MOD; } break; case DP_S_MAX: if (chisdigit((int) ch)) { if (max < 0) { max = 0; } max = 10*max + char_to_int (ch); ch = *format++; } else if(ch == '*') { max = va_arg (args, int); ch = *format++; state = DP_S_MOD; } else { state = DP_S_MOD; } break; case DP_S_MOD: /* Currently, we don't support Long Long, bummer */ switch (ch) { case 'h': cflags = DP_C_SHORT; ch = *format++; break; case 'l': cflags = DP_C_LONG; ch = *format++; break; default: break; } state = DP_S_CONV; break; case DP_S_CONV: switch (ch) { case 'd': case 'i': if (cflags == DP_C_SHORT) { #if ( defined(OTP_COMPILER) && OTP_COMPILER == TORNADO_2_2 ) value = va_arg (args, int); #else value = va_arg (args, int); #endif } else if (cflags == DP_C_LONG) { value = va_arg (args, long int); } else { value = va_arg (args, int); } fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); break; case 'o': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) { #if ( defined(OTP_COMPILER) && OTP_COMPILER == TORNADO_2_2 ) value = va_arg (args, int); #else value = va_arg (args, unsigned int); #endif } else if (cflags == DP_C_LONG) { value = va_arg (args, unsigned long int); } else { value = va_arg (args, unsigned int); } fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); break; case 'u': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) { #if ( defined(OTP_COMPILER) && OTP_COMPILER == TORNADO_2_2 ) value = va_arg (args, int); #else value = va_arg (args, unsigned int); #endif } else if (cflags == DP_C_LONG) { value = va_arg (args, unsigned long int); } else { value = va_arg (args, unsigned int); } fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); break; /*lint -save -e616 -e825*/ case 'X': flags |= DP_F_UP; case 'x': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) { #if ( defined(OTP_COMPILER) && OTP_COMPILER == TORNADO_2_2 ) value = va_arg (args, int); #else value = va_arg (args, unsigned int); #endif } else if (cflags == DP_C_LONG) { value = va_arg (args, unsigned long int); } else { value = va_arg (args, unsigned int); } fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); break; /*lint -restore*/ case 'c': dopr_outch (buffer, &currlen, maxlen,(char) va_arg (args, int)); break; case 's': strvalue = va_arg (args, char *); if (max < 0) { max = maxlen; /* ie, no max */ } fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); break; case 'p': strvalue = va_arg (args, void *); fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); break; case 'n': if (cflags == DP_C_SHORT) { short int *num; num = va_arg (args, short int *); *num = currlen; } else if (cflags == DP_C_LONG) { long int *num; num = va_arg (args, long int *); *num = currlen; } else { int *num; num = va_arg (args, int *); *num = currlen; } break; case '%': dopr_outch (buffer, &currlen, maxlen, ch); break; case 'w': /* not supported yet, treat as next char */ ch = *format++; break; default: /* Unknown, skip */ break; } ch = *format++; state = DP_S_DEFAULT; flags = cflags = min = 0; max = -1; break; case DP_S_DONE: break; default: /* hmm? */ break; /* some picky compilers need this */ } } if (currlen < maxlen - 1) { buffer[currlen] = '\0'; } else { buffer[maxlen - 1] = '\0'; } } static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, const char *value, int flags, int min, int max) { int padlen; /* amount to pad */ int cnt = 0; if (value == 0) value = ""; /*lint -save -e64*/ padlen = min - strlen(value); /*lint -restore*/ if (padlen < 0) padlen = 0; if (flags & DP_F_MINUS) padlen = -padlen; /* Left Justify */ while ((padlen > 0) && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, ' '); --padlen; ++cnt; } while (*value && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, *value++); ++cnt; } while ((padlen < 0) && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, ' '); ++padlen; ++cnt; } } /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ static void fmtint (char *buffer, size_t *currlen, size_t maxlen, long value, int base, int min, int max, int flags) { char signvalue = 0; unsigned long uvalue; char convert[20]; int place = 0; int spadlen = 0; /* amount to space pad */ int zpadlen = 0; /* amount to zero pad */ char *chars = ((flags & DP_F_UP) ? "0123456789ABCDEF" : "0123456789abcdef"); if (max < 0) max = 0; uvalue = value; if (!(flags & DP_F_UNSIGNED)) { if (value < 0) { signvalue = '-'; uvalue = -value; } else if (flags & DP_F_PLUS) { /* Do a sign (+/i) */ signvalue = '+'; } else if (flags & DP_F_SPACE) { signvalue = ' '; } } do { convert[place++] = chars[uvalue % (unsigned) base]; uvalue = (uvalue / (unsigned)base ); } while(uvalue && (place < 20)); if (place == 20) place--; convert[place] = 0; zpadlen = max - place; spadlen = (min - MAX (max, place)) - (signvalue ? 1 : 0); if (zpadlen < 0) zpadlen = 0; if (spadlen < 0) spadlen = 0; if (flags & DP_F_ZERO) { zpadlen = MAX(zpadlen, spadlen); spadlen = 0; } if (flags & DP_F_MINUS) spadlen = -spadlen; /* Left Justifty */ /* Spaces */ while (spadlen > 0) { dopr_outch (buffer, currlen, maxlen, ' '); --spadlen; } /* Sign */ if (signvalue) dopr_outch (buffer, currlen, maxlen, signvalue); /* Zeros */ if (zpadlen > 0) { while (zpadlen > 0) { dopr_outch (buffer, currlen, maxlen, '0'); --zpadlen; } } /* Digits */ while (place > 0) dopr_outch (buffer, currlen, maxlen, convert[--place]); /* Left Justified spaces */ while (spadlen < 0) { dopr_outch (buffer, currlen, maxlen, ' '); ++spadlen; } } static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c) { if (*currlen < maxlen) buffer[(*currlen)++] = c; } /* 王炯从snprintf.c拷贝过来 */ unsigned int otp_vsnprintf (char *str, size_t count, const char *fmt, va_list args) { if(count==0) { return 0; } str[0] = 0; dopr(str, count, fmt, args); /*lint -save -e64*/ return(strlen(str)); /*lint -restore*/ } /* 王炯从snprintf.c拷贝过来 向str中打印字符串,最多只打印count-1个字符。 如果打印了count-1个字符,则第count个字符为'\0'。 */ unsigned int otp_snprintf (char *str, unsigned int count, const char *fmt, ...) { int len; va_list ap; if(count==0 || !str ) { return 0; } va_start(ap, fmt); len = otp_vsnprintf(str, count, fmt, ap); va_end(ap); return len; } /* 把输入的字符串转换成小写。 该函数会转换str中的所有大写字母为小写,非大写字母保持不变。 遇到'\0'会结束转换,达到了缓冲区长度count也会结束转换 输入参数: str, 需要转换的字符串指针, count, str的缓冲区长度。 返回 str的值 */ char * otp_strtolower (char *str, int count) { int i=0; if( !str ) { return str; } while( i