Changed handling of numbers witth a leading plus character

This commit is contained in:
Maarten L. Hekkelman
2026-04-22 11:17:25 +02:00
parent 56c75490f2
commit de9b33a918
5 changed files with 61 additions and 6 deletions

View File

@@ -1,5 +1,8 @@
Version 10.0.3
- Clear pdbx_nonpoly_scheme before filling it in reconstruction
- Changed handling of numbers with a preceding plus character,
these are now stored as strings to avoid inadvertently
mutilating phone numbers.
Version 10.0.2
- Fixed regression in reconstruction introduced in 10.0.1

View File

@@ -331,8 +331,11 @@ class item_value
case TEXT:
{
auto sv = m_data.sv();
auto sp = sv.data();
if (*sp == '+')
++sp;
int64_t v;
auto &&[ptr, ec] = from_chars(sv.data(), sv.data() + sv.length(), v);
auto &&[ptr, ec] = from_chars(sp, sv.data() + sv.length(), v);
if (ec != std::errc{})
throw std::system_error(std::make_error_code(ec));
if (ptr != sv.data() + sv.length())
@@ -361,8 +364,11 @@ class item_value
case TEXT:
{
auto sv = m_data.sv();
auto sp = sv.data();
if (*sp == '+')
++sp;
double v;
auto &&[ptr, ec] = from_chars(sv.data(), sv.data() + sv.length(), v);
auto &&[ptr, ec] = from_chars(sp, sv.data() + sv.length(), v);
if (ec != std::errc{})
throw std::system_error(std::make_error_code(ec));
if (ptr != sv.data() + sv.length())

View File

@@ -239,7 +239,12 @@ void item_value::cast_to_int()
{
auto s = sv();
int64_t v;
auto [ptr, ec] = cif::from_chars(s.data(), s.data() + s.size(), v);
auto sp = s.data();
if (*sp == '+')
++sp;
auto [ptr, ec] = cif::from_chars(sp, s.data() + s.size(), v);
if (ec != std::errc{})
throw std::system_error(std::make_error_code(ec), "attempt to cast value to integer failed");
if (ptr != s.data() + s.size())

View File

@@ -635,9 +635,18 @@ sac_parser::CIFToken sac_parser::get_next_token()
if (result == CIFToken::VALUE_NUMERIC_INTEGER)
{
auto [ptr, ec] = from_chars(m_token_buffer.data(), m_token_buffer.data() + m_token_buffer.size(), m_token_value_int);
if (ec != std::errc{})
error("Invalid integer value: " + std::make_error_code(ec).message());
// Avoid interpreting phone numbers as integers, TODO: check if this is an issue
if (m_token_buffer.front() == '+')
{
result = CIFToken::VALUE_CHARSTRING;
m_token_value = std::string_view(m_token_buffer.data(), m_token_buffer.size());
}
else
{
auto [ptr, ec] = from_chars(m_token_buffer.data(), m_token_buffer.data() + m_token_buffer.size(), m_token_value_int);
if (ec != std::errc{})
error("Invalid integer value: " + std::make_error_code(ec).message());
}
}
else if (result == CIFToken::VALUE_NUMERIC_FLOAT)
{

View File

@@ -3664,5 +3664,37 @@ HETATM 2 O O . HOH A 1 . ? 10.518 -1.781 0 1 37.22 ? O HOH 2 D 1
)");
}
// --------------------------------------------------------------------
TEST_CASE("number-test-1")
{
auto data = R"(data_test
_pdbx_contact_author.id 1
_pdbx_contact_author.name_mi +98765432109
)"_cf;
auto &db = data.front();
db.load_dictionary("mmcif_pdbx.dic");
auto r = db["pdbx_contact_author"].front();
CHECK(r["name_mi"].str() == "+98765432109");
CHECK(r["name_mi"].get<int64_t>() == 98765432109);
CHECK(r["name_mi"].get<double>() == 98765432109.0);
}
TEST_CASE("number-test-2")
{
auto data = R"(data_test
_pdbx_contact_author.id 1
_pdbx_contact_author.name_mi '+98765432109'
)"_cf;
auto &db = data.front();
db.load_dictionary("mmcif_pdbx.dic");
auto r = db["pdbx_contact_author"].front();
CHECK(r["name_mi"].str() == "+98765432109");
CHECK(r["name_mi"].get<int64_t>() == 98765432109);
CHECK(r["name_mi"].get<double>() == 98765432109.0);
}