Clean-up number.cpp (dotnet/coreclr#18964)
authorPent Ploompuu <kaalikas@gmail.com>
Tue, 17 Jul 2018 21:59:00 +0000 (00:59 +0300)
committerJan Kotas <jkotas@microsoft.com>
Tue, 17 Jul 2018 21:59:00 +0000 (14:59 -0700)
Commit migrated from https://github.com/dotnet/coreclr/commit/4b618d9dfe1690c9df9e3c5ce351ae18d1a7c239

src/coreclr/src/classlibnative/bcltype/number.cpp
src/coreclr/src/classlibnative/bcltype/number.h

index b4bf7a5..b20044e 100644 (file)
@@ -8,88 +8,21 @@
 //
 
 #include "common.h"
-#include "excep.h"
 #include "number.h"
-#include "string.h"
 #include "bignum.h"
 #include "grisu3.h"
 #include "fp.h"
-#include <stdlib.h>
 
 typedef wchar_t wchar;
 
-#define INT32_PRECISION 10
-#define UINT32_PRECISION INT32_PRECISION
-#define INT64_PRECISION 19
-#define UINT64_PRECISION 20
-#define FLOAT_PRECISION 7
-#define DOUBLE_PRECISION 15
-#define LARGE_BUFFER_SIZE 600
-#define MIN_BUFFER_SIZE 105
-
 #define SCALE_NAN 0x80000000
 #define SCALE_INF 0x7FFFFFFF
 
-
-static const char* const posCurrencyFormats[] = {
-    "$#", "#$", "$ #", "# $"};
-
-static const char* const negCurrencyFormats[] = {
-    "($#)", "-$#", "$-#", "$#-",
-    "(#$)", "-#$", "#-$", "#$-",
-    "-# $", "-$ #", "# $-", "$ #-",
-    "$ -#", "#- $", "($ #)", "(# $)"};
-
-static const char* const posPercentFormats[] = {
-    "# %", "#%", "%#", "% #"                // Last one is new in Whidbey
-};
-
-static const char* const negPercentFormats[] = {
-    "-# %", "-#%", "-%#",
-    "%-#", "%#-",                        // Last 9 are new in WHidbey
-    "#-%", "#%-",
-    "-% #", "# %-", "% #-",
-    "% -#", "#- %"
-};
-
-static const char* const negNumberFormats[] = {
-    "(#)", "-#", "- #", "#-", "# -",
-};
-
-static const char posNumberFormat[] = "#";
-
 #if defined(_TARGET_X86_) && !defined(FEATURE_PAL)
 
 extern "C" void _cdecl /*__stdcall*/ DoubleToNumber(double value, int precision, NUMBER* number);
 extern "C" void _cdecl /*__stdcall*/ NumberToDouble(NUMBER* number, double* value);
 
-#pragma warning(disable:4035)
-
-wchar_t* COMNumber::Int32ToDecChars(__in wchar_t* p, unsigned int value, int digits)
-{
-    LIMITED_METHOD_CONTRACT
-
-    _asm {
-        mov     eax,value
-        mov     ebx,10
-        mov     ecx,digits
-        mov     edi,p
-        jmp     L2
-L1:             xor     edx,edx
-        div     ebx
-        add     edx,'0'          //promote dl to edx to avoid partial register stall and LCP stall  
-        sub     edi,2
-        mov     [edi],dx
-L2:             dec     ecx
-        jge     L1
-        or      eax,eax
-        jne     L1
-        mov     eax,edi
-    }
-}
-
-#pragma warning(default:4035)
-
 #else // _TARGET_X86_ && !FEATURE_PAL
 
 void Dragon4( double value, int count, int* dec, int* sign, wchar_t* digits )
@@ -807,1170 +740,8 @@ done:
     if (number->sign) *(UINT64*)value |= I64(0x8000000000000000);
 }
 
-wchar_t* COMNumber::Int32ToDecChars(__in wchar_t* p, unsigned int value, int digits)
-{
-    LIMITED_METHOD_CONTRACT
-    _ASSERTE(p != NULL);
-
-    while (--digits >= 0 || value != 0) {
-        *--p = value % 10 + '0';
-        value /= 10;
-    }
-    return p;
-}
 #endif // _TARGET_X86_ && !FEATURE_PAL
 
-#if defined(_MSC_VER) && defined(_TARGET_X86_)
-#pragma optimize("y", on)              // Small critical routines, don't put in EBP frame 
-#endif
-
-inline void AddStringRef(__in wchar** ppBuffer, STRINGREF strRef)
-{
-    WRAPPER_NO_CONTRACT
-    _ASSERTE(ppBuffer != NULL && strRef != NULL);
-
-    wchar* buffer = strRef->GetBuffer();
-    _ASSERTE(buffer != NULL);
-    DWORD length = strRef->GetStringLength();
-    for (wchar* str = buffer; str < buffer + length; (*ppBuffer)++, str++)
-    {
-        **ppBuffer = *str;
-    }
-}
-
-inline wchar* GetDigitsBuffer(NUMBER* number)
-{
-    return (number->allDigits != NULL) ? number->allDigits : number->digits;
-}
-
-#if defined(_MSC_VER) && defined(_TARGET_X86_)
-#pragma optimize("", on)               // Go back to command line default optimizations
-#endif
-
-
-void RoundNumber(NUMBER* number, int pos)
-{
-    LIMITED_METHOD_CONTRACT
-    _ASSERTE(number != NULL);
-
-    wchar_t* digits = GetDigitsBuffer(number);
-    int i = 0;
-    while (i < pos && digits[i] != 0) i++;
-    if (i == pos && digits[i] >= '5') {
-        while (i > 0 && digits[i - 1] == '9') i--;
-        if (i > 0) {
-            digits[i - 1]++;
-        }
-        else {
-            number->scale++;
-            digits[0] = '1';
-            i = 1;
-        }
-    }
-    else {
-        while (i > 0 && digits[i - 1] == '0') i--;
-    }
-    if (i == 0) {
-        number->scale = 0;
-        number->sign = 0;
-    }
-    digits[i] = 0;
-
-}
-
-#if defined(_MSC_VER) && defined(_TARGET_X86_)
-#pragma optimize("y", on)              // Small critical routines, don't put in EBP frame 
-#endif
-
-wchar ParseFormatSpecifier(STRINGREF str, int* digits)
-{
-    WRAPPER_NO_CONTRACT
-    _ASSERTE(digits != NULL);
-
-    if (str != 0) {
-        wchar* p = str->GetBuffer();
-        _ASSERTE(p != NULL);
-        wchar ch = *p;
-        if (ch != 0) {
-            if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
-                p++;
-                int n = -1;
-                if (*p >= '0' && *p <= '9') {
-                    n = *p++ - '0';
-                    while (*p >= '0' && *p <= '9') {
-                        n = n * 10 + *p++ - '0';
-                        if (n >= 10) break;
-                    }
-                }
-                if (*p == 0) {
-                    *digits = n;
-                    return ch;
-                }
-            }
-            return 0;
-        }
-    }
-    *digits = -1;
-    return 'G';
-}
-
-wchar* FormatExponent(__in wchar* buffer, int value, wchar expChar,
-    STRINGREF posSignStr, STRINGREF negSignStr, int minDigits)
-{
-    WRAPPER_NO_CONTRACT
-    _ASSERTE(buffer != NULL);
-
-    wchar digits[11];
-    *buffer++ = expChar;
-    if (value < 0) {
-        _ASSERTE(negSignStr != NULL);
-        AddStringRef(&buffer, negSignStr);
-        value = -value;
-    }
-    else {
-        if (posSignStr!= NULL) {
-            AddStringRef(&buffer, posSignStr);
-        }
-    }
-    wchar* p = COMNumber::Int32ToDecChars(digits + 10, value, minDigits);
-    _ASSERTE(p != NULL);
-    int i = (int) (digits + 10 - p);
-    while (--i >= 0) *buffer++ = *p++;
-    return buffer;
-}
-
-#if defined(_MSC_VER) && defined(_TARGET_X86_)
-#pragma optimize("", on)               // Go back to command line default optimizations
-#endif
-
-wchar* FormatGeneral(__in_ecount(cchBuffer) wchar* buffer, SIZE_T cchBuffer, NUMBER* number, int nMinDigits, int nMaxDigits, wchar expChar,
-    STRINGREF sNumberDecimal, STRINGREF sPositive, STRINGREF sNegative, STRINGREF sZero, BOOL bSuppressScientific = FALSE)
-{
-        WRAPPER_NO_CONTRACT
-        _ASSERTE(number != NULL);
-        _ASSERTE(buffer != NULL);
-
-    int digPos = number->scale;
-    int scientific = 0;
-    if (!bSuppressScientific) { // Don't switch to scientific notation
-        if (digPos > nMaxDigits || digPos < -3) {
-            digPos = 1;
-            scientific = 1;
-        }
-    }
-
-    wchar* dig = GetDigitsBuffer(number);
-    _ASSERT(dig != NULL);
-    if (digPos > 0) {
-        do {
-            *buffer++ = *dig != 0? *dig++: '0';
-        } while (--digPos > 0);
-    }
-    else {
-        *buffer++ = '0';
-    }
-    if (*dig != 0 || digPos < 0) {
-        AddStringRef(&buffer, sNumberDecimal);
-        while (digPos < 0) {
-            *buffer++ = '0';
-            digPos++;
-        }
-        while (*dig != 0) {
-            *buffer++ = *dig++;
-        }
-    }
-    if (scientific) buffer = FormatExponent(buffer, number->scale - 1, expChar, sPositive, sNegative, 2);
-    return buffer;
-}
-
-wchar* FormatScientific(__in_ecount(cchBuffer) wchar* buffer, SIZE_T cchBuffer, NUMBER* number, int nMinDigits, int nMaxDigits, wchar expChar,
-    STRINGREF sNumberDecimal, STRINGREF sPositive, STRINGREF sNegative, STRINGREF sZero)
-{
-    WRAPPER_NO_CONTRACT
-    _ASSERTE(number != NULL);
-    _ASSERTE(buffer != NULL);
-
-    wchar* dig = GetDigitsBuffer(number);
-    _ASSERTE(dig != NULL);
-    *buffer++ = *dig != 0? *dig++: '0';
-    if (nMaxDigits != 1) // For E0 we would like to suppress the decimal point
-        AddStringRef(&buffer, sNumberDecimal);
-    while (--nMaxDigits > 0) *buffer++ = *dig != 0? *dig++: '0';
-    int e = (GetDigitsBuffer(number))[0] == 0 ? 0 : number->scale - 1;
-    buffer = FormatExponent(buffer, e, expChar, sPositive, sNegative, 3);
-    _ASSERTE(buffer != NULL);
-    return buffer;
-}
-
-wchar* FormatFixed(__in_ecount(cchBuffer) wchar* buffer, SIZE_T cchBuffer, NUMBER* number, int nMinDigits, int nMaxDigits,
-    I4ARRAYREF groupDigitsRef, STRINGREF sDecimal, STRINGREF sGroup, STRINGREF sNegative,STRINGREF sZero)
-{
-    CONTRACTL {
-        THROWS;
-        INJECT_FAULT(COMPlusThrowOM());
-        GC_TRIGGERS;
-        MODE_COOPERATIVE;
-        PRECONDITION(CheckPointer(buffer));
-        PRECONDITION(CheckPointer(number));
-    } CONTRACTL_END;
-
-    int digPos = number->scale;
-    wchar* dig = GetDigitsBuffer(number);
-    const I4* groupDigits = NULL;
-    if (groupDigitsRef != NULL) {
-        groupDigits = groupDigitsRef->GetDirectConstPointerToNonObjectElements();
-    }
-
-    if (digPos > 0) {
-        if (groupDigits != NULL) {
-
-            int groupSizeIndex = 0;     // index into the groupDigits array.
-            int groupSizeCount = groupDigits[groupSizeIndex];   // the current total of group size.
-            int groupSizeLen   = groupDigitsRef->GetNumComponents();    // the length of groupDigits array.
-            int bufferSize     = digPos;                        // the length of the result buffer string.
-            int groupSeparatorLen = sGroup->GetStringLength();  // the length of the group separator string.
-            int groupSize = 0;                                      // the current group size.
-
-            //
-            // Find out the size of the string buffer for the result.
-            //
-            if (groupSizeLen != 0) // You can pass in 0 length arrays
-            {
-                while (digPos > groupSizeCount) {
-                    groupSize = groupDigits[groupSizeIndex];
-                    if (groupSize == 0) {
-                        break;
-                    }
-
-                    bufferSize += groupSeparatorLen;
-                    if (groupSizeIndex < groupSizeLen - 1) {
-                        groupSizeIndex++;
-                    }
-                    groupSizeCount += groupDigits[groupSizeIndex];
-                    if (groupSizeCount < 0 || bufferSize < 0) {
-                        COMPlusThrow(kArgumentOutOfRangeException); // if we overflow
-                    }
-                }
-                if (groupSizeCount == 0) // If you passed in an array with one entry as 0, groupSizeCount == 0
-                    groupSize = 0;
-                else
-                    groupSize = groupDigits[0];
-            }
-
-            groupSizeIndex = 0;
-            int digitCount = 0;
-            int digStart;
-            int digLength = (int)wcslen(dig);
-            digStart = (digPos<digLength)?digPos:digLength;
-            wchar* p = buffer + bufferSize - 1;
-            for (int i = digPos - 1; i >=0; i--) {
-                *(p--) = (i<digStart)?dig[i]:'0';
-
-                if (groupSize > 0) {
-                    digitCount++;
-                    if (digitCount == groupSize && i != 0) {
-                        for (int j = groupSeparatorLen - 1; j >=0; j--) {
-                            *(p--) = sGroup->GetBuffer()[j];
-                        }
-
-                        if (groupSizeIndex < groupSizeLen - 1) {
-                            groupSizeIndex++;
-                            groupSize = groupDigits[groupSizeIndex];
-                        }
-                        digitCount = 0;
-                    }
-                }
-            }
-            if (p < buffer - 1) {
-                // This indicates a buffer underflow since we write in backwards. 
-                DoJITFailFast();
-            }
-            buffer += bufferSize;
-            dig += digStart;
-        } else {
-            do {
-                *buffer++ = *dig != 0? *dig++: '0';
-            } while (--digPos > 0);
-        }
-    }
-    else {
-        *buffer++ = '0';
-    }
-    if (nMaxDigits > 0) {
-        AddStringRef(&buffer, sDecimal);
-        while (digPos < 0 && nMaxDigits > 0) {
-            *buffer++ = '0';
-            digPos++;
-            nMaxDigits--;
-        }
-        while (nMaxDigits > 0) {
-            *buffer++ = *dig != 0? *dig++: '0';
-            nMaxDigits--;
-        }
-    }
-    return buffer;
-}
-
-wchar* FormatNumber(__in_ecount(cchBuffer) wchar* buffer, SIZE_T cchBuffer, NUMBER* number, int nMinDigits, int nMaxDigits, int cNegativeNumberFormat, I4ARRAYREF cNumberGroup, STRINGREF sNumberDecimal, STRINGREF sNumberGroup, STRINGREF sNegative, STRINGREF sZero)
-{
-    CONTRACTL {
-        MODE_COOPERATIVE;
-        THROWS;
-        GC_TRIGGERS;
-        PRECONDITION(CheckPointer(buffer));
-        PRECONDITION(CheckPointer(number));
-    } CONTRACTL_END;
-
-    char ch;
-    const char* fmt;
-    fmt = number->sign?
-          negNumberFormats[cNegativeNumberFormat]:
-          posNumberFormat;
-
-    while ((ch = *fmt++) != 0) {
-        switch (ch) {
-        case '#':
-            buffer = FormatFixed(buffer, cchBuffer, number, nMinDigits,nMaxDigits,
-                cNumberGroup,
-                sNumberDecimal, sNumberGroup,sNegative,sZero);
-            break;
-        case '-':
-            AddStringRef(&buffer, sNegative);
-            break;
-        default:
-            *buffer++ = ch;
-        }
-    }
-    return buffer;
-
-}
-
-wchar* FormatCurrency(__in_ecount(cchBuffer) wchar* buffer, SIZE_T cchBuffer, NUMBER* number, int nMinDigits,int nMaxDigits, int cNegCurrencyFormat, int cPosCurrencyFormat, I4ARRAYREF cCurrencyGroup, 
-                      STRINGREF sCurrencyDecimal, STRINGREF sCurrencyGroup, STRINGREF sNegative, STRINGREF sCurrency,STRINGREF sZero)
-{
-    CONTRACTL {
-        MODE_COOPERATIVE;
-        THROWS;
-        GC_TRIGGERS;
-        PRECONDITION(CheckPointer(buffer));
-        PRECONDITION(CheckPointer(number));
-    } CONTRACTL_END;
-
-    char ch;
-    const char* fmt;
-    fmt = number->sign?
-          negCurrencyFormats[cNegCurrencyFormat]:
-          posCurrencyFormats[cPosCurrencyFormat];
-
-    while ((ch = *fmt++) != 0) {
-        switch (ch) {
-        case '#':
-            buffer = FormatFixed(buffer, cchBuffer, number, nMinDigits,nMaxDigits,
-                cCurrencyGroup,
-                sCurrencyDecimal, sCurrencyGroup,sNegative,sZero);
-            break;
-        case '-':
-            AddStringRef(&buffer, sNegative);
-            break;
-        case '$':
-            AddStringRef(&buffer, sCurrency);
-            break;
-        default:
-            *buffer++ = ch;
-        }
-    }
-    return buffer;
-}
-
-wchar* FormatPercent(__in_ecount(cchBuffer) wchar* buffer, SIZE_T cchBuffer, NUMBER* number, int nMinDigits, int nMaxDigits, int cNegativePercentFormat, int cPositivePercentFormat, I4ARRAYREF cPercentGroup, 
-                     STRINGREF sPercentDecimal, STRINGREF sPercentGroup, STRINGREF sNegative, STRINGREF sPercent, STRINGREF sZero)
-{
-    CONTRACTL {
-        MODE_COOPERATIVE;
-        THROWS;
-        GC_TRIGGERS;
-        PRECONDITION(CheckPointer(buffer));
-        PRECONDITION(CheckPointer(number));
-    } CONTRACTL_END;
-
-    char ch;
-    const char* fmt;
-    fmt = number->sign?
-          negPercentFormats[cNegativePercentFormat]:
-          posPercentFormats[cPositivePercentFormat];
-
-    while ((ch = *fmt++) != 0) {
-        switch (ch) {
-        case '#':
-            buffer = FormatFixed(buffer, cchBuffer, number, nMinDigits,nMaxDigits,
-                cPercentGroup,
-                sPercentDecimal, sPercentGroup,sNegative,sZero);
-            break;
-        case '-':
-            AddStringRef(&buffer, sNegative);
-            break;
-        case '%':
-            AddStringRef(&buffer, sPercent);
-            break;
-        default:
-            *buffer++ = ch;
-        }
-    }
-    return buffer;
-}
-
-STRINGREF NumberToString(NUMBER* number, wchar format, int nMaxDigits, NUMFMTREF numfmt, BOOL bDecimal = FALSE )
-{
-    CONTRACTL {
-        THROWS;
-        INJECT_FAULT(COMPlusThrowOM());
-        GC_TRIGGERS;
-        MODE_COOPERATIVE;
-        PRECONDITION(CheckPointer(number));
-    } CONTRACTL_END;
-
-    int nMinDigits=-1;
-    STRINGREF sZero=NULL;
-
-    // @TODO what if not sequential?
-
-    // Do the worst case calculation
-    /* US English - for Double.MinValue.ToString("C99"); we require 514 characters
-    ----------
-    2 paranthesis
-    1 currency character
-    308 characters
-    103 group seperators
-    1 decimal separator
-    99 0's
-
-        digPos + 99 + 6(slack) => digPos + 105
-        C
-        sNegative
-        sCurrencyGroup
-        sCurrencyDecimal
-        sCurrency
-        F
-        sNegative
-        sNumberDecimal
-        N
-        sNegative
-        sNumberDecimal
-        sNumberGroup
-        E
-        sNegative
-        sPositive
-        sNegative (for exponent)
-        sPositive
-        sNumberDecimal
-        G
-        sNegative
-        sPositive
-        sNegative (for exponent)
-        sPositive
-        sNumberDecimal
-        P (+2 for some spaces)
-        sNegative
-        sPercentGroup
-        sPercentDecimal
-        sPercent
-    */
-
-    _ASSERTE(numfmt != NULL);
-    _ASSERTE(!bDecimal);
-    UINT64 newBufferLen = MIN_BUFFER_SIZE;
-
-    CQuickBytesSpecifySize<LARGE_BUFFER_SIZE * sizeof(WCHAR)> buf;
-
-    wchar *buffer = NULL;
-    wchar* dst = NULL;
-    wchar ftype = format & 0xFFDF;
-    int digCount = 0;
-
-    switch (ftype) {
-    case 'C':
-        {
-        nMinDigits = nMaxDigits >= 0 ? nMaxDigits : numfmt->cCurrencyDecimals;
-
-        if (nMaxDigits< 0) 
-            nMaxDigits = numfmt->cCurrencyDecimals;
-        if (number->scale < 0)
-            digCount = 0;
-        else if (!ClrSafeInt<INT32>::addition(number->scale, nMaxDigits, digCount))
-            COMPlusThrowOM();
-
-        // It is critical to format with the same values that we use to calculate buffer size.
-        int cNegCurrencyFormat = numfmt->cNegCurrencyFormat;
-        int cPosCurrencyFormat = numfmt->cPosCurrencyFormat;
-        I4ARRAYREF cCurrencyGroup = numfmt->cCurrencyGroup;
-        STRINGREF sCurrencyDecimal = numfmt->sCurrencyDecimal;
-        STRINGREF sCurrencyGroup = numfmt->sCurrencyGroup;
-        STRINGREF sNegative = numfmt->sNegative;
-        STRINGREF sCurrency = numfmt->sCurrency;        
-        // Prefix: bogus warning 22011: newBufferLen+=digCount may be smaller than MIN_BUFFER_SIZE
-        PREFIX_ASSUME(digCount >=0 && digCount <= INT32_MAX);
-        newBufferLen += digCount;
-        newBufferLen += sNegative->GetStringLength(); // For number and exponent
-        if (!ClrSafeInt<UINT64>::addition((UINT64)sCurrencyGroup->GetStringLength() * digCount, newBufferLen, newBufferLen))
-            COMPlusThrowOM();
-        newBufferLen += sCurrencyDecimal->GetStringLength();
-        newBufferLen += sCurrency->GetStringLength();
-
-        _ASSERTE(newBufferLen >= MIN_BUFFER_SIZE);
-        if (newBufferLen > INT32_MAX) {
-            COMPlusThrowOM();
-        }
-        newBufferLen = newBufferLen * sizeof(WCHAR);
-        dst = buffer = (WCHAR*)buf.AllocThrows(static_cast<SIZE_T>(newBufferLen));
-
-            RoundNumber(number, number->scale + nMaxDigits); // Don't change this line to use digPos since digCount could have its sign changed.
-            dst = FormatCurrency(dst, static_cast<SIZE_T>(newBufferLen/sizeof(WCHAR)), number, nMinDigits,nMaxDigits, cNegCurrencyFormat, cPosCurrencyFormat, cCurrencyGroup, sCurrencyDecimal, sCurrencyGroup, sNegative, sCurrency,sZero);
-            
-            break;
-        }
-    case 'F':
-        {
-        if (nMaxDigits< 0) 
-            // This ensures that the PAL code pads out to the correct place even when we use the default precision
-            nMaxDigits = nMinDigits = numfmt->cNumberDecimals;
-        else
-            nMinDigits=nMaxDigits;
-
-        if (number->scale < 0)
-            digCount = 0;
-        else
-            digCount = number->scale + nMaxDigits;
-
-
-        // It is critical to format with the same values that we use to calculate buffer size.
-        STRINGREF sNumberDecimal = numfmt->sNumberDecimal;
-        STRINGREF sNegative = numfmt->sNegative;
-           
-        newBufferLen += digCount;
-        newBufferLen += sNegative->GetStringLength(); // For number and exponent
-        newBufferLen += sNumberDecimal->GetStringLength();
-
-        _ASSERTE(newBufferLen >= MIN_BUFFER_SIZE);
-        if (newBufferLen > INT32_MAX) {
-            COMPlusThrowOM();
-        }
-        newBufferLen = newBufferLen * sizeof(WCHAR);
-        dst = buffer = (WCHAR*)buf.AllocThrows(static_cast<SIZE_T>(newBufferLen));
-
-        RoundNumber(number, number->scale + nMaxDigits);
-        if (number->sign) {
-            AddStringRef(&dst, sNegative);
-        }
-            dst = FormatFixed(dst, static_cast<SIZE_T>(newBufferLen/sizeof(WCHAR)-(dst-buffer)), number, nMinDigits,nMaxDigits,
-                NULL,
-                sNumberDecimal, NULL, sNegative, sZero);
-        
-        break;
-        }
-    case 'N':
-        {
-        if (nMaxDigits < 0) 
-            // This ensures that the PAL code pads out to the correct place even when we use the default precision
-            nMaxDigits = nMinDigits = numfmt->cNumberDecimals; // Since we are using digits in our calculation
-        else
-            nMinDigits=nMaxDigits;
-
-        if (number->scale < 0)
-            digCount = 0;
-        else
-            digCount = number->scale + nMaxDigits;
-
-        // It is critical to format with the same values that we use to calculate buffer size.
-        I4ARRAYREF cNumberGroup = numfmt->cNumberGroup;
-        STRINGREF sNegative = numfmt->sNegative;
-        STRINGREF sNumberDecimal = numfmt->sNumberDecimal;
-        STRINGREF sNumberGroup = numfmt->sNumberGroup;
-        int cNegativeNumberFormat = numfmt->cNegativeNumberFormat;
-        newBufferLen += digCount;
-        newBufferLen += sNegative->GetStringLength(); // For number and exponent
-        if (!ClrSafeInt<UINT64>::addition((UINT64)sNumberGroup->GetStringLength() * digCount, newBufferLen, newBufferLen))
-            COMPlusThrowOM();
-        newBufferLen += sNumberDecimal->GetStringLength();
-
-        _ASSERTE(newBufferLen >= MIN_BUFFER_SIZE);
-        if (newBufferLen > INT32_MAX) {
-            COMPlusThrowOM();
-        }
-        newBufferLen = newBufferLen * sizeof(WCHAR);
-        dst = buffer = (WCHAR*)buf.AllocThrows(static_cast<SIZE_T>(newBufferLen));
-
-        RoundNumber(number, number->scale + nMaxDigits);
-        dst = FormatNumber(dst, static_cast<SIZE_T>(newBufferLen/sizeof(WCHAR)),number, nMinDigits, nMaxDigits, cNegativeNumberFormat, cNumberGroup, sNumberDecimal, sNumberGroup, sNegative, sZero);
-        
-        break;
-        }
-    case 'E':
-        {
-        // It is critical to format with the same values that we use to calculate buffer size.
-        STRINGREF sNumberDecimal = numfmt->sNumberDecimal;
-        STRINGREF sNegative = numfmt->sNegative;
-        STRINGREF sPositive = numfmt->sPositive;
-
-        if (nMaxDigits < 0) 
-            // This ensures that the PAL code pads out to the correct place even when we use the default precision
-            nMaxDigits = nMinDigits = 6;
-        else
-            nMinDigits=nMaxDigits;
-        nMaxDigits++;
-
-        newBufferLen += nMaxDigits;
-        newBufferLen += (((INT64)sNegative->GetStringLength() + sPositive->GetStringLength()) *2); // For number and exponent
-        newBufferLen += sNumberDecimal->GetStringLength();
-
-        _ASSERTE(newBufferLen >= MIN_BUFFER_SIZE);
-        if (newBufferLen > INT32_MAX) {
-            COMPlusThrowOM();
-        }
-        newBufferLen = newBufferLen * sizeof(WCHAR);
-        dst = buffer = (WCHAR*)buf.AllocThrows(static_cast<SIZE_T>(newBufferLen));
-
-        RoundNumber(number, nMaxDigits);
-        if (number->sign) {
-            AddStringRef(&dst, sNegative);
-        }
-        dst = FormatScientific(dst, static_cast<SIZE_T>(newBufferLen * sizeof(WCHAR)-(dst-buffer)),number, nMinDigits,nMaxDigits, format, sNumberDecimal, sPositive, sNegative,sZero);
-
-        break;
-        }
-    case 'G':
-        {
-            bool enableRounding = true;
-            if (nMaxDigits < 1) {
-                // This ensures that the PAL code pads out to the correct place even when we use the default precision
-                nMaxDigits = nMinDigits = number->precision;
-            }
-            else
-                nMinDigits=nMaxDigits;
-
-        // It is critical to format with the same values that we use to calculate buffer size.
-        STRINGREF sNumberDecimal = numfmt->sNumberDecimal;
-        STRINGREF sNegative = numfmt->sNegative;
-        STRINGREF sPositive = numfmt->sPositive;
-        newBufferLen += nMaxDigits;
-        newBufferLen += (((INT64)sNegative->GetStringLength() + sPositive->GetStringLength()) *2); // For number and exponent
-        newBufferLen += sNumberDecimal->GetStringLength();
-
-        _ASSERTE(newBufferLen >= MIN_BUFFER_SIZE);
-        if (newBufferLen > INT32_MAX) {
-            COMPlusThrowOM();
-        }
-        newBufferLen = newBufferLen * sizeof(WCHAR);
-        dst = buffer = (WCHAR*)buf.AllocThrows(static_cast<SIZE_T>(newBufferLen));
-
-            if (enableRounding) // Don't round for G formatting without precision
-                RoundNumber(number, nMaxDigits); // This also fixes up the minus zero case
-            if (number->sign) {
-                AddStringRef(&dst, sNegative);
-            }
-
-
-        dst = FormatGeneral(dst, static_cast<SIZE_T>(newBufferLen/sizeof(WCHAR)), number, nMinDigits,nMaxDigits, format - ('G' - 'E'), sNumberDecimal, sPositive, sNegative, sZero, !enableRounding);
-        
-        }
-        break;
-    case 'P':
-        {
-        if (nMaxDigits< 0) 
-            // This ensures that the PAL code pads out to the correct place even when we use the default precision
-            nMaxDigits = nMinDigits = numfmt->cPercentDecimals;
-        else
-            nMinDigits=nMaxDigits;
-        number->scale += 2;
-
-        if (number->scale < 0)
-            digCount = 0;
-        else
-            digCount = number->scale + nMaxDigits;
-
-
-
-        // It is critical to format with the same values that we use to calculate buffer size.
-        int cNegativePercentFormat = numfmt->cNegativePercentFormat;
-        int cPositivePercentFormat = numfmt->cPositivePercentFormat;
-        I4ARRAYREF cPercentGroup = numfmt->cPercentGroup;
-        STRINGREF sPercentDecimal = numfmt->sPercentDecimal;
-        STRINGREF sPercentGroup = numfmt->sPercentGroup;
-        STRINGREF sNegative = numfmt->sNegative;
-        STRINGREF sPercent = numfmt->sPercent;
-
-        newBufferLen += digCount;
-        newBufferLen += sNegative->GetStringLength(); // For number and exponent
-        if (!ClrSafeInt<UINT64>::addition((UINT64)sPercentGroup->GetStringLength() * digCount, newBufferLen, newBufferLen))
-            COMPlusThrowOM();
-        newBufferLen += sPercentDecimal->GetStringLength();
-        newBufferLen += sPercent->GetStringLength();
-    
-        _ASSERTE(newBufferLen >= MIN_BUFFER_SIZE);
-        if (newBufferLen > INT32_MAX) {
-            COMPlusThrowOM();
-        }
-        newBufferLen = newBufferLen * sizeof(WCHAR);
-        dst = buffer = (WCHAR*)buf.AllocThrows(static_cast<SIZE_T>(newBufferLen));
-    
-        RoundNumber(number, number->scale + nMaxDigits);
-        dst = FormatPercent(dst, static_cast<SIZE_T>(newBufferLen/sizeof(WCHAR)),number, nMinDigits,nMaxDigits, cNegativePercentFormat, cPositivePercentFormat, cPercentGroup, sPercentDecimal, sPercentGroup, sNegative, sPercent, sZero);
-        
-        break;
-        }
-    default:
-        COMPlusThrow(kFormatException, W("Argument_BadFormatSpecifier"));
-    }
- // check for overflow of the preallocated buffer
-// Review signed/unsigned mismatch in '<=' comparison.
-#pragma warning(push)
-#pragma warning(disable:4018)
-    if (!((dst - buffer >= 0) && (dst - buffer) <= (newBufferLen / sizeof(WCHAR) ))) {
-#pragma warning(pop)
-        DoJITFailFast();
-    }
-
-    return StringObject::NewString(buffer, (int) (dst - buffer));
-}
-
-LPCWSTR FindSection(LPCWSTR format, int section)
-{
-    LIMITED_METHOD_CONTRACT
-    _ASSERTE(format != NULL);
-
-    LPCWSTR src;
-    wchar ch;
-    if (section == 0) return format;
-    src = format;
-    for (;;) {
-        switch (ch = *src++) {
-        case '\'':
-        case '"':
-            while (*src != 0 && *src++ != ch);
-            break;
-        case '\\':
-            if (*src != 0) src++;
-            break;
-        case ';':
-            if (--section != 0) break;
-            if (*src != 0 && *src != ';') return src;
-        case 0:
-            return format;
-        }
-    }
-}
-
-#ifdef _PREFAST_
-#pragma warning(push)
-#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
-#endif
-STRINGREF NumberToStringFormat(NUMBER* number, STRINGREF str, NUMFMTREF numfmt)
-{
-    CONTRACTL {
-        THROWS;
-        INJECT_FAULT(COMPlusThrowOM());
-        GC_TRIGGERS;
-        MODE_COOPERATIVE;
-    } CONTRACTL_END;
-
-    int digitCount;
-    int decimalPos;
-    int firstDigit;
-    int lastDigit;
-    int digPos;
-    int scientific;
-    int percent;
-    int permille;
-    int thousandPos;
-    int thousandCount = 0;
-    int thousandSeps;
-    int scaleAdjust;
-    int adjust;
-    wchar* format=NULL;
-    LPCWSTR section=NULL;
-    LPCWSTR src=NULL;
-    wchar* dst=NULL;
-    wchar* dig=NULL;
-    wchar ch;
-    wchar* buffer=NULL;
-    CQuickBytes buf;
-
-    _ASSERTE(str != NULL);
-    _ASSERTE(numfmt != NULL);
-    
-    STRINGREF sNegative = numfmt->sNegative;
-    STRINGREF sPositive = numfmt->sPositive;
-    STRINGREF sNumberDecimal = numfmt->sNumberDecimal;
-    STRINGREF sPercent = numfmt->sPercent;
-    STRINGREF sPerMille = numfmt->sPerMille;
-    STRINGREF sNumberGroup = numfmt->sNumberGroup;
-    I4ARRAYREF cNumberGroup = numfmt->cNumberGroup;    
-
-    format = str->GetBuffer();
-
-    section = FindSection(format, (GetDigitsBuffer(number))[0] == 0 ? 2 : number->sign ? 1 : 0);
-
-ParseSection:
-    digitCount = 0;
-    decimalPos = -1;
-    firstDigit = 0x7FFFFFFF;
-    lastDigit = 0;
-    scientific = 0;
-    percent = 0;
-    permille = 0;
-    thousandPos = -1;
-    thousandSeps = 0;
-    scaleAdjust = 0;
-    src = section;
-    _ASSERTE(src != NULL);
-    while ((ch = *src++) != 0 && ch != ';') {
-        switch (ch) {
-        case '#':
-            digitCount++;
-            break;
-        case '0':
-            if (firstDigit == 0x7FFFFFFF) firstDigit = digitCount;
-            digitCount++;
-            lastDigit = digitCount;
-            break;
-        case '.':
-            if (decimalPos < 0) {
-                decimalPos = digitCount;
-            }
-            break;
-        case ',':
-            if (digitCount > 0 && decimalPos < 0) {
-                if (thousandPos >= 0) {
-                    if (thousandPos == digitCount) {
-                        thousandCount++;
-                        break;
-                    }
-                    thousandSeps = 1;
-                }
-                thousandPos = digitCount;
-                thousandCount = 1;
-            }
-            break;
-        case '%':
-            percent++;
-            scaleAdjust += 2;
-            break;
-        case 0x2030:
-            permille++;
-            scaleAdjust += 3;
-            break;
-        case '\'':
-        case '"':
-            while (*src != 0 && *src++ != ch);
-            break;
-        case '\\':
-            if (*src != 0) src++;
-            break;
-        case 'E':
-        case 'e':
-            if (*src=='0' || ((*src == '+' || *src == '-') && src[1] == '0')) {
-                while (*++src == '0');
-                scientific = 1;
-            }
-            break;
-        }
-    }
-
-    if (decimalPos < 0) decimalPos = digitCount;
-    if (thousandPos >= 0) {
-        if (thousandPos == decimalPos) {
-            scaleAdjust -= thousandCount * 3;
-        }
-        else {
-            thousandSeps = 1;
-        }
-    }
-    if ((GetDigitsBuffer(number))[0] != 0) {
-        number->scale += scaleAdjust;
-        int pos = scientific? digitCount: number->scale + digitCount - decimalPos;
-        RoundNumber(number, pos);
-        if ((GetDigitsBuffer(number))[0] == 0) {
-            src = FindSection(format, 2);
-            if (src != section) {
-                section = src;
-                goto ParseSection;
-            }
-        }
-    } else {
-        number->sign = 0; // We need to format -0 without the sign set.
-        number->scale = 0; // Decimals with scale ('0.00') should be rounded.
-    }
-
-    firstDigit = firstDigit < decimalPos? decimalPos - firstDigit: 0;
-    lastDigit = lastDigit > decimalPos? decimalPos - lastDigit: 0;
-    if (scientific) {
-        digPos = decimalPos;
-        adjust = 0;
-    }
-    else {
-        digPos = number->scale > decimalPos? number->scale: decimalPos;
-        adjust = number->scale - decimalPos;
-    }
-    src = section;
-    dig = GetDigitsBuffer(number);
-
-    // Find maximum number of characters that the destination string can grow by
-    // in the following while loop.  Use this to avoid buffer overflows.
-    // Longest strings are potentially +/- signs with 10 digit exponents,
-    // or decimal numbers, or the while loops copying from a quote or a \ onwards.
-    // Check for positive and negative
-    UINT64 maxStrIncLen = 0; // We need this to be UINT64 since the percent computation could go beyond a UINT.
-    if (number->sign) {
-        maxStrIncLen = sNegative->GetStringLength();
-    }
-    else {
-        maxStrIncLen = sPositive->GetStringLength();
-    }
-
-    // Add for any big decimal seperator
-    maxStrIncLen += sNumberDecimal->GetStringLength();
-
-    // Add for scientific
-    if (scientific) {
-        int inc1 = sPositive->GetStringLength();
-        int inc2 = sNegative->GetStringLength();
-        maxStrIncLen +=(inc1>inc2)?inc1:inc2;
-    }
-
-    // Add for percent separator
-    if (percent) {
-        maxStrIncLen += ((INT64)sPercent->GetStringLength()) * percent;
-    }
-
-    // Add for permilli separator
-    if (permille) {
-        maxStrIncLen += ((INT64)sPerMille->GetStringLength()) * permille;
-    }
-
-    //adjust can be negative, so we make this an int instead of an unsigned int.
-    // adjust represents the number of characters over the formatting eg. format string is "0000" and you are trying to
-    // format 100000 (6 digits). Means adjust will be 2. On the other hand if you are trying to format 10 adjust will be
-    // -2 and we'll need to fixup these digits with 0 padding if we have 0 formatting as in this example.
-    INT64 adjustLen=(adjust>0)?adjust:0; // We need to add space for these extra characters anyway.
-    CQuickBytes thousands;
-    INT32 bufferLen2 = 125;
-    INT32 *thousandsSepPos = NULL;
-    INT32 thousandsSepCtr = -1;
-
-    if (thousandSeps) { // Fixup possible buffer overrun problems
-        // We need to precompute this outside the number formatting loop
-        if(cNumberGroup->GetNumComponents() == 0) {
-            thousandSeps = 0; // Nothing to add
-        }
-        else {
-            thousandsSepPos = (INT32 *)thousands.AllocThrows(bufferLen2 * sizeof(INT32));
-            // We need this array to figure out where to insert the thousands separator. We would have to traverse the string
-            // backwards. PIC formatting always traverses forwards. These indices are precomputed to tell us where to insert
-            // the thousands separator so we can get away with traversing forwards. Note we only have to compute up to digPos.
-            // The max is not bound since you can have formatting strings of the form "000,000..", and this
-            // should handle that case too.
-
-            const I4* groupDigits = cNumberGroup->GetDirectConstPointerToNonObjectElements();
-            _ASSERTE(groupDigits != NULL);
-
-            int groupSizeIndex = 0;     // index into the groupDigits array.
-            INT64 groupTotalSizeCount = 0;
-            int groupSizeLen   = cNumberGroup->GetNumComponents();    // the length of groupDigits array.
-            if (groupSizeLen != 0)
-                groupTotalSizeCount = groupDigits[groupSizeIndex];   // the current running total of group size.
-            int groupSize = static_cast<INT32>(groupTotalSizeCount); // safe cast as long as groupDigits remains I4
-
-            int totalDigits = digPos + ((adjust < 0)?adjust:0); // actual number of digits in o/p
-            int numDigits = (firstDigit > totalDigits) ? firstDigit : totalDigits;
-            while (numDigits > groupTotalSizeCount) {
-                if (groupSize == 0)
-                    break;
-                thousandsSepPos[++thousandsSepCtr] = static_cast<INT32>(groupTotalSizeCount);
-                if (groupSizeIndex < groupSizeLen - 1) {
-                    groupSizeIndex++;
-                    groupSize = groupDigits[groupSizeIndex];
-                }
-                groupTotalSizeCount += groupSize;
-                if (bufferLen2 - thousandsSepCtr < 10) { // Slack of 10
-                    bufferLen2 *= 2;
-                    thousands.ReSizeThrows(bufferLen2*sizeof(INT32)); // memcopied by CQuickBytes automatically
-                    thousandsSepPos = (INT32 *)thousands.Ptr();
-                }
-            }
-
-            // We already have computed the number of separators above. Simply add space for them.
-            adjustLen += ( (thousandsSepCtr + 1) * ((INT64)sNumberGroup->GetStringLength()));
-        }
-    }
-
-    maxStrIncLen += adjustLen;
-
-    // Allocate temp buffer - gotta deal with Schertz' 500 MB strings.
-    // Some computations like when you specify Int32.MaxValue-2 %'s and each percent is setup to be Int32.MaxValue in length
-    // will generate a result that will be largest than an unsigned int can hold. This is to protect against overflow.
-    UINT64 tempLen = str->GetStringLength() + maxStrIncLen + 10;  // Include a healthy amount of temp space.
-    if (tempLen > 0x7FFFFFFF)
-        COMPlusThrowOM(); // if we overflow
-
-    unsigned int bufferLen = (UINT)tempLen;
-    if (bufferLen < 250) // Stay under 512 bytes
-        bufferLen = 250; // This is to prevent unnecessary calls to resize
-    buffer = (wchar *) buf.AllocThrows(bufferLen* sizeof(WCHAR));
-    dst = buffer;
-
-
-    if (number->sign && section == format) {
-        AddStringRef(&dst, sNegative);
-    }
-
-    BOOL decimalWritten = FALSE;
-
-    while ((ch = *src++) != 0 && ch != ';') {
-        // Make sure temp buffer is big enough, else resize it.
-        if (bufferLen - (unsigned int)(dst-buffer) < 10) {
-            int offset = static_cast<INT32>(dst - buffer);
-            bufferLen *= 2;
-            buf.ReSizeThrows(bufferLen*sizeof(WCHAR));
-            buffer = (wchar*)buf.Ptr(); // memcopied by QuickBytes automatically
-            dst = buffer + offset;
-        }
-
-        if (adjust > 0) {
-            switch (ch) {
-            case '#':
-            case '0':
-            case '.':
-                while (adjust > 0) { // digPos will be one greater than thousandsSepPos[thousandsSepCtr] since we are at
-                    // the character after which the groupSeparator needs to be appended.
-                    *dst++ = *dig != 0? *dig++: '0';
-                    if (thousandSeps && digPos > 1 && thousandsSepCtr>=0) {
-                        if (digPos == thousandsSepPos[thousandsSepCtr] + 1)  {
-                            AddStringRef(&dst, sNumberGroup);
-                            thousandsSepCtr--;
-                        }
-                    }
-                    digPos--;
-                    adjust--;
-                }
-            }
-        }
-
-        switch (ch) {
-        case '#':
-        case '0':
-            {
-                if (adjust < 0) {
-                    adjust++;
-                    ch = digPos <= firstDigit? '0': 0;
-                }
-                else {
-                    ch = *dig != 0? *dig++: digPos > lastDigit? '0': 0;
-                }
-                if (ch != 0) {
-                    *dst++ = ch;
-                    if (thousandSeps && digPos > 1 && thousandsSepCtr>=0) {
-                        if (digPos == thousandsSepPos[thousandsSepCtr] + 1) {
-                            AddStringRef(&dst, sNumberGroup);
-                            thousandsSepCtr--;
-                        }
-                    }
-                }
-
-                digPos--;
-                break;
-            }
-        case '.':
-            {
-                if (digPos != 0 || decimalWritten) {
-                    // For compatibility, don't echo repeated decimals
-                    break;
-                }
-                // If the format has trailing zeros or the format has a decimal and digits remain
-                if (lastDigit < 0
-                    || (decimalPos < digitCount && *dig != 0)) {
-                    AddStringRef(&dst, sNumberDecimal);
-                    decimalWritten = TRUE;
-                }
-                break;
-            }
-        case 0x2030:
-            AddStringRef(&dst, sPerMille);
-            break;
-        case '%':
-            AddStringRef(&dst, sPercent);
-            break;
-        case ',':
-            break;
-        case '\'':
-        case '"':
-            // Buffer overflow possibility
-            while (*src != 0 && *src != ch) {
-                *dst++ = *src++;
-                if ((unsigned int)(dst-buffer) == bufferLen-1) {
-                    if (bufferLen - (unsigned int)(dst-buffer) < maxStrIncLen) {
-                        int offset = static_cast<INT32>(dst - buffer);
-                        bufferLen *= 2;
-                        buf.ReSizeThrows(bufferLen*sizeof(WCHAR)); // memcopied by CQuickBytes automatically
-                        buffer = (wchar *)buf.Ptr();
-                        dst = buffer + offset;
-                    }
-                }
-            }
-            if (*src != 0) src++;
-            break;
-        case '\\':
-            if (*src != 0) *dst++ = *src++;
-            break;
-        case 'E':
-        case 'e':
-            {
-                STRINGREF sign = NULL;
-                int i = 0;
-                if (scientific) {
-                    if (*src=='0') {
-                        //Handles E0, which should format the same as E-0
-                        i++;
-                    } else if (*src == '+' && src[1] == '0') {
-                        //Handles E+0
-                        sign = sPositive;
-                    } else if (*src == '-' && src[1] == '0') {
-                        //Handles E-0
-                        //Do nothing, this is just a place holder s.t. we don't break out of the loop.
-                    } else {
-                        *dst++ = ch;
-                        break;
-                    }
-                    while (*++src == '0') i++;
-                    if (i > 10) i = 10;
-                    int exp = (GetDigitsBuffer(number))[0] == 0 ? 0 : number->scale - decimalPos;
-                    dst = FormatExponent(dst, exp, ch, sign, sNegative, i);
-                    scientific = 0;
-                }
-                else
-                {
-                    *dst++ = ch; // Copy E or e to output
-                    if (*src== '+' || *src == '-') {
-                        *dst++ = *src++;
-                    }
-                    while (*src == '0') {
-                        *dst++ = *src++;
-                    }
-                }
-                break;
-            }
-        default:
-            *dst++ = ch;
-        }
-    }
-    if (!((dst - buffer >= 0) && (dst - buffer <= (int)bufferLen))) {
-        DoJITFailFast();
-    }
-    STRINGREF newStr = StringObject::NewString(buffer, (int)(dst - buffer));
-    return newStr;
-}
-#ifdef _PREFAST_
-#pragma warning(pop)
-#endif
-
 FCIMPL3_VII(void, COMNumber::DoubleToNumberFC, double value, int precision, NUMBER* number)
 {
     FCALL_CONTRACT;
index 0fd12b1..22c74ca 100644 (file)
@@ -33,8 +33,6 @@ class COMNumber
 public:
     static FCDECL3_VII(void, DoubleToNumberFC, double value, int precision, NUMBER* number);
     static FCDECL1(double, NumberToDoubleFC, NUMBER* number);
-    
-    static wchar_t* Int32ToDecChars(__in wchar_t* p, unsigned int value, int digits);
 };
 
 #include <poppack.h>