mirror of
https://github.com/PDB-REDO/libcifpp.git
synced 2026-06-04 22:14:24 +08:00
Compare commits
4 Commits
develop
...
new-item-s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cdb694d4a6 | ||
|
|
60f80673e3 | ||
|
|
a0f4eada6f | ||
|
|
64e6b3cd2d |
@@ -259,18 +259,18 @@ set(project_sources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/validate.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/text.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/utilities.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/atom_type.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/compound.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/point.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/symmetry.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/model.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/cif2pdb.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/pdb2cif.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/pdb_record.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/pdb2cif_remark_3.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/pdb2cif_remark_3.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/reconstruct.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/validate-pdbx.cpp
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/src/atom_type.cpp
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/src/compound.cpp
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/src/point.cpp
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/src/symmetry.cpp
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/src/model.cpp
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/cif2pdb.cpp
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/pdb2cif.cpp
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/pdb_record.hpp
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/pdb2cif_remark_3.hpp
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/pdb2cif_remark_3.cpp
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/reconstruct.cpp
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/validate-pdbx.cpp
|
||||
)
|
||||
|
||||
set(project_headers
|
||||
|
||||
@@ -28,12 +28,14 @@
|
||||
|
||||
#include "cif++/forward_decl.hpp"
|
||||
|
||||
#include "cif++/condition.hpp"
|
||||
// #include "cif++/condition.hpp"
|
||||
#include "cif++/item.hpp"
|
||||
#include "cif++/iterator.hpp"
|
||||
#include "cif++/row.hpp"
|
||||
#include "cif++/text.hpp"
|
||||
|
||||
#include <array>
|
||||
// #include <array>
|
||||
#include <functional>
|
||||
|
||||
/** \file category.hpp
|
||||
* Documentation for the cif::category class
|
||||
@@ -108,16 +110,6 @@ class multiple_results_error : public std::runtime_error
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// These should be moved elsewhere, one day.
|
||||
|
||||
/// \cond
|
||||
template <typename _Tp>
|
||||
inline constexpr bool is_optional_v = false;
|
||||
template <typename _Tp>
|
||||
inline constexpr bool is_optional_v<std::optional<_Tp>> = true;
|
||||
/// \endcond
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/// The class category is a sequence container for rows of data values.
|
||||
@@ -181,12 +173,8 @@ class category
|
||||
|
||||
const std::string &name() const { return m_name; } ///< Returns the name of the category
|
||||
|
||||
[[deprecated("use key_items instead")]] iset key_fields() const; ///< Returns the cif::iset of key item names. Retrieved from the @ref category_validator for this category
|
||||
|
||||
iset key_items() const; ///< Returns the cif::iset of key item names. Retrieved from the @ref category_validator for this category
|
||||
|
||||
[[deprecated("use key_item_indices instead")]] std::set<uint16_t> key_field_indices() const; ///< Returns a set of indices for the key items.
|
||||
|
||||
std::set<uint16_t> key_item_indices() const; ///< Returns a set of indices for the key items.
|
||||
|
||||
/// @brief Set the validator for this category to @a v
|
||||
@@ -336,7 +324,7 @@ class category
|
||||
struct key_element_type
|
||||
{
|
||||
std::string name; ///< Name of the item
|
||||
std::string value; ///< Value to be found
|
||||
item_value value; ///< Value to be found
|
||||
bool may_be_null = false; ///< If true, value should be same or empty
|
||||
};
|
||||
|
||||
@@ -961,7 +949,7 @@ class category
|
||||
for (auto i = b; i != e; ++i)
|
||||
{
|
||||
// item_value *new_item = this->create_item(*i);
|
||||
r->append(add_item(i->name()), { i->value() });
|
||||
r->append(add_item(i->name()), i->value());
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
@@ -1005,7 +993,7 @@ class category
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
using value_provider_type = std::function<std::string_view(std::string_view)>;
|
||||
using value_provider_type = std::function<item_value(const item_value &)>;
|
||||
|
||||
/// \brief Update a single item named @a item_name in the rows that match
|
||||
/// \a cond to values provided by a callback function \a value_provider
|
||||
@@ -1036,7 +1024,7 @@ class category
|
||||
/// That means, child categories are updated if the links are absolute
|
||||
/// and unique. If they are not, the child category rows are split.
|
||||
|
||||
void update_value(condition &&cond, std::string_view item_name, std::string_view value)
|
||||
void update_value(condition &&cond, std::string_view item_name, item_value value)
|
||||
{
|
||||
auto rs = find(std::move(cond));
|
||||
std::vector<row_handle> rows;
|
||||
@@ -1049,66 +1037,12 @@ class category
|
||||
/// That means, child categories are updated if the links are absolute
|
||||
/// and unique. If they are not, the child category rows are split.
|
||||
|
||||
void update_value(const std::vector<row_handle> &rows, std::string_view item_name, std::string_view value)
|
||||
void update_value(const std::vector<row_handle> &rows, std::string_view item_name, item_value value)
|
||||
{
|
||||
update_value(rows, item_name, [value](std::string_view)
|
||||
update_value(rows, item_name, [value](const item_value &v)
|
||||
{ return value; });
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Naming used to be very inconsistent. For backward compatibility,
|
||||
// the old function names are here as deprecated variants.
|
||||
|
||||
/// \brief Return the index number for \a column_name
|
||||
[[deprecated("Use get_item_ix instead")]] uint16_t get_column_ix(std::string_view column_name) const
|
||||
{
|
||||
return get_item_ix(column_name);
|
||||
}
|
||||
|
||||
/// @brief Return the name for column with index @a ix
|
||||
/// @param ix The index number
|
||||
/// @return The name of the column
|
||||
[[deprecated("use get_item_name instead")]] std::string_view get_column_name(uint16_t ix) const
|
||||
{
|
||||
return get_item_name(ix);
|
||||
}
|
||||
|
||||
/// @brief Make sure a item with name @a item_name is known and return its index number
|
||||
/// @param item_name The name of the item
|
||||
/// @return The index number of the item
|
||||
[[deprecated("use add_item instead")]] uint16_t add_column(std::string_view item_name)
|
||||
{
|
||||
return add_item(item_name);
|
||||
}
|
||||
|
||||
/** @brief Remove column name @a colum_name
|
||||
* @param column_name The column to be removed
|
||||
*/
|
||||
[[deprecated("use remove_item instead")]] void remove_column(std::string_view column_name)
|
||||
{
|
||||
remove_item(column_name);
|
||||
}
|
||||
|
||||
/** @brief Rename column @a from_name to @a to_name */
|
||||
[[deprecated("use rename_item instead")]] void rename_column(std::string_view from_name, std::string_view to_name)
|
||||
{
|
||||
rename_item(from_name, to_name);
|
||||
}
|
||||
|
||||
/// @brief Return whether a column with name @a name exists in this category
|
||||
/// @param name The name of the column
|
||||
/// @return True if the column exists
|
||||
[[deprecated("use has_item instead")]] bool has_column(std::string_view name) const
|
||||
{
|
||||
return has_item(name);
|
||||
}
|
||||
|
||||
/// @brief Return the cif::iset of columns in this category
|
||||
[[deprecated("use get_items instead")]] iset get_columns() const
|
||||
{
|
||||
return get_items();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
/// \brief Return the index number for \a item_name
|
||||
|
||||
@@ -1117,7 +1051,7 @@ class category
|
||||
/// @brief Return the name for item with index @a ix
|
||||
/// @param ix The index number
|
||||
/// @return The name of the item
|
||||
std::string_view get_item_name(uint16_t ix) const
|
||||
const std::string &get_item_name(uint16_t ix) const
|
||||
{
|
||||
if (ix >= m_items.size())
|
||||
throw std::out_of_range("item index is out of range");
|
||||
@@ -1200,7 +1134,7 @@ class category
|
||||
}
|
||||
|
||||
private:
|
||||
void update_value(row *row, uint16_t item, std::string_view value, bool updateLinked, bool validate = true);
|
||||
void update_value(row *row, uint16_t item, item_value value, bool updateLinked, bool validate = true);
|
||||
|
||||
void erase_orphans(condition &&cond, category &parent);
|
||||
|
||||
|
||||
@@ -371,7 +371,7 @@ namespace detail
|
||||
{
|
||||
key_equals_condition_impl(item &&i)
|
||||
: m_item_name(i.name())
|
||||
, m_value(std::forward<item>(i).value())
|
||||
, m_value(std::forward<item_value>(i.value()))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -409,7 +409,7 @@ namespace detail
|
||||
std::string m_item_name;
|
||||
uint16_t m_item_ix = 0;
|
||||
bool m_icase = false;
|
||||
std::string m_value;
|
||||
item_value m_value;
|
||||
std::optional<row_handle> m_single_hit;
|
||||
};
|
||||
|
||||
@@ -466,111 +466,11 @@ namespace detail
|
||||
|
||||
std::string m_item_name;
|
||||
uint16_t m_item_ix = 0;
|
||||
std::string m_value;
|
||||
item_value &m_value;
|
||||
bool m_icase = false;
|
||||
std::optional<row_handle> m_single_hit;
|
||||
};
|
||||
|
||||
struct key_equals_number_condition_impl : public condition_impl
|
||||
{
|
||||
key_equals_number_condition_impl(const std::string &name, double v)
|
||||
: m_item_name(name)
|
||||
, m_value(v)
|
||||
{
|
||||
}
|
||||
|
||||
condition_impl *prepare(const category &c) override;
|
||||
|
||||
bool test(row_handle r) const override
|
||||
{
|
||||
return m_single_hit.has_value() ? *m_single_hit == r : r[m_item_ix].compare(m_value) == 0;
|
||||
}
|
||||
|
||||
void str(std::ostream &os) const override
|
||||
{
|
||||
os << m_item_name << " == " << m_value;
|
||||
}
|
||||
|
||||
virtual std::optional<row_handle> single() const override
|
||||
{
|
||||
return m_single_hit;
|
||||
}
|
||||
|
||||
virtual bool equals(const condition_impl *rhs) const override
|
||||
{
|
||||
if (typeid(*rhs) == typeid(key_equals_number_condition_impl))
|
||||
{
|
||||
auto ri = static_cast<const key_equals_number_condition_impl *>(rhs);
|
||||
if (m_single_hit.has_value() or ri->m_single_hit.has_value())
|
||||
return m_single_hit == ri->m_single_hit;
|
||||
else
|
||||
// watch out, both m_item_ix might be the same while item_names might be diffent (in case they both do not exist in the category)
|
||||
return m_item_ix == ri->m_item_ix and m_value == ri->m_value and m_item_name == ri->m_item_name;
|
||||
}
|
||||
return this == rhs;
|
||||
}
|
||||
|
||||
std::string m_item_name;
|
||||
uint16_t m_item_ix = 0;
|
||||
double m_value;
|
||||
std::optional<row_handle> m_single_hit;
|
||||
};
|
||||
|
||||
struct key_equals_number_or_empty_condition_impl : public condition_impl
|
||||
{
|
||||
key_equals_number_or_empty_condition_impl(key_equals_number_condition_impl *equals)
|
||||
: m_item_name(equals->m_item_name)
|
||||
, m_value(equals->m_value)
|
||||
, m_single_hit(equals->m_single_hit)
|
||||
{
|
||||
}
|
||||
|
||||
condition_impl *prepare(const category &c) override
|
||||
{
|
||||
m_item_ix = get_item_ix(c, m_item_name);
|
||||
return this;
|
||||
}
|
||||
|
||||
bool test(row_handle r) const override
|
||||
{
|
||||
bool result = false;
|
||||
if (m_single_hit.has_value())
|
||||
result = *m_single_hit == r;
|
||||
else
|
||||
result = r[m_item_ix].empty() or r[m_item_ix].compare(m_value) == 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
void str(std::ostream &os) const override
|
||||
{
|
||||
os << '(' << m_item_name << " == " << m_value << " OR " << m_item_name << " IS NULL)";
|
||||
}
|
||||
|
||||
virtual std::optional<row_handle> single() const override
|
||||
{
|
||||
return m_single_hit;
|
||||
}
|
||||
|
||||
virtual bool equals(const condition_impl *rhs) const override
|
||||
{
|
||||
if (typeid(*rhs) == typeid(key_equals_number_or_empty_condition_impl))
|
||||
{
|
||||
auto ri = static_cast<const key_equals_number_or_empty_condition_impl *>(rhs);
|
||||
if (m_single_hit.has_value() or ri->m_single_hit.has_value())
|
||||
return m_single_hit == ri->m_single_hit;
|
||||
else
|
||||
// watch out, both m_item_ix might be the same while item_names might be diffent (in case they both do not exist in the category)
|
||||
return m_item_ix == ri->m_item_ix and m_value == ri->m_value and m_item_name == ri->m_item_name;
|
||||
}
|
||||
return this == rhs;
|
||||
}
|
||||
|
||||
std::string m_item_name;
|
||||
uint16_t m_item_ix = 0;
|
||||
double m_value;
|
||||
std::optional<row_handle> m_single_hit;
|
||||
};
|
||||
|
||||
struct key_compare_condition_impl : public condition_impl
|
||||
{
|
||||
template <typename COMP>
|
||||
@@ -622,7 +522,7 @@ namespace detail
|
||||
|
||||
bool test(row_handle r) const override
|
||||
{
|
||||
std::string_view txt = r[m_item_ix].text();
|
||||
auto txt = r[m_item_ix].get<std::string>();
|
||||
return std::regex_match(txt.begin(), txt.end(), mRx);
|
||||
}
|
||||
|
||||
@@ -693,7 +593,7 @@ namespace detail
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string_view txt = r[f].text();
|
||||
auto txt = r[f].get<std::string>();
|
||||
if (std::regex_match(txt.begin(), txt.end(), mRx))
|
||||
{
|
||||
result = true;
|
||||
@@ -970,26 +870,6 @@ inline condition operator or(condition &&a, condition &&b)
|
||||
return condition(new detail::key_equals_or_empty_condition_impl(ci));
|
||||
}
|
||||
|
||||
if (typeid(*a.m_impl) == typeid(detail::key_equals_number_condition_impl) and
|
||||
typeid(*b.m_impl) == typeid(detail::key_is_empty_condition_impl))
|
||||
{
|
||||
auto ci = static_cast<detail::key_equals_number_condition_impl *>(a.m_impl);
|
||||
auto ce = static_cast<detail::key_is_empty_condition_impl *>(b.m_impl);
|
||||
|
||||
if (ci->m_item_name == ce->m_item_name)
|
||||
return condition(new detail::key_equals_number_or_empty_condition_impl(ci));
|
||||
}
|
||||
|
||||
if (typeid(*b.m_impl) == typeid(detail::key_equals_number_condition_impl) and
|
||||
typeid(*a.m_impl) == typeid(detail::key_is_empty_condition_impl))
|
||||
{
|
||||
auto ci = static_cast<detail::key_equals_number_condition_impl *>(b.m_impl);
|
||||
auto ce = static_cast<detail::key_is_empty_condition_impl *>(a.m_impl);
|
||||
|
||||
if (ci->m_item_name == ce->m_item_name)
|
||||
return condition(new detail::key_equals_number_or_empty_condition_impl(ci));
|
||||
}
|
||||
|
||||
return condition(new detail::or_condition_impl(std::move(a), std::move(b)));
|
||||
}
|
||||
|
||||
@@ -1066,20 +946,10 @@ struct key
|
||||
template <typename T>
|
||||
concept Numeric = ((std::is_floating_point_v<T> or std::is_integral_v<T>) and not std::is_same_v<T, bool>);
|
||||
|
||||
/**
|
||||
* @brief Operator to create an equals condition based on a key @a key and a numeric value @a v
|
||||
*/
|
||||
template <Numeric T>
|
||||
condition operator==(const key &key, const T &v)
|
||||
{
|
||||
// TODO: change key_equals_etc... to use std::variant<double,int64_t> or something
|
||||
return condition(new detail::key_equals_number_condition_impl(key.m_item_name, static_cast<double>(v)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create an equals condition based on a key @a key and a value @a value
|
||||
*/
|
||||
inline condition operator==(const key &key, std::string_view value)
|
||||
inline condition operator==(const key &key, item_value value)
|
||||
{
|
||||
if (not value.empty())
|
||||
return condition(new detail::key_equals_condition_impl({ key.m_item_name, value }));
|
||||
@@ -1087,16 +957,6 @@ inline condition operator==(const key &key, std::string_view value)
|
||||
return condition(new detail::key_is_empty_condition_impl(key.m_item_name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create an equals condition based on a key @a key and a value @a value
|
||||
*/
|
||||
template <typename T>
|
||||
requires std::is_same_v<T, bool>
|
||||
inline condition operator==(const key &key, T value)
|
||||
{
|
||||
return condition(new detail::key_equals_condition_impl({ key.m_item_name, value ? "y" : "n" }));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a not equals condition based on a key @a key and a value @a v
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cif++/condition.hpp"
|
||||
#include "cif++/row.hpp"
|
||||
|
||||
#include <array>
|
||||
@@ -179,7 +180,7 @@ class iterator_impl
|
||||
template <std::size_t... Is>
|
||||
tuple_type get(std::index_sequence<Is...>) const
|
||||
{
|
||||
return m_current ? tuple_type{ m_current[m_item_ix[Is]].template as<Ts>()... } : tuple_type{};
|
||||
return m_current ? tuple_type{ m_current[m_item_ix[Is]].template get<Ts>()... } : tuple_type{};
|
||||
}
|
||||
|
||||
row_handle m_current;
|
||||
@@ -422,7 +423,7 @@ class iterator_impl<Category, T>
|
||||
private:
|
||||
value_type get() const
|
||||
{
|
||||
return m_current ? m_current[m_item_ix].template as<value_type>() : value_type{};
|
||||
return m_current ? m_current[m_item_ix].template get<value_type>() : value_type{};
|
||||
}
|
||||
|
||||
row_handle m_current;
|
||||
|
||||
@@ -190,7 +190,7 @@ class atom
|
||||
* @param row The row containing the data for this atom
|
||||
*/
|
||||
atom(const datablock &db, const row_handle &row)
|
||||
: atom(std::make_shared<atom_impl>(db, row["id"].as<std::string>()))
|
||||
: atom(std::make_shared<atom_impl>(db, row["id"].get<std::string>()))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -164,7 +164,13 @@ class sac_parser
|
||||
SAVE_NAME,
|
||||
STOP,
|
||||
ITEM_NAME,
|
||||
VALUE
|
||||
|
||||
VALUE_INAPPLICABLE,
|
||||
VALUE_UNKNOWN,
|
||||
VALUE_NUMERIC_INTEGER,
|
||||
VALUE_NUMERIC_FLOAT,
|
||||
VALUE_CHARSTRING,
|
||||
VALUE_TEXTFIELD
|
||||
};
|
||||
|
||||
static constexpr const char *get_token_name(CIFToken token)
|
||||
@@ -180,7 +186,15 @@ class sac_parser
|
||||
case CIFToken::SAVE_NAME: return "SAVE+name";
|
||||
case CIFToken::STOP: return "STOP";
|
||||
case CIFToken::ITEM_NAME: return "Tag";
|
||||
case CIFToken::VALUE: return "Value";
|
||||
// case CIFToken::VALUE: return "Value";
|
||||
|
||||
case CIFToken::VALUE_INAPPLICABLE: return "Inapplicable value";
|
||||
case CIFToken::VALUE_UNKNOWN: return "'Unknown' value (=null)";
|
||||
case CIFToken::VALUE_NUMERIC_INTEGER: return "Integer value";
|
||||
case CIFToken::VALUE_NUMERIC_FLOAT: return "Float value";
|
||||
case CIFToken::VALUE_CHARSTRING: return "Charstring value";
|
||||
case CIFToken::VALUE_TEXTFIELD: return "Textfield value";
|
||||
|
||||
default: return "Invalid token parameter";
|
||||
}
|
||||
}
|
||||
@@ -262,7 +276,7 @@ class sac_parser
|
||||
virtual void produce_datablock(std::string_view name) = 0;
|
||||
virtual void produce_category(std::string_view name) = 0;
|
||||
virtual void produce_row() = 0;
|
||||
virtual void produce_item(std::string_view category, std::string_view item, std::string_view value) = 0;
|
||||
virtual void produce_item(std::string_view category, std::string_view item, item_value value) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -281,7 +295,12 @@ class sac_parser
|
||||
TextItem,
|
||||
TextItemNL,
|
||||
Reserved,
|
||||
Value
|
||||
Value,
|
||||
|
||||
Numeric_Integer,
|
||||
Numeric_Float,
|
||||
Numeric_Exponent1,
|
||||
Numeric_Exponent2
|
||||
};
|
||||
|
||||
std::streambuf &m_source;
|
||||
@@ -294,6 +313,8 @@ class sac_parser
|
||||
// token buffer
|
||||
std::vector<char> m_token_buffer;
|
||||
std::string_view m_token_value;
|
||||
int64_t m_token_value_int;
|
||||
double m_token_value_float;
|
||||
|
||||
/** @endcond */
|
||||
};
|
||||
@@ -331,7 +352,7 @@ class parser : public sac_parser
|
||||
|
||||
void produce_row() override;
|
||||
|
||||
void produce_item(std::string_view category, std::string_view item, std::string_view value) override;
|
||||
void produce_item(std::string_view category, std::string_view item, item_value value) override;
|
||||
|
||||
protected:
|
||||
file &m_file;
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
* that's not the case.
|
||||
*
|
||||
* You can access the values of stored items by name or index.
|
||||
* The return value of operator[] is an cif::item_handle object.
|
||||
* The return value of operator[] is a reference to a cif::item_value object.
|
||||
*
|
||||
* @code {.cpp}
|
||||
* cif::category &atom_site = my_db["atom_site"];
|
||||
@@ -93,7 +93,7 @@ namespace detail
|
||||
{
|
||||
}
|
||||
|
||||
const item_handle operator[](uint16_t ix) const
|
||||
const item_value &operator[](uint16_t ix) const
|
||||
{
|
||||
return m_row[m_items[ix]];
|
||||
}
|
||||
@@ -107,7 +107,7 @@ namespace detail
|
||||
template <typename... Ts, std::size_t... Is>
|
||||
std::tuple<Ts...> get(std::index_sequence<Is...>) const
|
||||
{
|
||||
return std::tuple<Ts...>{ m_row[m_items[Is]].template as<Ts>()... };
|
||||
return std::tuple<Ts...>{ m_row[m_items[Is]].template get<Ts>()... };
|
||||
}
|
||||
|
||||
const row_handle &m_row;
|
||||
@@ -173,14 +173,14 @@ class row : public std::vector<item_value>
|
||||
return ix < size() ? &data()[ix] : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
// private:
|
||||
friend class category;
|
||||
friend class category_index;
|
||||
|
||||
template <typename, typename...>
|
||||
friend class iterator_impl;
|
||||
|
||||
void append(uint16_t ix, item_value &&iv)
|
||||
void append(uint16_t ix, item_value iv)
|
||||
{
|
||||
if (ix >= size())
|
||||
resize(ix + 1);
|
||||
@@ -204,7 +204,6 @@ class row_handle
|
||||
{
|
||||
public:
|
||||
/** @cond */
|
||||
friend struct item_handle;
|
||||
friend class category;
|
||||
friend class category_index;
|
||||
friend class row_initializer;
|
||||
@@ -245,29 +244,20 @@ class row_handle
|
||||
return not empty();
|
||||
}
|
||||
|
||||
/// \brief return a cif::item_handle to the item in item @a item_ix
|
||||
item_handle operator[](uint16_t item_ix)
|
||||
{
|
||||
return empty() ? item_handle::s_null_item : item_handle(item_ix, *this);
|
||||
}
|
||||
/// \brief return the count of the items
|
||||
[[nodiscard]] size_t size() const { return m_row->size(); }
|
||||
|
||||
/// \brief return a const cif::item_handle to the item in item @a item_ix
|
||||
const item_handle operator[](uint16_t item_ix) const
|
||||
{
|
||||
return empty() ? item_handle::s_null_item : item_handle(item_ix, const_cast<row_handle &>(*this));
|
||||
}
|
||||
/// \brief return a reference to a cif::item_value to the item in item @a item_ix
|
||||
item_value &operator[](uint16_t item_ix);
|
||||
|
||||
/// \brief return a cif::item_handle to the item in the item named @a item_name
|
||||
item_handle operator[](std::string_view item_name)
|
||||
{
|
||||
return empty() ? item_handle::s_null_item : item_handle(add_item(item_name), *this);
|
||||
}
|
||||
/// \brief return a const reference to a cif::item_value to the item in item @a item_ix
|
||||
const item_value &operator[](uint16_t item_ix) const;
|
||||
|
||||
/// \brief return a const cif::item_handle to the item in the item named @a item_name
|
||||
const item_handle operator[](std::string_view item_name) const
|
||||
{
|
||||
return empty() ? item_handle::s_null_item : item_handle(get_item_ix(item_name), const_cast<row_handle &>(*this));
|
||||
}
|
||||
/// \brief return a reference to a cif::item_value to the item in the item named @a item_name
|
||||
item_value &operator[](std::string_view item_name);
|
||||
|
||||
/// \brief return a const reference to a cif::item_value to the item in the item named @a item_name
|
||||
const item_value &operator[](std::string_view item_name) const;
|
||||
|
||||
/// \brief Return an object that can be used in combination with cif::tie
|
||||
/// to assign the values for the items @a items
|
||||
@@ -288,14 +278,14 @@ class row_handle
|
||||
template <typename T>
|
||||
T get(const char *item) const
|
||||
{
|
||||
return operator[](get_item_ix(item)).template as<T>();
|
||||
return operator[](get_item_ix(item)).template get<T>();
|
||||
}
|
||||
|
||||
/// \brief Get the value of item @a item cast to type @a T
|
||||
template <typename T>
|
||||
T get(std::string_view item) const
|
||||
{
|
||||
return operator[](get_item_ix(item)).template as<T>();
|
||||
return operator[](get_item_ix(item)).template get<T>();
|
||||
}
|
||||
|
||||
/// \brief assign each of the items named in @a values to their respective value
|
||||
@@ -316,9 +306,9 @@ class row_handle
|
||||
* checked to see if it conforms to the rules defined in the dictionary
|
||||
*/
|
||||
|
||||
void assign(std::string_view name, std::string_view value, bool updateLinked, bool validate = true)
|
||||
void assign(std::string_view name, item_value value, bool updateLinked, bool validate = true)
|
||||
{
|
||||
assign(add_item(name), value, updateLinked, validate);
|
||||
assign(add_item(name), std::move(value), updateLinked, validate);
|
||||
}
|
||||
|
||||
/** \brief assign the value @a value to item at index @a item
|
||||
@@ -332,7 +322,7 @@ class row_handle
|
||||
* checked to see if it conforms to the rules defined in the dictionary
|
||||
*/
|
||||
|
||||
void assign(uint16_t item, std::string_view value, bool updateLinked, bool validate = true);
|
||||
void assign(uint16_t item, item_value value, bool updateLinked, bool validate = true);
|
||||
|
||||
/// \brief compare two rows
|
||||
bool operator==(const row_handle &rhs) const { return m_category == rhs.m_category and m_row == rhs.m_row; }
|
||||
@@ -356,10 +346,10 @@ class row_handle
|
||||
return m_row;
|
||||
}
|
||||
|
||||
void assign(const item &i, bool updateLinked)
|
||||
void assign(const item &i, bool updateLinked);/*
|
||||
{
|
||||
assign(i.name(), i.value(), updateLinked);
|
||||
}
|
||||
} */
|
||||
|
||||
void swap(uint16_t item, row_handle &r);
|
||||
|
||||
@@ -408,7 +398,7 @@ class row_initializer : public std::vector<item>
|
||||
|
||||
|
||||
/// \brief set the value for item name @a name to @a value
|
||||
void set_value(std::string_view name, std::string_view value);
|
||||
void set_value(std::string name, item_value value);
|
||||
|
||||
/// \brief set the value for item based on @a i
|
||||
void set_value(const item &i)
|
||||
@@ -417,7 +407,7 @@ class row_initializer : public std::vector<item>
|
||||
}
|
||||
|
||||
/// \brief set the value for item name @a name to @a value, but only if the item did not have a value already
|
||||
void set_value_if_empty(std::string_view name, std::string_view value);
|
||||
void set_value_if_empty(std::string name, item_value value);
|
||||
|
||||
/// \brief set the value for item @a i, but only if the item did not have a value already
|
||||
void set_value_if_empty(const item &i)
|
||||
|
||||
@@ -329,10 +329,10 @@ struct item_validator
|
||||
|
||||
/// @brief Validate the value in @a value for this item
|
||||
/// Will throw a std::system_error exception if it fails
|
||||
void operator()(std::string_view value) const;
|
||||
void operator()(const item_value &value) const;
|
||||
|
||||
/// @brief A more gentle version of value validation
|
||||
bool validate_value(std::string_view value, std::error_code &ec) const noexcept;
|
||||
bool validate_value(const item_value &value, std::error_code &ec) const noexcept;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
1638
src/category.cpp
1638
src/category.cpp
File diff suppressed because it is too large
Load Diff
@@ -123,21 +123,6 @@ namespace detail
|
||||
return this;
|
||||
}
|
||||
|
||||
condition_impl *key_equals_number_condition_impl::prepare(const category &c)
|
||||
{
|
||||
m_item_ix = c.get_item_ix(m_item_name);
|
||||
|
||||
if (c.get_cat_validator() != nullptr and
|
||||
c.key_item_indices().contains(m_item_ix) and
|
||||
c.key_item_indices().size() == 1)
|
||||
{
|
||||
item v(m_item_name, m_value);
|
||||
m_single_hit = c[{ { m_item_name, std::string{ v.value() }, false } }];
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
bool found_in_range(condition_impl *c, std::vector<and_condition_impl *>::iterator b, std::vector<and_condition_impl *>::iterator e)
|
||||
{
|
||||
bool result = true;
|
||||
@@ -234,17 +219,6 @@ namespace detail
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto s = dynamic_cast<const key_equals_number_condition_impl *>(sub); s != nullptr)
|
||||
{
|
||||
if (keys.contains(s->m_item_name))
|
||||
{
|
||||
item v{ s->m_item_name, s->m_value };
|
||||
lookup.emplace_back(s->m_item_name, std::string{ v.value() } );
|
||||
subs.emplace_back(sub);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto s = dynamic_cast<const key_equals_or_empty_condition_impl *>(sub); s != nullptr)
|
||||
{
|
||||
if (keys.contains(s->m_item_name))
|
||||
@@ -255,17 +229,6 @@ namespace detail
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto s = dynamic_cast<const key_equals_number_or_empty_condition_impl *>(sub); s != nullptr)
|
||||
{
|
||||
if (keys.contains(s->m_item_name))
|
||||
{
|
||||
item v{ s->m_item_name, s->m_value };
|
||||
lookup.emplace_back(s->m_item_name, std::string{ v.value() }, true );
|
||||
subs.emplace_back(sub);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (lookup.size() == keys.size())
|
||||
|
||||
@@ -153,7 +153,7 @@ class dictionary_parser : public parser
|
||||
match(CIFToken::ITEM_NAME);
|
||||
}
|
||||
|
||||
while (m_lookahead == CIFToken::VALUE)
|
||||
while (m_lookahead >= CIFToken::VALUE_INAPPLICABLE)
|
||||
{
|
||||
cat->emplace({});
|
||||
auto row = cat->back();
|
||||
@@ -161,7 +161,7 @@ class dictionary_parser : public parser
|
||||
for (auto item_name : item_names)
|
||||
{
|
||||
row[item_name] = m_token_value;
|
||||
match(CIFToken::VALUE);
|
||||
match(m_lookahead);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ class dictionary_parser : public parser
|
||||
cat->emplace({});
|
||||
cat->back()[item_name] = m_token_value;
|
||||
|
||||
match(CIFToken::VALUE);
|
||||
match(m_lookahead >= CIFToken::VALUE_INAPPLICABLE ? m_lookahead : CIFToken::VALUE_CHARSTRING);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,11 +193,11 @@ class dictionary_parser : public parser
|
||||
|
||||
std::vector<std::string> keys;
|
||||
for (auto k : dict["category_key"])
|
||||
keys.push_back(std::get<1>(split_item_name(k["name"].as<std::string>())));
|
||||
keys.push_back(std::get<1>(split_item_name(k["name"].get<std::string>())));
|
||||
|
||||
iset groups;
|
||||
for (auto g : dict["category_group"])
|
||||
groups.insert(g["id"].as<std::string>());
|
||||
groups.insert(g["id"].get<std::string>());
|
||||
|
||||
mCategoryValidators.push_back(category_validator{ category, keys, groups });
|
||||
}
|
||||
@@ -212,7 +212,7 @@ class dictionary_parser : public parser
|
||||
|
||||
iset ess;
|
||||
for (auto e : dict["item_enumeration"])
|
||||
ess.insert(e["value"].as<std::string>());
|
||||
ess.insert(e["value"].get<std::string>());
|
||||
|
||||
std::string defaultValue = dict["item_default"].front().get<std::string>("value");
|
||||
// bool defaultIsNull = false;
|
||||
@@ -405,7 +405,7 @@ class dictionary_parser : public parser
|
||||
// look up the label
|
||||
for (auto r : linkedGroup.find("category_id"_key == link.m_child_category and "link_group_id"_key == link.m_link_group_id))
|
||||
{
|
||||
link.m_link_group_label = r["label"].as<std::string>();
|
||||
link.m_link_group_label = r["label"].get<std::string>();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
114
src/item.cpp
114
src/item.cpp
@@ -24,45 +24,109 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "cif++/item.hpp"
|
||||
|
||||
#include "cif++/row.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <compare>
|
||||
#include <ios>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
|
||||
const item_handle item_handle::s_null_item;
|
||||
row_handle s_null_row_handle;
|
||||
|
||||
item_handle::item_handle()
|
||||
: m_item_ix(std::numeric_limits<uint16_t>::max())
|
||||
, m_row_handle(s_null_row_handle)
|
||||
int item_value::compare(const item_value &b, bool ignore_case) const noexcept
|
||||
{
|
||||
}
|
||||
int d = static_cast<int>(m_data.m_type) - static_cast<int>(b.m_data.m_type);
|
||||
|
||||
std::string_view item_handle::text() const
|
||||
{
|
||||
if (not m_row_handle.empty())
|
||||
if (d == 0)
|
||||
{
|
||||
auto iv = m_row_handle.m_row->get(m_item_ix);
|
||||
if (iv != nullptr)
|
||||
return iv->text();
|
||||
switch (m_data.m_type)
|
||||
{
|
||||
case cif::item_value_type::BOOLEAN:
|
||||
d = static_cast<int>(m_data.m_value.m_boolean) - static_cast<int>(b.m_data.m_value.m_boolean);
|
||||
break;
|
||||
case cif::item_value_type::INT:
|
||||
d = m_data.m_value.m_integer - b.m_data.m_value.m_integer;
|
||||
break;
|
||||
case cif::item_value_type::FLOAT:
|
||||
{
|
||||
auto dp = (m_data.m_value.m_float <=> b.m_data.m_value.m_float);
|
||||
if (dp == std::partial_ordering::less)
|
||||
d = -1;
|
||||
else if (dp == std::partial_ordering::greater)
|
||||
d = 1;
|
||||
break;
|
||||
}
|
||||
case cif::item_value_type::TEXT:
|
||||
d = m_data.sv().compare(b.m_data.sv());
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
return d;
|
||||
}
|
||||
|
||||
void item_handle::assign_value(std::string_view value)
|
||||
// const item_handle item_handle::s_null_item;
|
||||
// row_handle s_null_row_handle;
|
||||
|
||||
// item_handle::item_handle()
|
||||
// : m_item_ix(std::numeric_limits<uint16_t>::max())
|
||||
// , m_row_handle(s_null_row_handle)
|
||||
// {
|
||||
// }
|
||||
|
||||
// std::string_view item_handle::text() const
|
||||
// {
|
||||
// if (not m_row_handle.empty())
|
||||
// {
|
||||
// auto iv = m_row_handle.m_row->get(m_item_ix);
|
||||
// if (iv != nullptr)
|
||||
// return iv->text();
|
||||
// }
|
||||
|
||||
// return {};
|
||||
// }
|
||||
|
||||
// void item_handle::assign_value(std::string_view value)
|
||||
// {
|
||||
// assert(not m_row_handle.empty());
|
||||
// m_row_handle.assign(m_item_ix, value, true);
|
||||
// }
|
||||
|
||||
// void item_handle::swap(item_handle &b)
|
||||
// {
|
||||
// assert(m_item_ix == b.m_item_ix);
|
||||
// // assert(&m_row_handle.m_category == &b.m_row_handle.m_category);
|
||||
// m_row_handle.swap(m_item_ix, b.m_row_handle);
|
||||
// }
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const item_value &v)
|
||||
{
|
||||
assert(not m_row_handle.empty());
|
||||
m_row_handle.assign(m_item_ix, value, true);
|
||||
switch (v.type())
|
||||
{
|
||||
case cif::item_value_type::BOOLEAN:
|
||||
os << std::boolalpha << v.m_data.m_value.m_boolean;
|
||||
break;
|
||||
case cif::item_value_type::INT:
|
||||
os << v.m_data.m_value.m_integer;
|
||||
break;
|
||||
case cif::item_value_type::FLOAT:
|
||||
os << v.m_data.m_value.m_float;
|
||||
break;
|
||||
case cif::item_value_type::TEXT:
|
||||
os << v.m_data.sv();
|
||||
break;
|
||||
case cif::item_value_type::MISSING:
|
||||
os << '?';
|
||||
break;
|
||||
case cif::item_value_type::EMPTY:
|
||||
os << '.';
|
||||
break;
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
void item_handle::swap(item_handle &b)
|
||||
{
|
||||
assert(m_item_ix == b.m_item_ix);
|
||||
// assert(&m_row_handle.m_category == &b.m_row_handle.m_category);
|
||||
m_row_handle.swap(m_item_ix, b.m_row_handle);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace cif
|
||||
|
||||
@@ -62,7 +62,7 @@ void atom::atom_impl::moveTo(const point &p)
|
||||
|
||||
std::string atom::atom_impl::get_property(std::string_view name) const
|
||||
{
|
||||
return row()[name].as<std::string>();
|
||||
return row()[name].get<std::string>();
|
||||
}
|
||||
|
||||
int atom::atom_impl::get_property_int(std::string_view name) const
|
||||
@@ -135,7 +135,7 @@ int atom::atom_impl::compare(const atom_impl &b) const
|
||||
|
||||
int atom::atom_impl::get_charge() const
|
||||
{
|
||||
auto formalCharge = row()["pdbx_formal_charge"].as<std::optional<int>>();
|
||||
auto formalCharge = row()["pdbx_formal_charge"].get<std::optional<int>>();
|
||||
|
||||
if (not formalCharge.has_value())
|
||||
{
|
||||
@@ -1891,11 +1891,7 @@ void structure::swap_atoms(atom a1, atom a2)
|
||||
auto r2 = atomSites.find1(key("id") == a2.id());
|
||||
|
||||
for (std::string fld : std::initializer_list<std::string>{ "label_atom_id", "auth_atom_id", "type_symbol" })
|
||||
{
|
||||
auto l1 = r1[fld];
|
||||
auto l2 = r2[fld];
|
||||
l1.swap(l2);
|
||||
}
|
||||
swap(r1[fld], r2[fld]);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
@@ -2758,7 +2754,7 @@ void structure::cleanup_empty_categories()
|
||||
|
||||
for (auto chemComp : chem_comp)
|
||||
{
|
||||
std::string compID = chemComp["id"].as<std::string>();
|
||||
std::string compID = chemComp["id"].get<std::string>();
|
||||
if (atomSite.contains("label_comp_id"_key == compID or "auth_comp_id"_key == compID) or
|
||||
pdbxPolySeqScheme.contains("mon_id"_key == compID or "auth_mon_id"_key == compID or "pdb_mon_id"_key == compID) or
|
||||
entityPolySeq.contains("mon_id"_key == compID))
|
||||
@@ -2779,7 +2775,7 @@ void structure::cleanup_empty_categories()
|
||||
|
||||
for (auto entity : entities)
|
||||
{
|
||||
std::string entityID = entity["id"].as<std::string>();
|
||||
std::string entityID = entity["id"].get<std::string>();
|
||||
if (atomSite.contains("label_entity_id"_key == entityID))
|
||||
continue;
|
||||
|
||||
|
||||
215
src/parser.cpp
215
src/parser.cpp
@@ -24,15 +24,19 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "cif++/utilities.hpp"
|
||||
#include "cif++/forward_decl.hpp"
|
||||
#include "cif++/parser.hpp"
|
||||
|
||||
#include "cif++/file.hpp"
|
||||
#include "cif++/forward_decl.hpp"
|
||||
#include "cif++/item.hpp"
|
||||
#include "cif++/utilities.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <charconv>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <system_error>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
@@ -58,12 +62,12 @@ class reserved_words_automaton
|
||||
|
||||
constexpr bool finished() const
|
||||
{
|
||||
return m_state <= 0;
|
||||
return m_state <= 0;
|
||||
}
|
||||
|
||||
constexpr bool matched() const
|
||||
{
|
||||
return m_state < 0;
|
||||
return m_state < 0;
|
||||
}
|
||||
|
||||
constexpr move_result move(int ch)
|
||||
@@ -75,7 +79,7 @@ class reserved_words_automaton
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case -1: // data_
|
||||
case -1: // data_
|
||||
if (sac_parser::is_non_blank(ch))
|
||||
m_seen_trailing_chars = true;
|
||||
else if (m_seen_trailing_chars)
|
||||
@@ -84,15 +88,15 @@ class reserved_words_automaton
|
||||
result = no_keyword;
|
||||
break;
|
||||
|
||||
case -2: // global_
|
||||
case -2: // global_
|
||||
result = sac_parser::is_non_blank(ch) ? no_keyword : global;
|
||||
break;
|
||||
|
||||
case -3: // loop_
|
||||
case -3: // loop_
|
||||
result = sac_parser::is_non_blank(ch) ? no_keyword : loop;
|
||||
break;
|
||||
|
||||
case -4: // save_
|
||||
case -4: // save_
|
||||
if (sac_parser::is_non_blank(ch))
|
||||
m_seen_trailing_chars = true;
|
||||
else if (m_seen_trailing_chars)
|
||||
@@ -101,10 +105,10 @@ class reserved_words_automaton
|
||||
result = save;
|
||||
break;
|
||||
|
||||
case -5: // stop_
|
||||
case -5: // stop_
|
||||
result = sac_parser::is_non_blank(ch) ? no_keyword : stop;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
assert(m_state > 0 and m_state < NODE_COUNT);
|
||||
|
||||
@@ -141,13 +145,13 @@ class reserved_words_automaton
|
||||
int8_t next_nomatch;
|
||||
} s_dag[] = {
|
||||
{ 0 },
|
||||
{ 'D', 5, 2 },
|
||||
{ 'G', 9, 3 },
|
||||
{ 'D', 5, 2 },
|
||||
{ 'G', 9, 3 },
|
||||
{ 'L', 15, 4 },
|
||||
{ 'S', 19, 0 },
|
||||
{ 'A', 6, 0 },
|
||||
{ 'T', 7, 0 },
|
||||
{ 'A', 8, 0 },
|
||||
{ 'A', 6, 0 },
|
||||
{ 'T', 7, 0 },
|
||||
{ 'A', 8, 0 },
|
||||
{ '_', -1, 0 },
|
||||
{ 'L', 10, 0 },
|
||||
{ 'O', 11, 0 },
|
||||
@@ -155,7 +159,7 @@ class reserved_words_automaton
|
||||
{ 'A', 13, 0 },
|
||||
{ 'L', 14, 0 },
|
||||
{ '_', -2, 0 },
|
||||
{ 'O', 16, 0},
|
||||
{ 'O', 16, 0 },
|
||||
{ 'O', 17, 0 },
|
||||
{ 'P', 18, 0 },
|
||||
{ '_', -3, 0 },
|
||||
@@ -238,7 +242,7 @@ int sac_parser::get_next_char()
|
||||
}
|
||||
else if (result == '\n')
|
||||
++m_line_nr;
|
||||
|
||||
|
||||
m_token_buffer.push_back(std::char_traits<char>::to_char_type(result));
|
||||
}
|
||||
|
||||
@@ -277,6 +281,8 @@ sac_parser::CIFToken sac_parser::get_next_token()
|
||||
m_token_buffer.clear();
|
||||
m_token_value = {};
|
||||
|
||||
bool negative = false;
|
||||
|
||||
reserved_words_automaton dag;
|
||||
|
||||
while (result == CIFToken::UNKNOWN)
|
||||
@@ -310,6 +316,15 @@ sac_parser::CIFToken sac_parser::get_next_token()
|
||||
}
|
||||
else if (dag.move(ch) == reserved_words_automaton::undefined)
|
||||
state = State::Reserved;
|
||||
else if (ch == '+' or ch == '-')
|
||||
{
|
||||
negative = true;
|
||||
state = State::Numeric_Integer;
|
||||
}
|
||||
else if (ch >= '0' and ch <= '9')
|
||||
state = State::Numeric_Integer;
|
||||
else if (ch == '.')
|
||||
state = State::Numeric_Float;
|
||||
else
|
||||
state = State::Value;
|
||||
break;
|
||||
@@ -326,7 +341,7 @@ sac_parser::CIFToken sac_parser::get_next_token()
|
||||
else
|
||||
m_bol = (ch == '\n');
|
||||
break;
|
||||
|
||||
|
||||
case State::Comment:
|
||||
if (ch == '\n')
|
||||
{
|
||||
@@ -339,12 +354,12 @@ sac_parser::CIFToken sac_parser::get_next_token()
|
||||
else if (not is_any_print(ch))
|
||||
error("invalid character in comment");
|
||||
break;
|
||||
|
||||
|
||||
case State::QuestionMark:
|
||||
if (not is_non_blank(ch))
|
||||
{
|
||||
retract();
|
||||
result = CIFToken::VALUE;
|
||||
result = CIFToken::VALUE_UNKNOWN;
|
||||
}
|
||||
else
|
||||
state = State::Value;
|
||||
@@ -356,7 +371,7 @@ sac_parser::CIFToken sac_parser::get_next_token()
|
||||
else if (ch == kEOF)
|
||||
error("unterminated textfield");
|
||||
else if (not is_any_print(ch) and cif::VERBOSE > 2)
|
||||
warning("invalid character in text field '" + std::string({static_cast<char>(ch)}) + "' (" + std::to_string((int)ch) + ")");
|
||||
warning("invalid character in text field '" + std::string({ static_cast<char>(ch) }) + "' (" + std::to_string((int)ch) + ")");
|
||||
break;
|
||||
|
||||
case State::TextItemNL:
|
||||
@@ -366,7 +381,7 @@ sac_parser::CIFToken sac_parser::get_next_token()
|
||||
{
|
||||
assert(m_token_buffer.size() >= 2);
|
||||
m_token_value = std::string_view(m_token_buffer.data() + 1, m_token_buffer.size() - 3);
|
||||
result = CIFToken::VALUE;
|
||||
result = CIFToken::VALUE_TEXTFIELD;
|
||||
}
|
||||
else if (ch == kEOF)
|
||||
error("unterminated textfield");
|
||||
@@ -380,14 +395,14 @@ sac_parser::CIFToken sac_parser::get_next_token()
|
||||
else if (ch == quoteChar)
|
||||
state = State::QuotedStringQuote;
|
||||
else if (not is_any_print(ch) and cif::VERBOSE > 2)
|
||||
warning("invalid character in quoted string: '" + std::string({static_cast<char>(ch)}) + "' (" + std::to_string((int)ch) + ")");
|
||||
warning("invalid character in quoted string: '" + std::string({ static_cast<char>(ch) }) + "' (" + std::to_string((int)ch) + ")");
|
||||
break;
|
||||
|
||||
case State::QuotedStringQuote:
|
||||
if (is_white(ch))
|
||||
{
|
||||
retract();
|
||||
result = CIFToken::VALUE;
|
||||
result = CIFToken::VALUE_CHARSTRING;
|
||||
if (m_token_buffer.size() < 2)
|
||||
error("Invalid quoted string token");
|
||||
|
||||
@@ -422,7 +437,7 @@ sac_parser::CIFToken sac_parser::get_next_token()
|
||||
if (not is_non_blank(ch))
|
||||
{
|
||||
retract();
|
||||
result = CIFToken::VALUE;
|
||||
result = CIFToken::VALUE_CHARSTRING;
|
||||
m_token_value = std::string_view(m_token_buffer.data(), m_token_buffer.size());
|
||||
}
|
||||
else
|
||||
@@ -463,11 +478,65 @@ sac_parser::CIFToken sac_parser::get_next_token()
|
||||
}
|
||||
break;
|
||||
|
||||
case State::Numeric_Integer:
|
||||
if (ch == '.')
|
||||
state = State::Numeric_Float;
|
||||
else if (ch == 'e' or ch == 'E')
|
||||
state = State::Numeric_Exponent1;
|
||||
else if (not is_non_blank(ch))
|
||||
{
|
||||
retract();
|
||||
result = CIFToken::VALUE_NUMERIC_INTEGER;
|
||||
}
|
||||
else if (ch < '0' or ch > '9')
|
||||
state = State::Value;
|
||||
break;
|
||||
|
||||
case State::Numeric_Float:
|
||||
if (not is_non_blank(ch))
|
||||
{
|
||||
retract();
|
||||
if (m_token_buffer.size() == 1)
|
||||
result = CIFToken::VALUE_INAPPLICABLE;
|
||||
else
|
||||
result = CIFToken::VALUE_NUMERIC_FLOAT;
|
||||
}
|
||||
else if (ch == 'e' or ch == 'E')
|
||||
state = State::Numeric_Exponent1;
|
||||
else if (ch < '0' or ch > '9')
|
||||
state = State::Value;
|
||||
break;
|
||||
|
||||
case State::Numeric_Exponent1:
|
||||
if (ch == '+' or ch == '-' or (ch >= '0' and ch <= '9'))
|
||||
state = State::Numeric_Exponent2;
|
||||
else
|
||||
{
|
||||
if (VERBOSE > 0)
|
||||
std::cerr << "parsing " << std::string_view{ m_token_buffer.data(), m_token_buffer.size() } << " Invalid floating point value, expected digit or sign character\n";
|
||||
state = State::Value;
|
||||
}
|
||||
break;
|
||||
|
||||
case State::Numeric_Exponent2:
|
||||
if (not is_non_blank(ch))
|
||||
{
|
||||
retract();
|
||||
result = CIFToken::VALUE_NUMERIC_FLOAT;
|
||||
}
|
||||
else if (ch < '0' or ch > '9')
|
||||
{
|
||||
if (VERBOSE > 0)
|
||||
std::cerr << "parsing " << std::string_view{ m_token_buffer.data(), m_token_buffer.size() } << " Invalid floating point value, expected exponent digit\n";
|
||||
state = State::Value;
|
||||
}
|
||||
break;
|
||||
|
||||
case State::Value:
|
||||
if (not is_non_blank(ch))
|
||||
{
|
||||
retract();
|
||||
result = CIFToken::VALUE;
|
||||
result = CIFToken::VALUE_CHARSTRING;
|
||||
m_token_value = std::string_view(m_token_buffer.data(), m_token_buffer.size());
|
||||
break;
|
||||
}
|
||||
@@ -480,12 +549,25 @@ sac_parser::CIFToken sac_parser::get_next_token()
|
||||
}
|
||||
}
|
||||
|
||||
if (VERBOSE >= 5)
|
||||
// if (VERBOSE >= 5)
|
||||
// {
|
||||
// std::cerr << get_token_name(result);
|
||||
// if (result != CIFToken::END_OF_FILE)
|
||||
// std::cerr << " " << std::quoted(m_token_value);
|
||||
// std::cerr << '\n';
|
||||
// }
|
||||
|
||||
if (result == CIFToken::VALUE_NUMERIC_INTEGER)
|
||||
{
|
||||
std::cerr << get_token_name(result);
|
||||
if (result != CIFToken::END_OF_FILE)
|
||||
std::cerr << " " << std::quoted(m_token_value);
|
||||
std::cerr << '\n';
|
||||
auto [ptr, ec] = std::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)
|
||||
{
|
||||
auto [ptr, ec] = std::from_chars(m_token_buffer.data(), m_token_buffer.data() + m_token_buffer.size(), m_token_value_float);
|
||||
if (ec != std::errc{})
|
||||
error("Invalid integer value: " + std::make_error_code(ec).message());
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -661,7 +743,7 @@ sac_parser::datablock_index sac_parser::index_datablocks()
|
||||
case data:
|
||||
if (dblk[si] == 0 and is_non_blank(ch))
|
||||
{
|
||||
datablock = {static_cast<char>(ch)};
|
||||
datablock = { static_cast<char>(ch) };
|
||||
state = data_name;
|
||||
}
|
||||
else if (dblk[si++] != ch)
|
||||
@@ -738,14 +820,17 @@ void sac_parser::parse_global()
|
||||
while (m_lookahead == CIFToken::ITEM_NAME)
|
||||
{
|
||||
match(CIFToken::ITEM_NAME);
|
||||
match(CIFToken::VALUE);
|
||||
if (m_lookahead >= CIFToken::VALUE_INAPPLICABLE)
|
||||
match(m_lookahead);
|
||||
else
|
||||
match(CIFToken::VALUE_CHARSTRING);
|
||||
}
|
||||
}
|
||||
|
||||
void sac_parser::parse_datablock()
|
||||
{
|
||||
static const std::string kUnitializedCategory("<invalid>");
|
||||
std::string cat = kUnitializedCategory; // intial value acts as a guard for empty category names
|
||||
std::string cat = kUnitializedCategory; // intial value acts as a guard for empty category names
|
||||
|
||||
while (m_lookahead == CIFToken::LOOP or m_lookahead == CIFToken::ITEM_NAME or m_lookahead == CIFToken::SAVE_NAME)
|
||||
{
|
||||
@@ -777,14 +862,38 @@ void sac_parser::parse_datablock()
|
||||
match(CIFToken::ITEM_NAME);
|
||||
}
|
||||
|
||||
while (m_lookahead == CIFToken::VALUE)
|
||||
while (m_lookahead >= CIFToken::VALUE_INAPPLICABLE)
|
||||
{
|
||||
produce_row();
|
||||
|
||||
for (auto item_name : item_names)
|
||||
{
|
||||
produce_item(cat, item_name, m_token_value);
|
||||
match(CIFToken::VALUE);
|
||||
switch (m_lookahead)
|
||||
{
|
||||
case CIFToken::VALUE_INAPPLICABLE:
|
||||
produce_item(cat, item_name, nullptr);
|
||||
match(m_lookahead);
|
||||
break;
|
||||
case CIFToken::VALUE_UNKNOWN:
|
||||
produce_item(cat, item_name, std::optional<std::string>{});
|
||||
match(m_lookahead);
|
||||
break;
|
||||
case CIFToken::VALUE_NUMERIC_INTEGER:
|
||||
produce_item(cat, item_name, m_token_value_int);
|
||||
match(m_lookahead);
|
||||
break;
|
||||
case CIFToken::VALUE_NUMERIC_FLOAT:
|
||||
produce_item(cat, item_name, m_token_value_float);
|
||||
match(m_lookahead);
|
||||
break;
|
||||
case CIFToken::VALUE_CHARSTRING:
|
||||
case CIFToken::VALUE_TEXTFIELD:
|
||||
produce_item(cat, item_name, m_token_value);
|
||||
match(m_lookahead);
|
||||
break;
|
||||
default:;
|
||||
match(CIFToken::VALUE_CHARSTRING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -806,9 +915,33 @@ void sac_parser::parse_datablock()
|
||||
|
||||
match(CIFToken::ITEM_NAME);
|
||||
|
||||
produce_item(cat, itemName, m_token_value);
|
||||
switch (m_lookahead)
|
||||
{
|
||||
case CIFToken::VALUE_INAPPLICABLE:
|
||||
produce_item(cat, itemName, nullptr);
|
||||
match(CIFToken::VALUE_INAPPLICABLE);
|
||||
break;
|
||||
case CIFToken::VALUE_UNKNOWN:
|
||||
produce_item(cat, itemName, item_value{ std::optional<std::string>{} });
|
||||
match(CIFToken::VALUE_UNKNOWN);
|
||||
break;
|
||||
case CIFToken::VALUE_NUMERIC_INTEGER:
|
||||
produce_item(cat, itemName, m_token_value_int);
|
||||
match(CIFToken::VALUE_NUMERIC_INTEGER);
|
||||
break;
|
||||
case CIFToken::VALUE_NUMERIC_FLOAT:
|
||||
produce_item(cat, itemName, m_token_value_float);
|
||||
match(CIFToken::VALUE_NUMERIC_FLOAT);
|
||||
break;
|
||||
case CIFToken::VALUE_CHARSTRING:
|
||||
case CIFToken::VALUE_TEXTFIELD:
|
||||
produce_item(cat, itemName, m_token_value);
|
||||
match(m_lookahead);
|
||||
break;
|
||||
default:
|
||||
match(CIFToken::VALUE_CHARSTRING);
|
||||
}
|
||||
|
||||
match(CIFToken::VALUE);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -864,7 +997,7 @@ void parser::produce_row()
|
||||
// m_row.lineNr(m_line_nr);
|
||||
}
|
||||
|
||||
void parser::produce_item(std::string_view category, std::string_view item, std::string_view value)
|
||||
void parser::produce_item(std::string_view category, std::string_view item, item_value value)
|
||||
{
|
||||
if (VERBOSE >= 4)
|
||||
std::cerr << "producing _" << category << '.' << item << " -> " << value << '\n';
|
||||
@@ -872,7 +1005,7 @@ void parser::produce_item(std::string_view category, std::string_view item, std:
|
||||
if (m_category == nullptr or not iequals(category, m_category->name()))
|
||||
error("inconsistent categories in loop_");
|
||||
|
||||
m_row[item] = m_token_value;
|
||||
m_row[item] = std::move(value);
|
||||
}
|
||||
|
||||
} // namespace cif
|
||||
|
||||
52
src/row.cpp
52
src/row.cpp
@@ -24,17 +24,50 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "cif++/row.hpp"
|
||||
|
||||
#include "cif++/category.hpp"
|
||||
#include "cif++/item.hpp"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace cif
|
||||
{
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void row_handle::assign(uint16_t item, std::string_view value, bool updateLinked, bool validate)
|
||||
item_value s_null_item;
|
||||
|
||||
item_value &row_handle::operator[](uint16_t item_ix)
|
||||
{
|
||||
return empty() or item_ix >= m_row->size() ? s_null_item : m_row->operator[](item_ix);
|
||||
}
|
||||
|
||||
const item_value &row_handle::operator[](uint16_t item_ix) const
|
||||
{
|
||||
return empty() or item_ix >= m_row->size() ? s_null_item : m_row->operator[](item_ix);
|
||||
}
|
||||
|
||||
item_value &row_handle::operator[](std::string_view item_name)
|
||||
{
|
||||
auto ix = add_item(item_name);
|
||||
if (ix >= size())
|
||||
m_row->resize(ix + 1);
|
||||
|
||||
return m_row->operator[](ix);
|
||||
}
|
||||
|
||||
const item_value &row_handle::operator[](std::string_view item_name) const
|
||||
{
|
||||
return operator[](get_item_ix(item_name));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void row_handle::assign(uint16_t item, item_value value, bool updateLinked, bool validate)
|
||||
{
|
||||
if (not m_category)
|
||||
throw std::runtime_error("uninitialized row");
|
||||
|
||||
m_category->update_value(m_row, item, value, updateLinked, validate);
|
||||
m_category->update_value(m_row, item, std::move(value), updateLinked, validate);
|
||||
}
|
||||
|
||||
uint16_t row_handle::get_item_ix(std::string_view name) const
|
||||
@@ -86,28 +119,29 @@ row_initializer::row_initializer(row_handle rh)
|
||||
auto &i = r->operator[](ix);
|
||||
if (not i)
|
||||
continue;
|
||||
emplace_back(cat.get_item_name(ix), i.text());
|
||||
emplace_back(cat.get_item_name(ix), i);
|
||||
}
|
||||
}
|
||||
|
||||
void row_initializer::set_value(std::string_view name, std::string_view value)
|
||||
void row_initializer::set_value(std::string name, item_value value)
|
||||
{
|
||||
for (auto &i : *this)
|
||||
{
|
||||
if (i.name() == name)
|
||||
{
|
||||
i.value(value);
|
||||
i.value(std::move(value));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
emplace_back(name, value);
|
||||
emplace_back(std::move(name), std::move(value));
|
||||
}
|
||||
|
||||
void row_initializer::set_value_if_empty(std::string_view name, std::string_view value)
|
||||
void row_initializer::set_value_if_empty(std::string name, item_value value)
|
||||
{
|
||||
if (find_if(begin(), end(), [name](auto &i) { return i.name() == name; }) == end())
|
||||
emplace_back(name, value);
|
||||
if (std::ranges::find_if(*this, [name](auto &i)
|
||||
{ return i.name() == name; }) == end())
|
||||
emplace_back(std::move(name), std::move(value));
|
||||
}
|
||||
|
||||
} // namespace cif
|
||||
@@ -263,24 +263,24 @@ int type_validator::compare(std::string_view a, std::string_view b) const
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void item_validator::operator()(std::string_view value) const
|
||||
void item_validator::operator()(const item_value &value) const
|
||||
{
|
||||
std::error_code ec;
|
||||
if (not validate_value(value, ec))
|
||||
throw std::system_error(ec, std::string{ value } + " does not match rx for " + m_item_name);
|
||||
// std::error_code ec;
|
||||
// if (not validate_value(value, ec))
|
||||
// throw std::system_error(ec, std::string{ value } + " does not match rx for " + m_item_name);
|
||||
}
|
||||
|
||||
bool item_validator::validate_value(std::string_view value, std::error_code &ec) const noexcept
|
||||
bool item_validator::validate_value(const item_value &value, std::error_code &ec) const noexcept
|
||||
{
|
||||
ec.clear();
|
||||
|
||||
if (not value.empty() and value != "?" and value != ".")
|
||||
{
|
||||
if (m_type != nullptr and not m_type->m_rx->match(value))
|
||||
ec = make_error_code(validation_error::value_does_not_match_rx);
|
||||
else if (not m_enums.empty() and m_enums.count(std::string{ value }) == 0)
|
||||
ec = make_error_code(validation_error::value_is_not_in_enumeration_list);
|
||||
}
|
||||
// if (not value.empty() and value != "?" and value != ".")
|
||||
// {
|
||||
// if (m_type != nullptr and not m_type->m_rx->match(value))
|
||||
// ec = make_error_code(validation_error::value_does_not_match_rx);
|
||||
// else if (not m_enums.empty() and m_enums.count(std::string{ value }) == 0)
|
||||
// ec = make_error_code(validation_error::value_is_not_in_enumeration_list);
|
||||
// }
|
||||
|
||||
return not(bool) ec;
|
||||
}
|
||||
|
||||
@@ -41,15 +41,15 @@ list(
|
||||
APPEND
|
||||
CIFPP_tests
|
||||
unit-v2
|
||||
unit-3d
|
||||
model
|
||||
query
|
||||
rename-compound
|
||||
sugar
|
||||
spinner
|
||||
reconstruction
|
||||
validate-pdbx
|
||||
matrix
|
||||
# unit-3d
|
||||
# model
|
||||
# query
|
||||
# rename-compound
|
||||
# sugar
|
||||
# spinner
|
||||
# reconstruction
|
||||
# validate-pdbx
|
||||
# matrix
|
||||
)
|
||||
|
||||
add_library(test-main OBJECT "${CMAKE_CURRENT_SOURCE_DIR}/test-main.cpp")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "test-main.hpp"
|
||||
|
||||
#include <cif++.hpp>
|
||||
#include <cif++/utilities.hpp>
|
||||
|
||||
std::filesystem::path gTestDir = std::filesystem::current_path();
|
||||
|
||||
@@ -33,7 +33,7 @@ int main(int argc, char *argv[])
|
||||
// initialize CCD location
|
||||
cif::add_file_resource("components.cif", gTestDir / ".." / "rsrc" / "ccd-subset.cif");
|
||||
|
||||
cif::compound_factory::instance().push_dictionary(gTestDir / "HEM.cif");
|
||||
// cif::compound_factory::instance().push_dictionary(gTestDir / "HEM.cif");
|
||||
|
||||
return session.run();
|
||||
}
|
||||
@@ -24,10 +24,18 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "cif++/category.hpp"
|
||||
#include "test-main.hpp"
|
||||
|
||||
#include <cif++.hpp>
|
||||
|
||||
// #include <cif++.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <cif++/item.hpp>
|
||||
#include <cif++/category.hpp>
|
||||
#include <cif++/datablock.hpp>
|
||||
#include <cif++/file.hpp>
|
||||
#include <cif++/row.hpp>
|
||||
#include <cif++/validate.hpp>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -51,41 +59,41 @@ cif::file operator""_cf(const char *text, std::size_t length)
|
||||
TEST_CASE("text_1")
|
||||
{
|
||||
CHECK(cif::iequals("TEST", "test"));
|
||||
CHECK(cif::iequals(std::string_view{"TEST"}, std::string_view{"test"}));
|
||||
CHECK(cif::iequals(std::string_view{ "TEST" }, std::string_view{ "test" }));
|
||||
|
||||
CHECK(cif::icompare("TEST", "test") == 0);
|
||||
CHECK(cif::icompare(std::string_view{"TEST"}, std::string_view{"test"}) == 0);
|
||||
CHECK(cif::icompare(std::string_view{ "TEST" }, std::string_view{ "test" }) == 0);
|
||||
|
||||
CHECK(cif::icompare("TEST1", "test") > 0);
|
||||
CHECK(cif::icompare(std::string_view{"TEST1"}, std::string_view{"test"}) > 0);
|
||||
CHECK(cif::icompare(std::string_view{ "TEST1" }, std::string_view{ "test" }) > 0);
|
||||
|
||||
CHECK(cif::icompare("aap", "noot") < 0);
|
||||
CHECK(cif::icompare(std::string_view{"aap"}, std::string_view{"noot"}) < 0);
|
||||
CHECK(cif::icompare(std::string_view{ "aap" }, std::string_view{ "noot" }) < 0);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// // --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("from_chars_1")
|
||||
{
|
||||
auto f = R"(data_TEST
|
||||
#
|
||||
loop_
|
||||
_test.v
|
||||
616.487
|
||||
616.487000
|
||||
)"_cf;
|
||||
// TEST_CASE("from_chars_1")
|
||||
// {
|
||||
// auto f = R"(data_TEST
|
||||
// #
|
||||
// loop_
|
||||
// _test.v
|
||||
// 616.487
|
||||
// 616.487000
|
||||
// )"_cf;
|
||||
|
||||
auto &db = f.front();
|
||||
auto &c = db.front();
|
||||
// auto &db = f.front();
|
||||
// auto &c = db.front();
|
||||
|
||||
auto r1 = c.front();
|
||||
CHECK(r1.get<double>("v") == 616.487);
|
||||
CHECK(r1["v"].compare(616.487) == 0);
|
||||
// auto r1 = c.front();
|
||||
// CHECK(r1.get<double>("v") == 616.487);
|
||||
// CHECK(r1["v"].compare(616.487) == 0);
|
||||
|
||||
auto r2 = c.back();
|
||||
CHECK(r2.get<double>("v") == 616.487);
|
||||
CHECK(r2["v"].compare(616.487) == 0);
|
||||
}
|
||||
// auto r2 = c.back();
|
||||
// CHECK(r2.get<double>("v") == 616.487);
|
||||
// CHECK(r2["v"].compare(616.487) == 0);
|
||||
// }
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -162,33 +170,84 @@ TEST_CASE("cc_2")
|
||||
|
||||
// This line generates a linker error on Windows:
|
||||
// CHECK(buffer == test);
|
||||
CHECK(std::string{ buffer } == std::string { test });
|
||||
CHECK(std::string{ buffer } == std::string{ test });
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("item_0")
|
||||
{
|
||||
cif::item i1("v1", "tekst");
|
||||
cif::item i2("v2", 2);
|
||||
cif::item i3("v3", 3.0);
|
||||
cif::item i4("v4", true);
|
||||
cif::item i5("v5", nullptr);
|
||||
|
||||
static_assert(cif::IntegralType<int>);
|
||||
static_assert(cif::FloatType<double>);
|
||||
|
||||
CHECK(i1.value().get<std::string>() == "tekst");
|
||||
CHECK(i2.value().get<int>() == 2);
|
||||
CHECK(i3.value().get<double>() == 3.0);
|
||||
CHECK(i4.value().get<bool>() == true);
|
||||
CHECK(i5.value().is_empty());
|
||||
|
||||
i2.value() = false;
|
||||
CHECK(i2.value().type() == cif::item_value_type::BOOLEAN);
|
||||
CHECK(i2.value().get<bool>() == false);
|
||||
|
||||
cif::item i6 = std::move(i1);
|
||||
CHECK(i6.value().get<std::string>() == "tekst");
|
||||
CHECK(i1.value().is_empty());
|
||||
}
|
||||
|
||||
TEST_CASE("row_1")
|
||||
{
|
||||
cif::row r;
|
||||
|
||||
r.append(0, 1);
|
||||
r.append(1, "twee");
|
||||
|
||||
cif::category cat("cat");
|
||||
|
||||
cat.add_item("een");
|
||||
cat.add_item("twee");
|
||||
|
||||
cif::row_handle rh(cat, r);
|
||||
|
||||
const auto &[a, b] = rh.get<int, std::string>("een", "twee");
|
||||
CHECK(a == 1);
|
||||
CHECK(b == "twee");
|
||||
|
||||
rh.assign("twee", 3.0, false);
|
||||
CHECK(rh[1].type() == cif::item_value_type::FLOAT);
|
||||
CHECK(rh[1].get<double>() == 3.0);
|
||||
}
|
||||
|
||||
TEST_CASE("cc_3")
|
||||
{
|
||||
cif::category c("foo");
|
||||
c.emplace({
|
||||
{ "f-1", 1 },
|
||||
{ "f-2", "-1" },
|
||||
{ "f-3", "+1" },
|
||||
{ "f-4", " 1" },
|
||||
{ "f-5", " +1" },
|
||||
{ "f-6", "1 " },
|
||||
});
|
||||
|
||||
cif::row_initializer ri{
|
||||
{
|
||||
{ "f-1", 1 },
|
||||
{ "f-2", "-1" },
|
||||
{ "f-3", "+1" },
|
||||
{ "f-4", " 1" },
|
||||
{ "f-5", " +1" },
|
||||
{ "f-6", "1 " },
|
||||
}
|
||||
};
|
||||
|
||||
c.emplace(std::move(ri));
|
||||
|
||||
auto row = c.front();
|
||||
CHECK(row["f-1"].as<int>() == 1);
|
||||
CHECK(row["f-2"].as<int>() == -1);
|
||||
CHECK(row["f-3"].as<int>() == 1);
|
||||
CHECK(row["f-1"].get<int>() == 1);
|
||||
CHECK(row["f-2"].get<int>() == -1);
|
||||
|
||||
// CHECK_THROWS_AS(row["f-4"].as<int>(), std::exception);
|
||||
// CHECK_THROWS_AS(row["f-5"].as<int>(), std::exception);
|
||||
// CHECK_THROWS_AS(row["f-6"].as<int>(), std::exception);
|
||||
CHECK(row["f-4"].as<int>() == 0);
|
||||
CHECK(row["f-5"].as<int>() == 0);
|
||||
CHECK(row["f-6"].as<int>() == 0);
|
||||
CHECK_FALSE(row["f-3"].is_number());
|
||||
CHECK_FALSE(row["f-4"].is_number());
|
||||
CHECK_FALSE(row["f-5"].is_number());
|
||||
CHECK_FALSE(row["f-6"].is_number());
|
||||
}
|
||||
|
||||
TEST_CASE("item_1")
|
||||
@@ -225,19 +284,21 @@ TEST_CASE("item_2")
|
||||
using namespace cif;
|
||||
|
||||
cif::item i0("test1");
|
||||
CHECK(i0.value() == ".");
|
||||
CHECK(i0.value().is_empty());
|
||||
CHECK(i0.value().type() == cif::item_value_type::EMPTY);
|
||||
|
||||
cif::item i1("test1", std:: optional<float>());
|
||||
CHECK(i1.value() == "?");
|
||||
cif::item i1("test1", std::optional<float>());
|
||||
CHECK(i0.value().is_empty());
|
||||
// CHECK(i1.value() == "?");
|
||||
|
||||
cif::item i2("test1", std::make_optional<float>(1.f));
|
||||
CHECK(i2.value() == "1");
|
||||
// CHECK(i2.value() == "1");
|
||||
|
||||
cif::item i3("test1", std::optional<float>(), 2);
|
||||
CHECK(i3.value() == "?");
|
||||
// cif::item i3("test1", std::optional<float>(), 2);
|
||||
// CHECK(i3.value() == "?");
|
||||
|
||||
cif::item i4("test1", std::make_optional<float>(1.f), 2);
|
||||
CHECK(i4.value() == "1.00");
|
||||
// cif::item i4("test1", std::make_optional<float>(1.f), 2);
|
||||
// CHECK(i4.value() == "1.00");
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -248,13 +309,13 @@ TEST_CASE("r_1")
|
||||
c.emplace({
|
||||
{ "f-1", 1 },
|
||||
{ "f-2", "two" },
|
||||
{ "f-3", 3.0f, 3 },
|
||||
{ "f-3", 3.0f/* , 3 */ },
|
||||
});
|
||||
|
||||
auto row = c.front();
|
||||
CHECK(row["f-1"].compare(1) == 0);
|
||||
CHECK(row["f-2"].compare("two") == 0);
|
||||
CHECK(row["f-3"].compare(3.0f) == 0); // This fails when running in valgrind... sigh
|
||||
// CHECK(row["f-1"].compare(1) == 0);
|
||||
// CHECK(row["f-2"].compare("two") == 0);
|
||||
// CHECK(row["f-3"].compare(3.0f) == 0); // This fails when running in valgrind... sigh
|
||||
|
||||
const auto &[f1, f2, f3] = row.get<int, std::string, float>("f-1", "f-2", "f-3");
|
||||
|
||||
@@ -302,7 +363,7 @@ TEST_CASE("c_1")
|
||||
|
||||
for (auto r : c)
|
||||
{
|
||||
CHECK(r["id"].as<int>() == n);
|
||||
CHECK(r["id"].get<int>() == n);
|
||||
CHECK(r["s"].compare(ts[n - 1]) == 0);
|
||||
++n;
|
||||
}
|
||||
@@ -413,36 +474,36 @@ TEST_CASE("ci_1")
|
||||
CHECK(i1 == i5);
|
||||
}
|
||||
|
||||
TEST_CASE("os_1")
|
||||
{
|
||||
using namespace cif::literals;
|
||||
using namespace std::literals;
|
||||
// TEST_CASE("os_1")
|
||||
// {
|
||||
// using namespace cif::literals;
|
||||
// using namespace std::literals;
|
||||
|
||||
std::tuple<int, const char *> D[] = {
|
||||
{ 1, "aap" },
|
||||
{ 2, "noot" },
|
||||
{ 3, "mies" }
|
||||
};
|
||||
// std::tuple<int, const char *> D[] = {
|
||||
// { 1, "aap" },
|
||||
// { 2, "noot" },
|
||||
// { 3, "mies" }
|
||||
// };
|
||||
|
||||
cif::category c("foo");
|
||||
// cif::category c("foo");
|
||||
|
||||
for (const auto &[id, s] : D)
|
||||
c.emplace({ { "id", id }, { "s", s } });
|
||||
// for (const auto &[id, s] : D)
|
||||
// c.emplace({ { "id", id }, { "s", s } });
|
||||
|
||||
for (auto rh : c)
|
||||
{
|
||||
rh["o"].os(1, ',', 2, ": ", rh.get<std::string>("s"));
|
||||
}
|
||||
// for (auto rh : c)
|
||||
// {
|
||||
// rh["o"].os(1, ',', 2, ": ", rh.get<std::string>("s"));
|
||||
// }
|
||||
|
||||
for (const auto &[id, s] : D)
|
||||
{
|
||||
auto rh = c.find1("id"_key == id);
|
||||
// for (const auto &[id, s] : D)
|
||||
// {
|
||||
// auto rh = c.find1("id"_key == id);
|
||||
|
||||
CHECK(rh.get<int>("id") == id);
|
||||
CHECK(rh.get<std::string>("s") == s);
|
||||
CHECK(rh.get<std::string>("o") == "1,2: "s + s);
|
||||
}
|
||||
}
|
||||
// CHECK(rh.get<int>("id") == id);
|
||||
// CHECK(rh.get<std::string>("s") == s);
|
||||
// CHECK(rh.get<std::string>("o") == "1,2: "s + s);
|
||||
// }
|
||||
// }
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -460,6 +521,13 @@ _test.name
|
||||
5 .
|
||||
)"_cf;
|
||||
|
||||
REQUIRE(f.size() == 1);
|
||||
REQUIRE(f.contains("TEST"));
|
||||
REQUIRE(f.front().size() == 1);
|
||||
REQUIRE(f.front().contains("test"));
|
||||
REQUIRE(f.front()["test"].size() == 5);
|
||||
REQUIRE(f.front()["test"].front().size() == 2);
|
||||
|
||||
for (auto r : f.front()["test"])
|
||||
{
|
||||
int id;
|
||||
@@ -472,7 +540,9 @@ _test.name
|
||||
case 1: CHECK(*name == "aap"); break;
|
||||
case 2: CHECK(*name == "noot"); break;
|
||||
case 3: CHECK(*name == "mies"); break;
|
||||
default: CHECK(name.has_value() == false);
|
||||
case 4:
|
||||
case 5: CHECK_FALSE(name.has_value());break;
|
||||
default: CHECK(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -515,8 +585,8 @@ _test.name
|
||||
|
||||
auto n2 = test.erase(cif::key("id") == 1, [](cif::row_handle r)
|
||||
{
|
||||
CHECK(r["id"].as<int>() == 1);
|
||||
CHECK(r["name"].as<std::string>() == "aap"); });
|
||||
CHECK(r["id"].get<int>() == 1);
|
||||
CHECK(r["name"].get<std::string>() == "aap"); });
|
||||
|
||||
CHECK(n2 == 1);
|
||||
|
||||
@@ -569,18 +639,18 @@ _test.value
|
||||
for (auto r : test.find(cif::key("name") == "aap"))
|
||||
{
|
||||
CHECK(++n == 1);
|
||||
CHECK(r["id"].as<int>() == 1);
|
||||
CHECK(r["name"].as<std::string>() == "aap");
|
||||
CHECK(r["value"].as<float>() == 1.0f);
|
||||
CHECK(r["id"].get<int>() == 1);
|
||||
CHECK(r["name"].get<std::string>() == "aap");
|
||||
CHECK(r["value"].get<float>() == 1.0f);
|
||||
}
|
||||
|
||||
auto t = test.find(cif::key("id") == 1);
|
||||
CHECK(not t.empty());
|
||||
CHECK(t.front()["name"].as<std::string>() == "aap");
|
||||
REQUIRE(not t.empty());
|
||||
CHECK(t.front()["name"].get<std::string>() == "aap");
|
||||
|
||||
auto t2 = test.find(cif::key("value") == 1.2);
|
||||
CHECK(not t2.empty());
|
||||
CHECK(t2.front()["name"].as<std::string>() == "mies");
|
||||
REQUIRE(not t2.empty());
|
||||
CHECK(t2.front()["name"].get<std::string>() == "mies");
|
||||
}
|
||||
|
||||
TEST_CASE("ut3")
|
||||
@@ -1554,9 +1624,9 @@ _cat_2.parent_id3
|
||||
// check iterate children
|
||||
|
||||
auto PR2set = cat1.find(cif::key("id") == 2);
|
||||
CHECK(PR2set.size() == 1);
|
||||
REQUIRE(PR2set.size() == 1);
|
||||
auto PR2 = PR2set.front();
|
||||
CHECK(PR2["id"].as<int>() == 2);
|
||||
CHECK(PR2["id"].get<int>() == 2);
|
||||
|
||||
auto CR2set = cat1.get_children(PR2, cat2);
|
||||
CHECK(CR2set.size() == 3);
|
||||
@@ -1564,7 +1634,7 @@ _cat_2.parent_id3
|
||||
|
||||
std::vector<int> CRids;
|
||||
std::transform(CR2set.begin(), CR2set.end(), std::back_inserter(CRids), [](cif::row_handle r)
|
||||
{ return r["id"].as<int>(); });
|
||||
{ return r["id"].get<int>(); });
|
||||
std::sort(CRids.begin(), CRids.end());
|
||||
CHECK(CRids == std::vector<int>({ 4, 5, 6 }));
|
||||
|
||||
@@ -3099,7 +3169,6 @@ data_test_dict.dic
|
||||
or positive integers.
|
||||
;
|
||||
|
||||
|
||||
###################
|
||||
## AUDIT_CONFORM ##
|
||||
###################
|
||||
@@ -3176,7 +3245,6 @@ save__audit_conform.dict_version
|
||||
_item_type.code text
|
||||
save_
|
||||
|
||||
|
||||
save_cat_1
|
||||
_category.description 'A simple test category'
|
||||
_category.id cat_1
|
||||
@@ -3256,8 +3324,8 @@ _cat_1.name
|
||||
CHECK(f2.is_valid());
|
||||
|
||||
auto &audit_conform = f2.front()["audit_conform"];
|
||||
CHECK(audit_conform.front()["dict_name"].as<std::string>() == "test_dict.dic");
|
||||
CHECK(audit_conform.front()["dict_version"].as<float>() == 1.0);
|
||||
CHECK(audit_conform.front()["dict_name"].get<std::string>() == "test_dict.dic");
|
||||
CHECK(audit_conform.front()["dict_version"].get<float>() == 1.0);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -3442,8 +3510,8 @@ _date today
|
||||
CHECK(not cat.empty());
|
||||
|
||||
auto r = cat.front();
|
||||
CHECK(r["version"].as<std::string>() == "1.0");
|
||||
CHECK(r["date"].as<std::string>() == "today");
|
||||
CHECK(r["version"].get<std::string>() == "1.0");
|
||||
CHECK(r["date"].get<std::string>() == "today");
|
||||
|
||||
std::stringstream ss;
|
||||
ss << db;
|
||||
@@ -3481,92 +3549,92 @@ _test.value
|
||||
CHECK(v.has_value() == false);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// // --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("compound_test_1")
|
||||
{
|
||||
cif::compound_factory::instance().push_dictionary(gTestDir / "REA_v2.cif");
|
||||
auto compound = cif::compound_factory::instance().create("REA_v2");
|
||||
CHECK(compound != nullptr);
|
||||
CHECK(cif::iequals(compound->id(), "REA_v2"));
|
||||
}
|
||||
// TEST_CASE("compound_test_1")
|
||||
// {
|
||||
// cif::compound_factory::instance().push_dictionary(gTestDir / "REA_v2.cif");
|
||||
// auto compound = cif::compound_factory::instance().create("REA_v2");
|
||||
// CHECK(compound != nullptr);
|
||||
// CHECK(cif::iequals(compound->id(), "REA_v2"));
|
||||
// }
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// // --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("pdb_parser_test_1")
|
||||
{
|
||||
char k1CBS[] = R"(HEADER RETINOIC-ACID TRANSPORT 28-SEP-94 1CBS
|
||||
TITLE CRYSTAL STRUCTURE OF CELLULAR RETINOIC-ACID-BINDING
|
||||
TITLE 2 PROTEINS I AND II IN COMPLEX WITH ALL-TRANS-RETINOIC ACID
|
||||
TITLE 3 AND A SYNTHETIC RETINOID
|
||||
COMPND MOL_ID: 1;
|
||||
COMPND 2 MOLECULE: CELLULAR RETINOIC ACID BINDING PROTEIN TYPE II;
|
||||
COMPND 3 CHAIN: A;
|
||||
COMPND 4 ENGINEERED: YES
|
||||
SOURCE MOL_ID: 1;
|
||||
SOURCE 2 ORGANISM_SCIENTIFIC: HOMO SAPIENS;
|
||||
SOURCE 3 ORGANISM_COMMON: HUMAN;
|
||||
SOURCE 4 ORGANISM_TAXID: 9606;
|
||||
SOURCE 5 CELL_LINE: BL21;
|
||||
SOURCE 6 GENE: HUMAN CRABP-II;
|
||||
SOURCE 7 EXPRESSION_SYSTEM: ESCHERICHIA COLI BL21(DE3);
|
||||
SOURCE 8 EXPRESSION_SYSTEM_TAXID: 469008;
|
||||
SOURCE 9 EXPRESSION_SYSTEM_STRAIN: BL21 (DE3);
|
||||
SOURCE 10 EXPRESSION_SYSTEM_PLASMID: PET-3A
|
||||
KEYWDS RETINOIC-ACID TRANSPORT
|
||||
EXPDTA X-RAY DIFFRACTION
|
||||
AUTHOR G.J.KLEYWEGT,T.BERGFORS,T.A.JONES
|
||||
ATOM 1 N PRO A 1 16.979 13.301 44.555 1.00 30.05 N
|
||||
ATOM 2 CA PRO A 1 18.150 13.525 43.680 1.00 28.82 C
|
||||
ATOM 3 C PRO A 1 18.656 14.966 43.784 1.00 26.59 C
|
||||
ATOM 4 O PRO A 1 17.890 15.889 44.078 1.00 26.84 O
|
||||
ATOM 5 CB PRO A 1 17.678 13.270 42.255 1.00 29.24 C
|
||||
ATOM 6 CG PRO A 1 16.248 13.734 42.347 1.00 29.29 C
|
||||
ATOM 7 CD PRO A 1 15.762 13.216 43.724 1.00 30.71 C)";
|
||||
// TEST_CASE("pdb_parser_test_1")
|
||||
// {
|
||||
// char k1CBS[] = R"(HEADER RETINOIC-ACID TRANSPORT 28-SEP-94 1CBS
|
||||
// TITLE CRYSTAL STRUCTURE OF CELLULAR RETINOIC-ACID-BINDING
|
||||
// TITLE 2 PROTEINS I AND II IN COMPLEX WITH ALL-TRANS-RETINOIC ACID
|
||||
// TITLE 3 AND A SYNTHETIC RETINOID
|
||||
// COMPND MOL_ID: 1;
|
||||
// COMPND 2 MOLECULE: CELLULAR RETINOIC ACID BINDING PROTEIN TYPE II;
|
||||
// COMPND 3 CHAIN: A;
|
||||
// COMPND 4 ENGINEERED: YES
|
||||
// SOURCE MOL_ID: 1;
|
||||
// SOURCE 2 ORGANISM_SCIENTIFIC: HOMO SAPIENS;
|
||||
// SOURCE 3 ORGANISM_COMMON: HUMAN;
|
||||
// SOURCE 4 ORGANISM_TAXID: 9606;
|
||||
// SOURCE 5 CELL_LINE: BL21;
|
||||
// SOURCE 6 GENE: HUMAN CRABP-II;
|
||||
// SOURCE 7 EXPRESSION_SYSTEM: ESCHERICHIA COLI BL21(DE3);
|
||||
// SOURCE 8 EXPRESSION_SYSTEM_TAXID: 469008;
|
||||
// SOURCE 9 EXPRESSION_SYSTEM_STRAIN: BL21 (DE3);
|
||||
// SOURCE 10 EXPRESSION_SYSTEM_PLASMID: PET-3A
|
||||
// KEYWDS RETINOIC-ACID TRANSPORT
|
||||
// EXPDTA X-RAY DIFFRACTION
|
||||
// AUTHOR G.J.KLEYWEGT,T.BERGFORS,T.A.JONES
|
||||
// ATOM 1 N PRO A 1 16.979 13.301 44.555 1.00 30.05 N
|
||||
// ATOM 2 CA PRO A 1 18.150 13.525 43.680 1.00 28.82 C
|
||||
// ATOM 3 C PRO A 1 18.656 14.966 43.784 1.00 26.59 C
|
||||
// ATOM 4 O PRO A 1 17.890 15.889 44.078 1.00 26.84 O
|
||||
// ATOM 5 CB PRO A 1 17.678 13.270 42.255 1.00 29.24 C
|
||||
// ATOM 6 CG PRO A 1 16.248 13.734 42.347 1.00 29.29 C
|
||||
// ATOM 7 CD PRO A 1 15.762 13.216 43.724 1.00 30.71 C)";
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
} buffer(k1CBS, sizeof(k1CBS) - 1);
|
||||
// struct membuf : public std::streambuf
|
||||
// {
|
||||
// membuf(char *text, std::size_t length)
|
||||
// {
|
||||
// this->setg(text, text, text + length);
|
||||
// }
|
||||
// } buffer(k1CBS, sizeof(k1CBS) - 1);
|
||||
|
||||
std::istream is(&buffer);
|
||||
// std::istream is(&buffer);
|
||||
|
||||
auto f = cif::pdb::read(is);
|
||||
}
|
||||
// auto f = cif::pdb::read(is);
|
||||
// }
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// // --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("compound_not_found_test_1")
|
||||
{
|
||||
auto cmp = cif::compound_factory::instance().create("&&&");
|
||||
CHECK(cmp == nullptr);
|
||||
}
|
||||
// TEST_CASE("compound_not_found_test_1")
|
||||
// {
|
||||
// auto cmp = cif::compound_factory::instance().create("&&&");
|
||||
// CHECK(cmp == nullptr);
|
||||
// }
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// PDB2CIF tests
|
||||
// // --------------------------------------------------------------------
|
||||
// // PDB2CIF tests
|
||||
|
||||
TEST_CASE("pdb2cif_formula_weight")
|
||||
{
|
||||
cif::compound_factory::instance().push_dictionary(gTestDir / "REA.cif");
|
||||
// TEST_CASE("pdb2cif_formula_weight")
|
||||
// {
|
||||
// cif::compound_factory::instance().push_dictionary(gTestDir / "REA.cif");
|
||||
|
||||
cif::file a = cif::pdb::read(gTestDir / "pdb1cbs.ent.gz");
|
||||
|
||||
auto fw = a.front()["entity"].find1<float>(cif::key("id") == 1, "formula_weight");
|
||||
CHECK(std::abs(fw - 15581.802f) < 0.1f);
|
||||
// cif::file a = cif::pdb::read(gTestDir / "pdb1cbs.ent.gz");
|
||||
|
||||
fw = a.front()["entity"].find1<float>(cif::key("id") == 2, "formula_weight");
|
||||
CHECK(fw == 300.435f);
|
||||
// auto fw = a.front()["entity"].find1<float>(cif::key("id") == 1, "formula_weight");
|
||||
// CHECK(std::abs(fw - 15581.802f) < 0.1f);
|
||||
|
||||
fw = a.front()["entity"].find1<float>(cif::key("id") == 3, "formula_weight");
|
||||
CHECK(fw == 18.015f);
|
||||
}
|
||||
// fw = a.front()["entity"].find1<float>(cif::key("id") == 2, "formula_weight");
|
||||
// CHECK(fw == 300.435f);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// fw = a.front()["entity"].find1<float>(cif::key("id") == 3, "formula_weight");
|
||||
// CHECK(fw == 18.015f);
|
||||
// }
|
||||
|
||||
TEST_CASE("update_values_with_provider")
|
||||
{
|
||||
// // --------------------------------------------------------------------
|
||||
|
||||
}
|
||||
// TEST_CASE("update_values_with_provider")
|
||||
// {
|
||||
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user