CodeBlob iNumber(Number number) { return iNumber(number.coefficient, number.exponent); }
void parseNumber(const std::string& number, Signedness signedness, T& sign, std::string& integer, std::string& fractional) { char dec_point = '.'; enum {PS_SIGN, PS_INT, PS_POINT, PS_FRAC} state; state = PS_SIGN; std::string iNumber(number); if (iNumber.empty()) { iNumber = "0"; } T iSign = T(1); std::string iInteger; std::string iFractional; sign = T(1); integer = "0"; fractional = "0"; std::size_t idx = 0; if ((iNumber[idx] == '-') && (signedness == Fi::SIGNED)) { iSign = T(-1); ++idx; state = PS_INT; } else if ((iNumber[idx] == '-') && (signedness == Fi::UNSIGNED)) { throw std::invalid_argument("An unsigned number cannot have a " "negative sign!"); } else if (iNumber[idx] == '+') { iSign = T(1); ++idx; state = PS_INT; } else if (isDigit(iNumber[idx])) { iSign = T(1); state = PS_INT; } else if (iNumber[idx] == dec_point) { iSign = T(1); ++idx; state = PS_FRAC; } else { throw std::invalid_argument("Invalid number format: " + number); } for (; idx < iNumber.length(); ++idx) { if (isDigit(iNumber[idx]) && (state == PS_INT)) { iInteger.push_back(iNumber[idx]); } else if (isDigit(iNumber[idx]) && (state == PS_FRAC)) { iFractional.push_back(iNumber[idx]); } else if ((iNumber[idx] == dec_point) && (state == PS_INT)) { state = PS_FRAC; } else { throw std::invalid_argument("Invalid number format: " + number); } } if (iInteger.empty() && iFractional.empty()) { throw std::invalid_argument("A number must have at least one digit!"); } size_t firstNZ = iInteger.find_first_not_of('0'); if (firstNZ > 0) { iInteger.erase(0, firstNZ); } size_t lastNZ = iFractional.find_last_not_of('0'); if (lastNZ == std::string::npos) { iFractional = "0"; } else { iFractional.erase(lastNZ + 1); } if (iInteger.empty()) { iInteger = "0"; } if (iFractional.empty()) { iFractional = "0"; } sign = iSign; integer = iInteger; fractional = iFractional; }