ssprintf() family of functions for std::string + printf functionality Added: branches/xmlbuildsystem/reactos/tools/rbuild/ssprintf.cpp Added: branches/xmlbuildsystem/reactos/tools/rbuild/ssprintf.h _____
Added: branches/xmlbuildsystem/reactos/tools/rbuild/ssprintf.cpp --- branches/xmlbuildsystem/reactos/tools/rbuild/ssprintf.cpp 2005-01-04 18:24:21 UTC (rev 12793) +++ branches/xmlbuildsystem/reactos/tools/rbuild/ssprintf.cpp 2005-01-04 18:38:31 UTC (rev 12794) @@ -0,0 +1,1893 @@
+// ssprintf.cpp + +#include <malloc.h> +#include <math.h> +#include <float.h> +#include <assert.h> +#include "ssprintf.h" + +#ifdef _MSC_VER +#define alloca _alloca +#endif//_MSC_VER + +typedef __int64 LONGLONG; +typedef unsigned __int64 ULONGLONG; + +typedef struct { + unsigned int mantissa:23; + unsigned int exponent:8; + unsigned int sign:1; +} ieee_float_t; + +typedef struct { + unsigned int mantissal:32; + unsigned int mantissah:20; + unsigned int exponent:11; + unsigned int sign:1; +} ieee_double_t; + +typedef struct { + unsigned int mantissal:32; + unsigned int mantissah:32; + unsigned int exponent:15; + unsigned int sign:1; + unsigned int empty:16; +} ieee_long_double_t; + +std::string ssprintf ( const char* fmt, ... ) +{ + va_list arg; + va_start(arg, fmt); + std::string f = ssvprintf ( fmt, arg ); + va_end(arg); + return f; +} + +std::wstring sswprintf ( const wchar_t* fmt, ... ) +{ + va_list arg; + va_start(arg, fmt); + std::wstring f = sswvprintf ( fmt, arg ); + va_end(arg); + return f; +} + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ +#define ZEROTRUNC 128 /* truncate zero 's */ + + +static int skip_atoi(const char **s) +{ + int i=0; + + while (isdigit(**s)) + i = i*10 + *((*s)++) - '0'; + return i; +} + +static int skip_wtoi(const wchar_t **s) +{ + int i=0; + + while (iswdigit(**s)) + i = i*10 + *((*s)++) - L'0'; + return i; +} + + +static int do_div(LONGLONG *n,int base) +{ + int __res = ((ULONGLONG) *n) % (unsigned) base; + *n = ((ULONGLONG) *n) / (unsigned) base; + return __res; +} + + +static bool number(std::string& f, LONGLONG num, int base, int size, int precision ,int type) +{ + char c,sign,tmp[66]; + const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; + int i; + + if (type & LARGE) + digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return 0; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = '-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else while (num != 0) + tmp[i++] = digits[do_div(&num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + f += ' '; + if (sign) + f += sign; + if (type & SPECIAL) + { + if (base==8) + f += '0'; + else if (base==16) + { + f += '0'; + f += digits[33]; + } + } + if (!(type & LEFT)) + { + while (size-- > 0) + f += c; + } + while (i < precision--) + { + f += '0'; + } + while (i-- > 0) + { + f += tmp[i]; + } + while (size-- > 0) + { + f += ' '; + } + return true; +} + +static bool wnumber(std::wstring& f, LONGLONG num, int base, int size, int precision ,int type) +{ + wchar_t c,sign,tmp[66]; + const wchar_t *digits = L"0123456789abcdefghijklmnopqrstuvwxyz"; + int i; + + if (type & LARGE) + digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return 0; + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = L'-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = L'+'; + size--; + } else if (type & SPACE) { + sign = L' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]=L'0'; + else while (num != 0) + tmp[i++] = digits[do_div(&num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + f += L' '; + if (sign) + f += sign; + if (type & SPECIAL) + { + if (base==8) + f += L'0'; + else if (base==16) + { + f += L'0'; + f += digits[33]; + } + } + if (!(type & LEFT)) + { + while (size-- > 0) + f += c; + } + while (i < precision--) + { + f += L'0'; + } + while (i-- > 0) + { + f += tmp[i]; + } + while (size-- > 0) + { + f += L' '; + } + return true; +} + + +static bool numberf(std::string& f, double __n, char exp_sign, int size, int precision, int type) +{ + double exponent = 0.0; + double e; + long ie; + + //int x; + char *buf, *tmp; + int i = 0; + int j = 0; + //int k = 0; + + double frac, intr; + double p; + char sign; + char c; + char ro = 0; + int result; + + union + { + double* __n; + ieee_double_t* n; + } n; + + n.__n = &__n; + + if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) { + ie = ((unsigned int)n.n->exponent - (unsigned int)0x3ff); + exponent = ie/3.321928; + } + + if ( exp_sign == 'g' || exp_sign == 'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == 'e' || exp_sign == 'E' ) { + frac = modf(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + result = numberf(f,__n/pow(10.0L,e),'f',size-4, precision, type); + if (result < 0) + return false; + f += exp_sign; + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + result = number(f,ie, 10,2, 2,type ); + if (result < 0) + return false; + return true; + } + + if ( exp_sign == 'f' ) { + buf = (char*)alloca(4096); + if (type & LEFT) { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (__n < 0) { + sign = '-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + + frac = modf(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + + if ( precision > 0 ) { + //frac = modfl(__n,&intr); + i = precision-1; + while ( i >= 0 ) { + frac*=10.0L; + frac = modf(frac, &p); + buf[i] = (int)p + '0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) { + buf[i++] = '.'; + size--; + } + } + + if ( intr == 0.0 ) { + buf[i++] = '0'; + size--; + } + else { + while ( intr > 0.0 ) { + p = intr; + intr/=10.0L; + modf(intr, &intr); + + p -= 10.0*intr; + + buf[i++] = (int)p + '0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= '0' && buf[j] <= '8' ) { + buf[j]++; + ro = 0; + } + else if ( buf[j] == '9' ) { + buf[j] = '0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = '1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + { + while(size-->0) + f += ' '; + } + if (sign) + { + f += sign; + } + + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + { + f += ' '; + } + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + { + f += c; + } + + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) + { + j = 0; + while ( j < i && ( *tmp == '0' || *tmp == '.' )) + { + tmp++; + i--; + } + } +// else +// while (i < precision--) +// putc('0', f); + while (i-- > 0) + { + f += tmp[i]; + } + while (size-- > 0) + { + f += ' '; + } + } + return true; +} + +static bool wnumberf(std::wstring& f, double __n, wchar_t exp_sign, int size, int precision, int type) +{ + double exponent = 0.0; + double e; + long ie; + + int i = 0; + int j = 0; + + double frac, intr; + double p; + wchar_t *buf, *tmp, sign, c, ro = 0; + int result; + + union + { + double* __n; + ieee_double_t* n; + } n; + + n.__n = &__n; + + if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) { + ie = ((unsigned int)n.n->exponent - (unsigned int)0x3ff); + exponent = ie/3.321928; + } + + if ( exp_sign == L'g' || exp_sign == L'G' ) + { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == L'e' || exp_sign == L'E' ) + { + frac = modf(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + result = wnumberf(f,__n/pow(10.0L,e),L'f',size-4, precision, type); + if (result < 0) + return false; + f += exp_sign; + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + result = wnumber(f,ie, 10,2, 2,type ); + if (result < 0) + return false; + return true; + } + + if ( exp_sign == L'f' ) + { + buf = (wchar_t*)alloca(4096*sizeof(wchar_t)); + if (type & LEFT) + type &= ~ZEROPAD; + + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) + { + if (__n < 0) + { + sign = L'-'; + __n = fabs(__n); + size--; + } + else if (type & PLUS) + { + sign = L'+'; + size--; + } + else if (type & SPACE) + { + sign = L' '; + size--; + } + } + + frac = modf(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + + if ( precision > 0 ) { + //frac = modfl(__n,&intr); + i = precision-1; + while ( i >= 0 ) { + frac*=10.0L; + frac = modf(frac, &p); + buf[i] = (int)p + L'0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) { + buf[i++] = L'.'; + size--; + } + } + + if ( intr == 0.0 ) { + buf[i++] = L'0'; + size--; + } + else { + while ( intr > 0.0 ) { + p = intr; + intr/=10.0L; + modf(intr, &intr); + + p -= 10.0*intr; + + buf[i++] = (int)p + L'0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= L'0' && buf[j] <= L'8' ) { + buf[j]++; + ro = 0; + } + else if ( buf[j] == L'9' ) { + buf[j] = L'0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = L'1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + { + while(size-->0) + f += L' '; + } + if (sign) + { + f += sign; + } + + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + { + f += L' '; + } + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + { + f += c; + } + + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) + { + j = 0; + while ( j < i && ( *tmp == L'0' || *tmp == L'.' )) + { + tmp++; + i--; + } + } + while (i-- > 0) + { + f += tmp[i]; + } + while (size-- > 0) + { + f += L' '; + } + } + return true; +} + +static bool numberfl(std::string& f, long double __n, char exp_sign, int size, int precision, int type) +{ + long double exponent = 0.0; + long double e; + long ie; + + //int x; + char *buf, *tmp; + int i = 0; + int j = 0; + //int k = 0; + + long double frac, intr; + long double p; + char sign; + char c; + char ro = 0; + + int result; + + union + { + long double* __n; + ieee_long_double_t* n; + } n; + + n.__n = &__n; + + if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) { + ie = ((unsigned int)n.n->exponent - (unsigned int)0x3fff); + exponent = ie/3.321928; + } + + if ( exp_sign == 'g' || exp_sign == 'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == 'e' || exp_sign == 'E' ) { + frac = modfl(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + result = numberf(f,__n/powl(10.0L,e),'f',size-4, precision, type); + if (result < 0) + return false; + f += exp_sign; + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + result = number(f,ie, 10,2, 2,type ); + if (result < 0) + return false; + return true; + } + + if ( exp_sign == 'f' ) + { + + buf = (char*)alloca(4096); + if (type & LEFT) + { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) + { + if (__n < 0) + { + sign = '-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) + { + sign = '+'; + size--; + } else if (type & SPACE) + { + sign = ' '; + size--; + } + } + + frac = modfl(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + if ( precision > 0 ) + { + //frac = modfl(__n,&intr); + + i = precision-1; + while ( i >= 0 ) + { + frac*=10.0L; + frac = modfl((long double)frac, &p); + buf[i] = (int)p + '0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) + { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) + { + buf[i++] = '.'; + size--; + } + } + + if ( intr == 0.0 ) + { + buf[i++] = '0'; + size--; + } + else + { + while ( intr > 0.0 ) + { + p=intr; + intr/=10.0L; + modfl(intr, &intr); + + p -= 10.0L*intr; + + buf[i++] = (int)p + '0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= '0' && buf[j] <= '8' ) + { + buf[j]++; + ro = 0; + } + else if ( buf[j] == '9' ) + { + buf[j] = '0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = '1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + { + while(size-->0) + f += ' '; + } + if (sign) + { + f += sign; + } + + if (!(type&(ZEROPAD+LEFT))) + { + while(size-->0) + f += ' '; + } + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + { + f += c; + } + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) + { + j = 0; + while ( j < i && ( *tmp == '0' || *tmp == '.' )) + { + tmp++; + i--; + } + } + while (i-- > 0) + { + f += tmp[i]; + } + while (size-- > 0) + { + f += ' '; + } + } + return true; +} + +static bool wnumberfl(std::wstring& f, long double __n, wchar_t exp_sign, int size, int precision, int type) +{ + long double exponent = 0.0; + long double e; + long ie; + + wchar_t *buf, *tmp, sign, c, ro = 0; + int i = 0; + int j = 0; + + long double frac, intr; + long double p; + + int result; + + union + { + long double* __n; + ieee_long_double_t* n; + } n; + + n.__n = &__n; + + if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) { + ie = ((unsigned int)n.n->exponent - (unsigned int)0x3fff); + exponent = ie/3.321928; + } + + if ( exp_sign == L'g' || exp_sign == L'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == L'e' || exp_sign == L'E' ) { + frac = modfl(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + result = wnumberf(f,__n/powl(10.0L,e),L'f',size-4, precision, type); + if (result < 0) + return false; + f += exp_sign; + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + result = wnumber(f,ie, 10,2, 2,type ); + if (result < 0) + return false; + return true; + } + + if ( exp_sign == L'f' ) + { + + buf = (wchar_t*)alloca(4096*sizeof(wchar_t)); + if (type & LEFT) + { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) + { + if (__n < 0) + { + sign = L'-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) + { + sign = L'+'; + size--; + } else if (type & SPACE) + { + sign = L' '; + size--; + } + } + + frac = modfl(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + if ( precision > 0 ) + { + //frac = modfl(__n,&intr); + + i = precision-1; + while ( i >= 0 ) + { + frac*=10.0L; + frac = modfl((long double)frac, &p); + buf[i] = (int)p + L'0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) + { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) + { + buf[i++] = L'.'; + size--; + } + } + + if ( intr == 0.0 ) + { + buf[i++] = L'0'; + size--; + } + else + { + while ( intr > 0.0 ) + { + p=intr; + intr/=10.0L; + modfl(intr, &intr); + + p -= 10.0L*intr; + + buf[i++] = (int)p + L'0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= L'0' && buf[j] <= L'8' ) + { + buf[j]++; + ro = 0; + } + else if ( buf[j] == L'9' ) + { + buf[j] = L'0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = L'1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + { + while(size-->0) [truncated at 1000 lines; 926 more skipped]