bool CalcInput::TryAddDigit()

in src/CalcManager/CEngine/CalcInput.cpp [59:170]


bool CalcInput::TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMode, wstring_view maxNumStr, int32_t wordBitWidth, int maxDigits)
{
    // Convert from an integer into a character
    // This includes both normal digits and alpha 'digits' for radixes > 10
    auto chDigit = static_cast<wchar_t>((value < 10) ? (L'0' + value) : (L'A' + value - 10));

    CalcNumSec* pNumSec;
    size_t maxCount;
    if (m_hasExponent)
    {
        pNumSec = &m_exponent;
        maxCount = C_EXP_MAX_DIGITS;
    }
    else
    {
        pNumSec = &m_base;
        maxCount = maxDigits;
        // Don't include the decimal point in the count. In that way you can enter the maximum allowed precision.
        // Precision doesn't include decimal point.
        if (HasDecimalPt())
        {
            maxCount++;
        }
        // First leading 0 is not counted in input restriction as the output can be of that form
        // See NumberToString algorithm. REVIEW: We don't have such input restriction mimicking based on output of NumberToString for exponent
        // NumberToString can give 10 digit exponent, but we still restrict the exponent here to be only 4 digits.
        if (!pNumSec->IsEmpty() && pNumSec->value.front() == L'0')
        {
            maxCount++;
        }
    }

    // Ignore leading zeros
    if (pNumSec->IsEmpty() && (value == 0))
    {
        return true;
    }

    if (pNumSec->value.size() < maxCount)
    {
        pNumSec->value += chDigit;
        return true;
    }

    // if we are in integer mode, within the base, and we're on the last digit then
    // there are special cases where we can actually add one more digit.
    if (isIntegerMode && pNumSec->value.size() == maxCount && !m_hasExponent)
    {
        bool allowExtraDigit = false;

        if (radix == 8)
        {
            switch (wordBitWidth % 3)
            {
            case 1:
                // in 16 or 64bit word size, if the first digit is a 1 we can enter 6 (16bit) or 22 (64bit) digits
                allowExtraDigit = (pNumSec->value.front() == L'1');
                break;

            case 2:
                // in 8 or 32bit word size, if the first digit is a 3 or less we can enter 3 (8bit) or 11 (32bit) digits
                allowExtraDigit = (pNumSec->value.front() <= L'3');
                break;
            }
        }
        else if (radix == 10)
        {
            // If value length is at least the max, we know we can't add another digit.
            if (pNumSec->value.size() < maxNumStr.size())
            {
                // Compare value to substring of maxNumStr of value.size() length.
                // If cmpResult > 0:
                // eg. max is "127", and the current number is "20". first digit itself says we are out.
                // Additional digit is not possible

                // If cmpResult < 0:
                // Success case. eg. max is "127", and current number is say "11". The second digit '1' being <
                // corresponding digit '2', means all digits are possible to append, like 119 will still be < 127

                // If cmpResult == 0:
                // Undecided still. The case when max is "127", and current number is "12". Look for the new number being 7 or less to allow
                auto cmpResult = pNumSec->value.compare(0, wstring::npos, maxNumStr, 0, pNumSec->value.size());
                if (cmpResult < 0)
                {
                    allowExtraDigit = true;
                }
                else if (cmpResult == 0)
                {
                    auto lastChar = maxNumStr[pNumSec->value.size()];
                    if (chDigit <= lastChar)
                    {
                        allowExtraDigit = true;
                    }
                    else if (pNumSec->IsNegative() && chDigit <= lastChar + 1)
                    {
                        // Negative value case, eg. max is "127", and current number is "-12". Then 8 is also valid, as the range
                        // is always from -(max+1)...max in signed mode
                        allowExtraDigit = true;
                    }
                }
            }
        }

        if (allowExtraDigit)
        {
            pNumSec->value += chDigit;
            return true;
        }
    }

    return false;
}