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

Function DecimalFromString

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

Source from the content-addressed store, hash-verified

861
862template <typename Decimal>
863Status DecimalFromString(const char* type_name, std::string_view s, Decimal* out,
864 int32_t* precision, int32_t* scale) {
865 if (s.empty()) {
866 return Status::Invalid("Empty string cannot be converted to ", type_name);
867 }
868
869 DecimalComponents dec;
870 if (!ParseDecimalComponents(s.data(), s.size(), &dec)) {
871 return Status::Invalid("The string '", s, "' is not a valid ", type_name, " number");
872 }
873
874 // Count number of significant digits (without leading zeros)
875 size_t first_non_zero = dec.whole_digits.find_first_not_of('0');
876 size_t significant_digits = dec.fractional_digits.size();
877 if (first_non_zero != std::string::npos) {
878 significant_digits += dec.whole_digits.size() - first_non_zero;
879 }
880 int32_t parsed_precision = static_cast<int32_t>(significant_digits);
881
882 int32_t parsed_scale = 0;
883 if (dec.has_exponent) {
884 auto adjusted_exponent = dec.exponent;
885 parsed_scale =
886 -adjusted_exponent + static_cast<int32_t>(dec.fractional_digits.size());
887 } else {
888 parsed_scale = static_cast<int32_t>(dec.fractional_digits.size());
889 }
890
891 if (out != nullptr) {
892 static_assert(Decimal::kBitWidth % 64 == 0, "decimal bit-width not a multiple of 64");
893 std::array<uint64_t, Decimal::kBitWidth / 64> little_endian_array{};
894 ShiftAndAdd(dec.whole_digits, little_endian_array.data(), little_endian_array.size());
895 ShiftAndAdd(dec.fractional_digits, little_endian_array.data(),
896 little_endian_array.size());
897 *out = Decimal(bit_util::little_endian::ToNative(little_endian_array));
898 if (dec.sign == '-') {
899 out->Negate();
900 }
901 }
902
903 if (parsed_scale < 0) {
904 // Force the scale to zero, to avoid negative scales (due to compatibility issues
905 // with external systems such as databases)
906 if (-parsed_scale > Decimal::kMaxScale) {
907 return Status::Invalid("The string '", s, "' cannot be represented as ", type_name);
908 }
909 if (out != nullptr) {
910 *out *= Decimal::GetScaleMultiplier(-parsed_scale);
911 }
912 parsed_precision -= parsed_scale;
913 parsed_scale = 0;
914 }
915
916 if (precision != nullptr) {
917 *precision = parsed_precision;
918 }
919 if (scale != nullptr) {
920 *scale = parsed_scale;

Callers 1

FromStringMethod · 0.70

Calls 11

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

Tested by

no test coverage detected