MCPcopy Create free account
hub / github.com/apache/arrow / SimpleDecimalFromString

Function SimpleDecimalFromString

cpp/src/arrow/util/decimal.cc:931–999  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

929
930template <typename DecimalClass>
931Status SimpleDecimalFromString(const char* type_name, std::string_view s,
932 DecimalClass* out, int32_t* precision, int32_t* scale) {
933 if (s.empty()) {
934 return Status::Invalid("Empty string cannot be converted to ", type_name);
935 }
936
937 DecimalComponents dec;
938 if (!ParseDecimalComponents(s.data(), s.size(), &dec)) {
939 return Status::Invalid("The string '", s, "' is not a valid ", type_name, " number");
940 }
941
942 // count number of significant digits (without leading zeros)
943 size_t first_non_zero = dec.whole_digits.find_first_not_of('0');
944 size_t significant_digits = dec.fractional_digits.size();
945 if (first_non_zero != std::string::npos) {
946 significant_digits += dec.whole_digits.size() - first_non_zero;
947 }
948 int32_t parsed_precision = static_cast<int32_t>(significant_digits);
949
950 int32_t parsed_scale = 0;
951 if (dec.has_exponent) {
952 // parsed_scale = -exponent + fractional_digits, computed with overflow
953 // detection: an exponent of INT32_MIN ("0E-2147483648") makes the negation,
954 // and a near-INT32_MIN exponent the addition, signed-overflow UB otherwise.
955 if (internal::SubtractWithOverflow(static_cast<int32_t>(dec.fractional_digits.size()),
956 dec.exponent, &parsed_scale)) {
957 return Status::Invalid("The string '", s, "' cannot be represented as ", type_name);
958 }
959 } else {
960 parsed_scale = static_cast<int32_t>(dec.fractional_digits.size());
961 }
962
963 if (out != nullptr) {
964 uint64_t value{0};
965 ShiftAndAdd(dec.whole_digits, &value, 1);
966 ShiftAndAdd(dec.fractional_digits, &value, 1);
967 if (value > static_cast<uint64_t>(
968 std::numeric_limits<typename DecimalClass::ValueType>::max())) {
969 return Status::Invalid("The string '", s, "' cannot be represented as ", type_name);
970 }
971
972 *out = DecimalClass(value);
973 if (dec.sign == '-') {
974 out->Negate();
975 }
976 }
977
978 if (parsed_scale < 0) {
979 // Force the scale to zero, to avoid negative scales (due to compatibility issues
980 // with external systems such as databases)
981 if (-parsed_scale > DecimalClass::kMaxScale) {
982 return Status::Invalid("The string '", s, "' cannot be represented as ", type_name);
983 }
984 if (out != nullptr) {
985 *out *= DecimalClass::GetScaleMultiplier(-parsed_scale);
986 }
987 parsed_precision -= parsed_scale;
988 parsed_scale = 0;

Callers 1

FromStringMethod · 0.85

Calls 9

ParseDecimalComponentsFunction · 0.85
ShiftAndAddFunction · 0.85
GetScaleMultiplierFunction · 0.85
NegateMethod · 0.80
InvalidFunction · 0.50
OKFunction · 0.50
emptyMethod · 0.45
dataMethod · 0.45
sizeMethod · 0.45

Tested by

no test coverage detected