📄 printf.c
字号:
//---------------------------------------------------------------------------------
// Copyright (c) Haisoft 2006-9-1
// Copyright jinhailiao 2008-2010
// E-mail: jinhailiao@163.com
// Project: HGui
// File: printf.c
// Description: a simple sprintf() and printf()...
//-------------------------------------------------------------
// Reversion Histroy:
//-------------------------------------------------------------
// Version date operations by who
// 1.0.0 2008-05-30 create Kingsea
//---------------------------------------------------------------------------------
#include "haitype.h"
#include "haiclib.h"
#ifdef HAVE_STDARG_H
#include "stdarg.h"
#else
typedef char * va_list;
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )
#endif
double hai_pow(double x, int y)
{
int i;
double num = 1.0;
if (y == 0)
return 1.0;
for (i = 0; i < y; i++)
num = num * x;
return num;
}
void hai_SplitDouble(double val, int precision, double *outd, double *outf)
{
int num, i, m, ival;
double fval, dval = 0.0, fdval;
if (val < 0) val = -val;
for (num=0,fval=val; fval>=1.0; num++,fval/=10.0);
for (i = 0; i < num; i++)
{
ival = (int)(fval*=10.0);
fval -= (double)ival;
dval = dval*10.0+ival;//累加整数值
}
fdval = val - dval;
for (m=0,fval=fdval; fval>0&&m<precision+1; m++)
{
ival = (int)(fval *= 10.0);
fval -= (double)ival;
}
if (m > precision)
{
fval = hai_pow(10, precision);
fval = 0.5/fval;
fdval += fval;
if (fdval >= 1.0)
{
fdval -= 1.0;
dval += 1.0;
}
}
*outd = dval;
*outf = fdval;
}
enum {SP_START, SP_FLAG, SP_WIDTH, SP_PRECI, SP_TYPE, SP_END};
#define SP_ALIGN_LEFT 1
#define SP_ALIGN_RIGHT 0
#define SP_SIGN_YES 1
#define SP_SIGN_NO 0
S_WORD hai_vsprintf(char *buf, const char *format, va_list argptr)
{
char ch;
char *p = buf;
char *pHex = "0123456789ABCDEF";//HexUp
char *HexLo = "0123456789abcdef";
char NumStr[256];
int i, val;
va_list va = argptr;
while (*format)
{
if (*format == '%')
{
char state = SP_START;
char prefix = 1;
char fill = ' ';
char NeedFill = 0;
char sign = SP_SIGN_NO;
char HexOct = 0;
char align = SP_ALIGN_RIGHT;
char *pstr;
int width = 0;
int precision = -1;
int ival = 0;
double fval = 0.0, dval = 0.0, fdval = 0.0;
unsigned int uval = 0;
format++;
while (ch=*format)
{
switch (state)
{
case SP_START:
if (ch=='-'||ch=='+'||ch==' '||ch=='0'||ch=='#')//flag
state = SP_FLAG;
else if (ch>='1' && ch<='9')
state = SP_WIDTH;
else if (ch == '.')
state = SP_PRECI, precision = 0, format++ /* skip the '.' */;
else if (ch=='c'||ch=='C'||ch=='d'||ch=='i'||ch=='o'||ch=='u'||ch=='x'||ch=='X'||ch=='e'||ch=='E'
||ch=='f'||ch=='g'||ch=='G'||ch=='n'||ch=='P'||ch=='s'||ch=='S')
state = SP_TYPE;
else
state = SP_END;
break;
case SP_FLAG:
format++;
if (ch=='-')
align = SP_ALIGN_LEFT;
else if (ch=='+')
sign = SP_SIGN_YES;
else if (ch==' '||ch=='0')
fill = ch, NeedFill = 1;
else if (ch=='#')
HexOct = 1;
else
state = SP_START, format-- /* back one char */;
break;
case SP_WIDTH:
if (ch>='0' && ch<='9')
format++, width = width*10 + (ch-'0');
else if (ch == '.')
state = SP_PRECI, precision = 0, format++ /* skip the '.' */;
else if (ch=='c'||ch=='C'||ch=='d'||ch=='i'||ch=='o'||ch=='u'||ch=='x'||ch=='X'||ch=='e'||ch=='E'
||ch=='f'||ch=='g'||ch=='G'||ch=='n'||ch=='P'||ch=='s'||ch=='S')
state = SP_TYPE;
else
state = SP_END;
break;
case SP_PRECI:
if (ch>='0' && ch<='9')
format++, precision = precision*10 + (ch-'0');
else if (ch=='c'||ch=='C'||ch=='d'||ch=='i'||ch=='o'||ch=='u'||ch=='x'||ch=='X'||ch=='e'||ch=='E'
||ch=='f'||ch=='g'||ch=='G'||ch=='n'||ch=='P'||ch=='s'||ch=='S')
state = SP_TYPE;
else
state = SP_END;
break;
case SP_TYPE:
switch (ch)
{
case 'c':
case 'C':
ival = va_arg(va, char);
if (align==SP_ALIGN_RIGHT)
while (width-- > 1) *p++ = fill;
*p++ = (char)ival;
if (align==SP_ALIGN_LEFT)
while (width-- > 1) *p++ = fill;
break;
case 'd':
case 'i':
ival = va_arg(va, int);
if (precision == -1) precision = 1;
for (i=0, val=ival<0? -ival:ival; val>0; i++, val = val/10)
NumStr[i] = val%10+'0';
for (; i < precision; i++)
NumStr[i] = '0';
// if (i==0) NumStr[i++] = '0';
val = i;
if (align==SP_ALIGN_LEFT)
{
if (ival<0 || sign==SP_SIGN_YES)
*p++ = ival<0? '-':'+';
else if (NeedFill==1 && fill==' ')
*p++ = fill;
else
prefix = 0; // set NO_PRE_FILL flag
for (i--; i >= 0; i--)
*p++ = NumStr[i];
for (width -= (prefix+val); width > 0; width--)
*p++ = ' ';
}
else
{
if (width <= val)
{
if (ival<0 || sign==SP_SIGN_YES)
*p++ = ival<0? '-':'+';
else if (NeedFill==1 && fill==' ')
*p++ = fill;
}
else
{
if (!(ival<0 || sign==SP_SIGN_YES))
prefix = 0;
if (fill==' ')
{
for (width -= (prefix+val); width > 0; width--)
*p++ = fill;
if (prefix) *p++ = ival<0? '-':'+';
}
else
{
if (prefix) *p++ = ival<0? '-':'+';
for (width -= (prefix+val); width > 0; width--)
*p++ = fill;
}
}
for (i--; i >= 0; i--)
*p++ = NumStr[i];
}
break;
case 'u':
uval = va_arg(va, unsigned int);
if (precision == -1) precision = 1;
for (i=0; uval>0; i++, uval = uval/10)
NumStr[i] = uval%10+'0';
for (; i < precision; i++)
NumStr[i] = '0';
// if (i==0) NumStr[i++] = '0';
val = i;
if (align==SP_ALIGN_LEFT)
{
for (i--; i >= 0; i--)
*p++ = NumStr[i];
for (width -= val; width > 0; width--)
*p++ = ' ';
}
else
{
for (width -= val; width > 0; width--)
*p++ = fill;
for (i--; i >= 0; i--)
*p++ = NumStr[i];
}
break;
case 'o':
uval = va_arg(va, unsigned int);
if (precision == -1) precision = 1;
for (i=0; uval>0; i++, uval = uval>>3)
NumStr[i] = (uval&0x7)+'0';
for (; i < precision; i++)
NumStr[i] = '0';
// if (i==0) NumStr[i++] = '0';
val = i;
if (align==SP_ALIGN_LEFT)
{
if (HexOct) *p++ = '0';
else prefix = 0;
for (i--; i >= 0; i--)
*p++ = NumStr[i];
for (width -= (prefix+val); width > 0; width--)
*p++ = ' ';
}
else
{
if (!HexOct) prefix = 0;
for (width -= (prefix+val); width > 0; width--)
*p++ = fill;
if (HexOct) *p++ = '0';
for (i--; i >= 0; i--)
*p++ = NumStr[i];
}
break;
case 'x':
pHex = HexLo; //default -> HexUp;
case 'X':
uval = va_arg(va, unsigned int);
if (precision == -1) precision = 1;
for (i=0; uval>0; i++, uval = uval>>4)
NumStr[i] = pHex[uval&0xF];
for (; i < precision; i++)
NumStr[i] = '0';
// if (i==0) NumStr[i++] = '0';
val = i;
if (align==SP_ALIGN_LEFT)
{
if (HexOct) *p++ = '0', *p++ = 'x', prefix = 2;
else prefix = 0;
for (i--; i >= 0; i--)
*p++ = NumStr[i];
for (width -= (prefix+val); width > 0; width--)
*p++ = ' ';
}
else
{
if (HexOct) prefix = 2;
else prefix = 0;
if (fill == ' ')
{
for (width -= (prefix+val); width > 0; width--)
*p++ = fill;
if (HexOct) *p++ = '0', *p++ = 'x';
}
else
{
if (HexOct) *p++ = '0', *p++ = 'x';
for (width -= (prefix+val); width > 0; width--)
*p++ = fill;
}
for (i--; i >= 0; i--)
*p++ = NumStr[i];
}
break;
case 's':
case 'S':
pstr = va_arg(va, char*);
if (!pstr) pstr = "<null>";
for (i = 0; pstr[i]; i++);
val = i;
if (align == SP_ALIGN_LEFT)
{
for (i = 0; i < val; i++)
*p++ = pstr[i];
for (width -= val; width > 0; width--)
*p++ = ' ';
}
else
{
for (width -= val; width > 0; width--)
*p++ = fill;
for (i = 0; i < val; i++)
*p++ = pstr[i];
}
break;
case 'f':
dval = va_arg(va, double);
if (precision == -1) precision = 6;
hai_SplitDouble(dval, precision, &fval, &fdval);
for (val=0; fval>=1.0; val++,fval/=10.0);
for (i = 0; i < val; i++)
{
ival = (int)(fval*=10.0);
NumStr[i] = (char)ival+'0';
fval -= (double)ival;
}
if (val==0) NumStr[val++] = '0';
if (align==SP_ALIGN_LEFT)
{
if (dval<0 || sign==SP_SIGN_YES)
*p++ = dval<0? '-':'+';
else if (NeedFill==1 && fill==' ')
*p++ = fill;
else
prefix = 0; // set NO_PRE_FILL flag
for (i = 0; i < val; i++)
*p++ = NumStr[i];
*p++ = '.';
for (i = 0; i < precision; i++)
{
ival = (int)(fdval *= 10.0);
*p++ = (char)ival + '0';
fdval -= (double)ival;
}
for (width -= (prefix+val+precision+1); width > 0; width--)//add 1 for the '.'
*p++ = ' ';
}
else
{
if (width <= (val+precision+1))
{
if (dval<0 || sign==SP_SIGN_YES)
*p++ = dval<0? '-':'+';
else if (NeedFill==1 && fill==' ')
*p++ = fill;
}
else
{
if (!(dval<0 || sign==SP_SIGN_YES))
prefix = 0;
if (fill==' ')
{
for (width -= (prefix+val+precision+1); width > 0; width--)
*p++ = fill;
if (prefix) *p++ = dval<0? '-':'+';
}
else
{
if (prefix) *p++ = dval<0? '-':'+';
for (width -= (prefix+val+precision+1); width > 0; width--)
*p++ = fill;
}
}
for (i = 0; i < val; i++)
*p++ = NumStr[i];
*p++ = '.';
for (i = 0; i < precision; i++)
{
ival = (int)(fdval *= 10.0);
*p++ = (char)ival + '0';
fdval -= (double)ival;
}
}
break;
case 'e':
case 'E':
case 'g':
case 'G':
case 'n':
case 'P'://unsupport now......
dval = va_arg(va, double);
break;
default:
break;
}
format++, state = SP_END;
break;
default:
break;
}
if (state == SP_END)
break;
}
}
#if 0
else if (*format == '\\') //process escape sequences
{
switch (*++format)
{
default : *p++ = *format++; break;
case 'a': *p++ = '\a'; format++; break; // Bell (alert)
case 'b': *p++ = '\b'; format++; break; // Backspace
case 'f': *p++ = '\f'; format++; break; // Formfeed
case 'n': *p++ = '\n'; format++; break; // New line
case 'r': *p++ = '\r'; format++; break; // Carriage return
case 't': *p++ = '\t'; format++; break; // Horizontal tab
case 'v': *p++ = '\v'; format++; break; // Vertical tab
// user default \' Single quotation mark
// user default \" Double quotation mark
// user default \\ Backslash
// user default \? Literal question mark
case '0': case '1': case '2': case '3':// \ooo ASCII character in octal notation
case '4': case '5': case '6': case '7':
for (val=*format-'0',ch=*++format,i=0; (ch>='0'&&ch<='7')&&(i<2); ch=*++format,i++)
val = val*8+(ch-'0');
*p++ = val;
break;
case 'x': // \xhhh ASCII character in hexadecimal notation
for (ch = *++format,val = 0,i = 0; i < 2; ch = *++format,i++)
if (ch>='0'&&ch<='9') val = val*16 + (ch-'0');
else if (ch>='a'&&ch<='f') val = val*16 + (ch-'a'+10);
else if (ch>='A'&&ch<='F') val = val*16 + (ch-'A'+10);
else break;
if (val == 0 && i == 0) val = 'x';
*p++ = val;
break;
}
}
#endif
else
{
*p++ = *format++;
}
}
va_end(va);
*p = '\0';
return (S_WORD)(p-buf);
}
S_VOID hai_PutChar(char ch)
{
//user add code for yourself purpose
void hai_UartPutChar(S_BYTE data);
hai_UartPutChar(ch);
}
S_WORD hai_sprintf(char *buf, const char *format, ...)
{
S_WORD num;
va_list va;
va_start(va, format);
num = hai_vsprintf(buf, format, va);
va_end(va);
return num;
}
S_WORD hai_printf(const char *format, ...)
{
S_WORD num;
va_list va;
char buf[1024], *p = buf;
hai_memset(buf, 0x00, sizeof(buf));
va_start(va, format);
num = hai_vsprintf(buf, format, va);
va_end(va);
while (*p)
hai_PutChar(*p++);
return num;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -