Author: amunger Date: Thu Jun 1 05:57:31 2006 New Revision: 22138
URL: http://svn.reactos.ru/svn/reactos?rev=22138&view=rev Log: Merged rtl fixes from trunk, per GreatLord. Revisions: 22081-22085
Modified: branches/ros-branch-0_3_0/reactos/lib/rtl/sprintf.c branches/ros-branch-0_3_0/reactos/lib/rtl/swprintf.c
Modified: branches/ros-branch-0_3_0/reactos/lib/rtl/sprintf.c URL: http://svn.reactos.ru/svn/reactos/branches/ros-branch-0_3_0/reactos/lib/rtl/... ============================================================================== --- branches/ros-branch-0_3_0/reactos/lib/rtl/sprintf.c (original) +++ branches/ros-branch-0_3_0/reactos/lib/rtl/sprintf.c Thu Jun 1 05:57:31 2006 @@ -26,6 +26,42 @@ #define LEFT 16 /* left justified */ #define SPECIAL 32 /* 0x */ #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ + +typedef struct { + unsigned int mantissal:32; + unsigned int mantissah:20; + unsigned int exponent:11; + unsigned int sign:1; +} double_t; + +static +__inline +int +_isinf(double __x) +{ + union + { + double* __x; + double_t* x; + } x; + + x.__x = &__x; + return ( x.x->exponent == 0x7ff && ( x.x->mantissah == 0 && x.x->mantissal == 0 )); +} + +static +__inline +int +_isnan(double __x) +{ + union + { + double* __x; + double_t* x; + } x; + x.__x = &__x; + return ( x.x->exponent == 0x7ff && ( x.x->mantissah != 0 || x.x->mantissal != 0 )); +}
static @@ -144,6 +180,109 @@ return buf; }
+static char * +numberf(char * buf, char * end, double num, int base, int size, int precision, int type) +{ + char c,sign,tmp[66]; + const char *digits; + const char *small_digits = "0123456789abcdefghijklmnopqrstuvwxyz"; + const char *large_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int i; + long long x; + + /* FIXME + the float version of number is direcly copy of number + */ + + digits = (type & LARGE) ? large_digits : small_digits; + 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) + { + x = num; + tmp[i++] = digits[do_div(&x,base)]; + num=x; + } + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) { + while(size-->0) { + if (buf <= end) + *buf = ' '; + ++buf; + } + } + if (sign) { + if (buf <= end) + *buf = sign; + ++buf; + } + if (type & SPECIAL) { + if (base==8) { + if (buf <= end) + *buf = '0'; + ++buf; + } else if (base==16) { + if (buf <= end) + *buf = '0'; + ++buf; + if (buf <= end) + *buf = digits[33]; + ++buf; + } + } + if (!(type & LEFT)) { + while (size-- > 0) { + if (buf <= end) + *buf = c; + ++buf; + } + } + while (i < precision--) { + if (buf <= end) + *buf = '0'; + ++buf; + } + while (i-- > 0) { + if (buf <= end) + *buf = tmp[i]; + ++buf; + } + while (size-- > 0) { + if (buf <= end) + *buf = ' '; + ++buf; + } + return buf; +} + static char* string(char* buf, char* end, const char* s, int len, int field_width, int precision, int flags) { @@ -241,6 +380,8 @@ { int len; unsigned long long num; + double _double; + int base; char *str, *end; const char *s; @@ -253,10 +394,12 @@ number of chars for from string */ int qualifier; /* 'h', 'l', 'L', 'I' or 'w' for integer fields */
+ /* clear the string buffer with zero so we do not need NULL terment it at end */ + str = buf; end = buf + cnt - 1; if (end < buf - 1) { - end = ((void *) -1); + end = ((char *) -1); cnt = end - buf + 1; }
@@ -439,6 +582,49 @@ *ip = (str - buf); } continue; + + /* float number formats - set up the flags and "break" */ + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + _double = (double)va_arg(args, double); + if ( _isnan(_double) ) { + s = "Nan"; + len = 3; + while ( len > 0 ) { + if (str <= end) + *str = *s++; + ++str; + len --; + } + } else if ( _isinf(_double) < 0 ) { + s = "-Inf"; + len = 4; + while ( len > 0 ) { + if (str <= end) + *str = *s++; + ++str; + len --; + } + } else if ( _isinf(_double) > 0 ) { + s = "+Inf"; + len = 4; + while ( len > 0 ) { + if (str <= end) + *str = *s++; + ++str; + len --; + } + } else { + if ( precision == -1 ) + precision = 6; + str = numberf(str, end, (int)_double, base, field_width, precision, flags); + } + + continue; +
/* integer number formats - set up the flags and "break" */ case 'o': @@ -501,8 +687,20 @@ if (str <= end) *str = '\0'; else if (cnt > 0) + { /* don't write out a null byte if the buf size is zero */ - *end = '\0'; + //*end = '\0'; + if (str-buf >cnt ) + { + *end = '\0'; + } + else + { + end++; + *end = '\0'; + } + + } return str-buf; }
Modified: branches/ros-branch-0_3_0/reactos/lib/rtl/swprintf.c URL: http://svn.reactos.ru/svn/reactos/branches/ros-branch-0_3_0/reactos/lib/rtl/... ============================================================================== --- branches/ros-branch-0_3_0/reactos/lib/rtl/swprintf.c (original) +++ branches/ros-branch-0_3_0/reactos/lib/rtl/swprintf.c Thu Jun 1 05:57:31 2006 @@ -26,6 +26,42 @@ #define LEFT 16 /* left justified */ #define SPECIAL 32 /* 0x */ #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ + +typedef struct { + unsigned int mantissal:32; + unsigned int mantissah:20; + unsigned int exponent:11; + unsigned int sign:1; +} double_t; + +static +__inline +int +_isinf(double __x) +{ + union + { + double* __x; + double_t* x; + } x; + + x.__x = &__x; + return ( x.x->exponent == 0x7ff && ( x.x->mantissah == 0 && x.x->mantissal == 0 )); +} + +static +__inline +int +_isnan(double __x) +{ + union + { + double* __x; + double_t* x; + } x; + x.__x = &__x; + return ( x.x->exponent == 0x7ff && ( x.x->mantissah != 0 || x.x->mantissal != 0 )); +}
static @@ -144,6 +180,110 @@ return buf; }
+static wchar_t * +numberf(wchar_t * buf, wchar_t * end, double num, int base, int size, int precision, int type) +{ + wchar_t c, sign, tmp[66]; + const wchar_t *digits; + const wchar_t *small_digits = L"0123456789abcdefghijklmnopqrstuvwxyz"; + const wchar_t *large_digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int i; + long long x; + + /* FIXME + the float version of number is direcly copy of number + */ + + + digits = (type & LARGE) ? large_digits : small_digits; + 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 = ' '; + 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) + { + x = num; + tmp[i++] = digits[do_div(&x,base)]; + num = x; + } + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) { + while(size-->0) { + if (buf <= end) + *buf = L' '; + ++buf; + } + } + if (sign) { + if (buf <= end) + *buf = sign; + ++buf; + } + if (type & SPECIAL) { + if (base==8) { + if (buf <= end) + *buf = L'0'; + ++buf; + } else if (base==16) { + if (buf <= end) + *buf = L'0'; + ++buf; + if (buf <= end) + *buf = digits[33]; + ++buf; + } + } + if (!(type & LEFT)) { + while (size-- > 0) { + if (buf <= end) + *buf = c; + ++buf; + } + } + while (i < precision--) { + if (buf <= end) + *buf = L'0'; + ++buf; + } + while (i-- > 0) { + if (buf <= end) + *buf = tmp[i]; + ++buf; + } + while (size-- > 0) { + if (buf <= end) + *buf = L' '; + ++buf; + } + return buf; +} + static wchar_t* string(wchar_t* buf, wchar_t* end, const char* s, int len, int field_width, int precision, int flags) { @@ -245,6 +385,8 @@ wchar_t * str, * end; const char *s; const wchar_t *sw; + const wchar_t *ss; + double _double;
int flags; /* flags to number() */
@@ -256,7 +398,7 @@ str = buf; end = buf + cnt - 1; if (end < buf - 1) { - end = ((void *) -1); + end = ((wchar_t *) -1); cnt = end - buf + 1; }
@@ -439,6 +581,50 @@ *ip = (str - buf); } continue; + /* float number formats - set up the flags and "break" */ + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + _double = (double)va_arg(args, double); + + if ( _isnan(_double) ) { + ss = L"Nan"; + len = 3; + while ( len > 0 ) { + if (str <= end) + *str = *ss++; + ++str; + len --; + } + } else if ( _isinf(_double) < 0 ) { + ss = L"-Inf"; + len = 4; + while ( len > 0 ) { + if (str <= end) + *str = *ss++; + ++str; + len --; + } + } else if ( _isinf(_double) > 0 ) { + ss = L"+Inf"; + len = 4; + while ( len > 0 ) { + if (str <= end) + *str = *ss++; + ++str; + len --; + } + } else { + if ( precision == -1 ) + precision = 6; + str = numberf(str, end, _double, base, field_width, precision, flags); + } + + continue; + +
/* integer number formats - set up the flags and "break" */ case L'o': @@ -500,9 +686,21 @@ } if (str <= end) *str = L'\0'; - else if (cnt > 0) + else if (cnt > 0) + { /* don't write out a null byte if the buf size is zero */ - *end = L'\0'; + //*end = '\0'; + if (str-buf >cnt ) + { + *end = L'\0'; + } + else + { + end++; + *end = L'\0'; + } + + } return str-buf; }