Commit 50bf2145 by Maarten L. Hekkelman

Merge branch 'develop' into trunk

parents 93375a50 dc77729f
...@@ -27,7 +27,7 @@ cmake_minimum_required(VERSION 3.16) ...@@ -27,7 +27,7 @@ cmake_minimum_required(VERSION 3.16)
# set the project name # set the project name
project( project(
libcifpp libcifpp
VERSION 7.0.0 VERSION 7.0.1
LANGUAGES CXX) LANGUAGES CXX)
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
...@@ -304,34 +304,45 @@ set(project_sources ...@@ -304,34 +304,45 @@ set(project_sources
) )
set(project_headers set(project_headers
${PROJECT_SOURCE_DIR}/include/cif++.hpp include/cif++.hpp
${PROJECT_SOURCE_DIR}/include/cif++/utilities.hpp include/cif++/utilities.hpp
${PROJECT_SOURCE_DIR}/include/cif++/item.hpp include/cif++/item.hpp
${PROJECT_SOURCE_DIR}/include/cif++/datablock.hpp include/cif++/datablock.hpp
${PROJECT_SOURCE_DIR}/include/cif++/file.hpp include/cif++/file.hpp
${PROJECT_SOURCE_DIR}/include/cif++/validate.hpp include/cif++/validate.hpp
${PROJECT_SOURCE_DIR}/include/cif++/iterator.hpp include/cif++/iterator.hpp
${PROJECT_SOURCE_DIR}/include/cif++/parser.hpp include/cif++/parser.hpp
${PROJECT_SOURCE_DIR}/include/cif++/forward_decl.hpp include/cif++/forward_decl.hpp
${PROJECT_SOURCE_DIR}/include/cif++/dictionary_parser.hpp include/cif++/dictionary_parser.hpp
${PROJECT_SOURCE_DIR}/include/cif++/condition.hpp include/cif++/condition.hpp
${PROJECT_SOURCE_DIR}/include/cif++/category.hpp include/cif++/category.hpp
${PROJECT_SOURCE_DIR}/include/cif++/row.hpp include/cif++/row.hpp
${PROJECT_SOURCE_DIR}/include/cif++/atom_type.hpp include/cif++/atom_type.hpp
${PROJECT_SOURCE_DIR}/include/cif++/compound.hpp include/cif++/compound.hpp
${PROJECT_SOURCE_DIR}/include/cif++/point.hpp include/cif++/point.hpp
${PROJECT_SOURCE_DIR}/include/cif++/symmetry.hpp include/cif++/symmetry.hpp
${PROJECT_SOURCE_DIR}/include/cif++/model.hpp include/cif++/model.hpp
${PROJECT_SOURCE_DIR}/include/cif++/pdb.hpp include/cif++/pdb.hpp
${PROJECT_SOURCE_DIR}/include/cif++/pdb/cif2pdb.hpp include/cif++/pdb/cif2pdb.hpp
${PROJECT_SOURCE_DIR}/include/cif++/pdb/io.hpp include/cif++/pdb/io.hpp
${PROJECT_SOURCE_DIR}/include/cif++/pdb/pdb2cif.hpp include/cif++/pdb/pdb2cif.hpp
${PROJECT_SOURCE_DIR}/include/cif++/pdb/tls.hpp) include/cif++/pdb/tls.hpp)
add_library(cifpp ${project_sources} ${project_headers} add_library(cifpp STATIC)
${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp)
add_library(cifpp::cifpp ALIAS cifpp) add_library(cifpp::cifpp ALIAS cifpp)
target_sources(cifpp
PRIVATE ${project_sources}
${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp
PUBLIC
FILE_SET cifpp_headers TYPE HEADERS
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include
FILES ${project_headers}
)
# The code now really requires C++20
target_compile_features(cifpp PUBLIC cxx_std_20)
set(CMAKE_DEBUG_POSTFIX d) set(CMAKE_DEBUG_POSTFIX d)
set_target_properties(cifpp PROPERTIES DEBUG_POSTFIX "d") set_target_properties(cifpp PROPERTIES DEBUG_POSTFIX "d")
...@@ -452,14 +463,9 @@ else() ...@@ -452,14 +463,9 @@ else()
endif() endif()
# Install rules # Install rules
install( install(TARGETS cifpp
TARGETS cifpp EXPORT cifpp
EXPORT cifpp-targets FILE_SET cifpp_headers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
if(MSVC AND BUILD_SHARED_LIBS) if(MSVC AND BUILD_SHARED_LIBS)
install( install(
...@@ -479,23 +485,12 @@ if(OLD_CONFIG_FILES) ...@@ -479,23 +485,12 @@ if(OLD_CONFIG_FILES)
install(CODE "file(REMOVE ${OLD_CONFIG_FILES})") install(CODE "file(REMOVE ${OLD_CONFIG_FILES})")
endif() endif()
install( install(EXPORT cifpp
EXPORT cifpp-targets
FILE "cifpp-targets.cmake"
NAMESPACE cifpp:: NAMESPACE cifpp::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cifpp) FILE "cifpp-targets.cmake"
DESTINATION lib/cmake/cifpp)
install(
DIRECTORY include/cif++
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
COMPONENT Devel)
install(
FILES include/cif++.hpp
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
COMPONENT Devel)
if(CIFPP_DATA_DIR) if(CIFPP_DATA_DIR AND CIFPP_DOWNLOAD_CCD)
install( install(
FILES ${PROJECT_SOURCE_DIR}/rsrc/mmcif_ddl.dic FILES ${PROJECT_SOURCE_DIR}/rsrc/mmcif_ddl.dic
${PROJECT_SOURCE_DIR}/rsrc/mmcif_pdbx.dic ${PROJECT_SOURCE_DIR}/rsrc/mmcif_pdbx.dic
...@@ -503,7 +498,7 @@ if(CIFPP_DATA_DIR) ...@@ -503,7 +498,7 @@ if(CIFPP_DATA_DIR)
DESTINATION ${CIFPP_DATA_DIR}) DESTINATION ${CIFPP_DATA_DIR})
endif() endif()
if(CIFPP_CACHE_DIR) if(CIFPP_CACHE_DIR AND CIFPP_DOWNLOAD_CCD)
install( install(
FILES ${PROJECT_SOURCE_DIR}/rsrc/mmcif_ddl.dic FILES ${PROJECT_SOURCE_DIR}/rsrc/mmcif_ddl.dic
${PROJECT_SOURCE_DIR}/rsrc/mmcif_pdbx.dic ${PROJECT_SOURCE_DIR}/rsrc/mmcif_pdbx.dic
...@@ -515,14 +510,13 @@ set(CONFIG_TEMPLATE_FILE ${PROJECT_SOURCE_DIR}/cmake/cifpp-config.cmake.in) ...@@ -515,14 +510,13 @@ set(CONFIG_TEMPLATE_FILE ${PROJECT_SOURCE_DIR}/cmake/cifpp-config.cmake.in)
configure_package_config_file( configure_package_config_file(
${CONFIG_TEMPLATE_FILE} ${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config.cmake ${CONFIG_TEMPLATE_FILE} ${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cifpp INSTALL_DESTINATION lib/cmake/cifpp
PATH_VARS CIFPP_DATA_DIR) PATH_VARS CIFPP_DATA_DIR)
install( install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config.cmake" FILES "${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config-version.cmake" "${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config-version.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cifpp DESTINATION lib/cmake/cifpp)
COMPONENT Devel)
set_target_properties( set_target_properties(
cifpp cifpp
......
Version 7.0.1
- Various reconstruction fixes
- category order in output fixed
- better implementation of constructors for file, datablock and category
- small optimisation in iterator
Version 7.0.0 Version 7.0.0
- Renaming many methods and parameters to be more - Renaming many methods and parameters to be more
consistent with the mmCIF dictionaries. consistent with the mmCIF dictionaries.
......
...@@ -141,31 +141,39 @@ class category ...@@ -141,31 +141,39 @@ class category
/// \endcond /// \endcond
category() = default; ///< Default constructor category() = default; ///< Default constructor
category(std::string_view name); ///< Constructor taking a \a name category(std::string_view name); ///< Constructor taking a \a name
category(const category &rhs); ///< Copy constructor category(const category &rhs); ///< Copy constructor
category(category &&rhs); ///< Move constructor
category &operator=(const category &rhs); ///< Copy assignement operator category(category &&rhs) noexcept ///< Move constructor
category &operator=(category &&rhs); ///< Move assignement operator {
swap(*this, rhs);
}
category &operator=(category rhs) ///< assignement operator
{
swap(*this, rhs);
return *this;
}
/// @brief Destructor /// @brief Destructor
/// @note Please note that the destructor is not virtual. It is assumed that /// @note Please note that the destructor is not virtual. It is assumed that
/// you will not derive from this class. /// you will not derive from this class.
~category(); ~category();
friend void swap(category &a, category &b) noexcept;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
const std::string &name() const { return m_name; } ///< Returns the name of the category const std::string &name() const { return m_name; } ///< Returns the name of the category
[[deprecated("use key_items instead")]] [[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_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 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")]] [[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_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. 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 /// @brief Set the validator for this category to @a v
/// @param v The category_validator to assign. A nullptr value is allowed. /// @param v The category_validator to assign. A nullptr value is allowed.
...@@ -1010,7 +1018,8 @@ class category ...@@ -1010,7 +1018,8 @@ class category
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, std::string_view value)
{ {
update_value(rows, item_name, [value](std::string_view) { return value; }); update_value(rows, item_name, [value](std::string_view)
{ return value; });
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -1018,8 +1027,7 @@ class category ...@@ -1018,8 +1027,7 @@ class category
// the old function names are here as deprecated variants. // the old function names are here as deprecated variants.
/// \brief Return the index number for \a column_name /// \brief Return the index number for \a column_name
[[deprecated("Use get_item_ix instead")]] [[deprecated("Use get_item_ix instead")]] uint16_t get_column_ix(std::string_view column_name) const
uint16_t get_column_ix(std::string_view column_name) const
{ {
return get_item_ix(column_name); return get_item_ix(column_name);
} }
...@@ -1027,8 +1035,7 @@ class category ...@@ -1027,8 +1035,7 @@ class category
/// @brief Return the name for column with index @a ix /// @brief Return the name for column with index @a ix
/// @param ix The index number /// @param ix The index number
/// @return The name of the column /// @return The name of the column
[[deprecated("use get_item_name instead")]] [[deprecated("use get_item_name instead")]] std::string_view get_column_name(uint16_t ix) const
std::string_view get_column_name(uint16_t ix) const
{ {
return get_item_name(ix); return get_item_name(ix);
} }
...@@ -1036,8 +1043,7 @@ class category ...@@ -1036,8 +1043,7 @@ class category
/// @brief Make sure a item with name @a item_name is known and return its index number /// @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 /// @param item_name The name of the item
/// @return The index number of the item /// @return The index number of the item
[[deprecated("use add_item instead")]] [[deprecated("use add_item instead")]] uint16_t add_column(std::string_view item_name)
uint16_t add_column(std::string_view item_name)
{ {
return add_item(item_name); return add_item(item_name);
} }
...@@ -1045,15 +1051,13 @@ class category ...@@ -1045,15 +1051,13 @@ class category
/** @brief Remove column name @a colum_name /** @brief Remove column name @a colum_name
* @param column_name The column to be removed * @param column_name The column to be removed
*/ */
[[deprecated("use remove_item instead")]] [[deprecated("use remove_item instead")]] void remove_column(std::string_view column_name)
void remove_column(std::string_view column_name)
{ {
remove_item(column_name); remove_item(column_name);
} }
/** @brief Rename column @a from_name to @a to_name */ /** @brief Rename column @a from_name to @a to_name */
[[deprecated("use rename_item instead")]] [[deprecated("use rename_item instead")]] void rename_column(std::string_view from_name, std::string_view to_name)
void rename_column(std::string_view from_name, std::string_view to_name)
{ {
rename_item(from_name, to_name); rename_item(from_name, to_name);
} }
...@@ -1061,15 +1065,13 @@ class category ...@@ -1061,15 +1065,13 @@ class category
/// @brief Return whether a column with name @a name exists in this category /// @brief Return whether a column with name @a name exists in this category
/// @param name The name of the column /// @param name The name of the column
/// @return True if the column exists /// @return True if the column exists
[[deprecated("use has_item instead")]] [[deprecated("use has_item instead")]] bool has_column(std::string_view name) const
bool has_column(std::string_view name) const
{ {
return has_item(name); return has_item(name);
} }
/// @brief Return the cif::iset of columns in this category /// @brief Return the cif::iset of columns in this category
[[deprecated("use get_items instead")]] [[deprecated("use get_items instead")]] iset get_columns() const
iset get_columns() const
{ {
return get_items(); return get_items();
} }
...@@ -1125,7 +1127,7 @@ class category ...@@ -1125,7 +1127,7 @@ class category
{ {
item_validator = m_cat_validator->get_validator_for_item(item_name); item_validator = m_cat_validator->get_validator_for_item(item_name);
if (item_validator == nullptr) if (item_validator == nullptr)
m_validator->report_error( validation_error::item_not_allowed_in_category, m_name, item_name, false); m_validator->report_error(validation_error::item_not_allowed_in_category, m_name, item_name, false);
} }
m_items.emplace_back(item_name, item_validator); m_items.emplace_back(item_name, item_validator);
...@@ -1169,8 +1171,7 @@ class category ...@@ -1169,8 +1171,7 @@ class category
/// This function returns effectively the list of fully qualified item /// This function returns effectively the list of fully qualified item
/// names, that is category_name + '.' + item_name for each item /// names, that is category_name + '.' + item_name for each item
[[deprecated("use get_item_order instead")]] [[deprecated("use get_item_order instead")]] std::vector<std::string> get_tag_order() const
std::vector<std::string> get_tag_order() const
{ {
return get_item_order(); return get_item_order();
} }
......
...@@ -61,12 +61,26 @@ class datablock : public std::list<category> ...@@ -61,12 +61,26 @@ class datablock : public std::list<category>
/** @cond */ /** @cond */
datablock(const datablock &); datablock(const datablock &);
datablock(datablock &&) = default;
datablock &operator=(const datablock &); datablock(datablock &&db) noexcept
datablock &operator=(datablock &&) = default; {
swap_(*this, db);
}
datablock &operator=(datablock db)
{
swap_(*this, db);
return *this;
}
/** @endcond */ /** @endcond */
friend void swap_(datablock &a, datablock &b) noexcept
{
std::swap(a.m_name, b.m_name);
std::swap(a.m_validator, b.m_validator);
std::swap(static_cast<std::list<category>&>(a), static_cast<std::list<category>&>(b));
}
// -------------------------------------------------------------------- // --------------------------------------------------------------------
/** /**
......
...@@ -100,10 +100,22 @@ class file : public std::list<datablock> ...@@ -100,10 +100,22 @@ class file : public std::list<datablock>
} }
/** @cond */ /** @cond */
file(const file &) = default; file(const file &rhs)
file(file &&) = default; : std::list<datablock>(rhs)
file &operator=(const file &) = default; {
file &operator=(file &&) = default; }
file(file &&rhs)
{
this->swap(rhs);
}
file &operator=(file f)
{
this->swap(f);
return *this;
}
/** @endcond */ /** @endcond */
/** /**
......
...@@ -288,19 +288,16 @@ struct item_value ...@@ -288,19 +288,16 @@ struct item_value
} }
/** @cond */ /** @cond */
item_value(item_value &&rhs) item_value(item_value &&rhs) noexcept
: m_length(std::exchange(rhs.m_length, 0)) : m_length(std::exchange(rhs.m_length, 0))
, m_storage(std::exchange(rhs.m_storage, 0)) , m_storage(std::exchange(rhs.m_storage, 0))
{ {
} }
item_value &operator=(item_value &&rhs) item_value &operator=(item_value &&rhs) noexcept
{ {
if (this != &rhs) std::swap(m_length, rhs.m_length);
{ std::swap(m_storage, rhs.m_storage);
m_length = std::exchange(rhs.m_length, m_length);
m_storage = std::exchange(rhs.m_storage, m_storage);
}
return *this; return *this;
} }
......
...@@ -49,7 +49,7 @@ namespace cif ...@@ -49,7 +49,7 @@ namespace cif
/** /**
* @brief Implementation of an iterator that can return * @brief Implementation of an iterator that can return
* multiple values in a tuple. Of course, that tuple can * multiple values in a tuple. Of course, that tuple can
* then used in structured binding to receive the values * then be used in structured binding to receive the values
* in a for loop e.g. * in a for loop e.g.
* *
* @tparam Category The category for this iterator * @tparam Category The category for this iterator
...@@ -84,11 +84,11 @@ class iterator_impl ...@@ -84,11 +84,11 @@ class iterator_impl
iterator_impl() = default; iterator_impl() = default;
iterator_impl(const iterator_impl &rhs) = default; iterator_impl(const iterator_impl &rhs) = default;
iterator_impl(iterator_impl &&rhs) = default;
template <typename C2, typename... T2s> template <typename C2, typename... T2s>
iterator_impl(const iterator_impl<C2, T2s...> &rhs) iterator_impl(const iterator_impl<C2, T2s...> &rhs)
: m_category(rhs.m_category) : m_current(const_cast<row_handle&>(rhs.m_current))
, m_current(rhs.m_current)
, m_value(rhs.m_value) , m_value(rhs.m_value)
, m_item_ix(rhs.m_item_ix) , m_item_ix(rhs.m_item_ix)
{ {
...@@ -96,8 +96,7 @@ class iterator_impl ...@@ -96,8 +96,7 @@ class iterator_impl
template <typename IRowType> template <typename IRowType>
iterator_impl(iterator_impl<IRowType, Ts...> &rhs) iterator_impl(iterator_impl<IRowType, Ts...> &rhs)
: m_category(rhs.m_category) : m_current(const_cast<row_handle&>(rhs.m_current))
, m_current(const_cast<row_type *>(rhs.m_current))
, m_value(rhs.m_value) , m_value(rhs.m_value)
, m_item_ix(rhs.m_item_ix) , m_item_ix(rhs.m_item_ix)
{ {
...@@ -106,19 +105,17 @@ class iterator_impl ...@@ -106,19 +105,17 @@ class iterator_impl
template <typename IRowType> template <typename IRowType>
iterator_impl(const iterator_impl<IRowType> &rhs, const std::array<uint16_t, N> &cix) iterator_impl(const iterator_impl<IRowType> &rhs, const std::array<uint16_t, N> &cix)
: m_category(rhs.m_category) : m_current(const_cast<row_handle&>(rhs.m_current))
, m_current(rhs.m_current)
, m_item_ix(cix) , m_item_ix(cix)
{ {
m_value = get(std::make_index_sequence<N>()); m_value = get(std::make_index_sequence<N>());
} }
iterator_impl &operator=(const iterator_impl &i) iterator_impl &operator=(iterator_impl i)
{ {
m_category = i.m_category; std::swap(m_current, i.m_current);
m_current = i.m_current; std::swap(m_item_ix, i.m_item_ix);
m_item_ix = i.m_item_ix; std::swap(m_value, i.m_value);
m_value = i.m_value;
return *this; return *this;
} }
...@@ -136,18 +133,18 @@ class iterator_impl ...@@ -136,18 +133,18 @@ class iterator_impl
operator const row_handle() const operator const row_handle() const
{ {
return { *m_category, *m_current }; return m_current;
} }
operator row_handle() operator row_handle()
{ {
return { *m_category, *m_current }; return m_current;
} }
iterator_impl &operator++() iterator_impl &operator++()
{ {
if (m_current != nullptr) if (m_current)
m_current = m_current->m_next; m_current.m_row = m_current.m_row->m_next;
m_value = get(std::make_index_sequence<N>()); m_value = get(std::make_index_sequence<N>());
...@@ -182,17 +179,10 @@ class iterator_impl ...@@ -182,17 +179,10 @@ class iterator_impl
template <size_t... Is> template <size_t... Is>
tuple_type get(std::index_sequence<Is...>) const tuple_type get(std::index_sequence<Is...>) const
{ {
if (m_current != nullptr) return m_current ? tuple_type{ m_current[m_item_ix[Is]].template as<Ts>()... } : tuple_type{};
{
row_handle rh{ *m_category, *m_current };
return tuple_type{ rh[m_item_ix[Is]].template as<Ts>()... };
}
return {};
} }
category_type *m_category = nullptr; row_handle m_current;
row_type *m_current = nullptr;
value_type m_value; value_type m_value;
std::array<uint16_t, N> m_item_ix; std::array<uint16_t, N> m_item_ix;
}; };
...@@ -219,37 +209,34 @@ class iterator_impl<Category> ...@@ -219,37 +209,34 @@ class iterator_impl<Category>
using iterator_category = std::forward_iterator_tag; using iterator_category = std::forward_iterator_tag;
using value_type = row_handle; using value_type = row_handle;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using pointer = row_handle; using pointer = value_type *;
using reference = row_handle; using reference = value_type &;
iterator_impl() = default; iterator_impl() = default;
iterator_impl(const iterator_impl &rhs) = default; iterator_impl(const iterator_impl &rhs) = default;
iterator_impl(iterator_impl &&rhs) = default;
template <typename C2> template <typename C2>
iterator_impl(const iterator_impl<C2> &rhs) iterator_impl(const iterator_impl<C2> &rhs)
: m_category(rhs.m_category) : m_current(const_cast<row_handle &>(rhs.m_current))
, m_current(const_cast<row_type *>(rhs.m_current))
{ {
} }
iterator_impl(Category &cat, row *current) iterator_impl(Category &cat, row *current)
: m_category(const_cast<category_type *>(&cat)) : m_current(cat, *current)
, m_current(current)
{ {
} }
template <typename IRowType> template <typename IRowType>
iterator_impl(const iterator_impl<IRowType> &rhs, const std::array<uint16_t, 0> &) iterator_impl(const iterator_impl<IRowType> &rhs, const std::array<uint16_t, 0> &)
: m_category(rhs.m_category) : m_current(const_cast<row_handle &>(rhs.m_current))
, m_current(rhs.m_current)
{ {
} }
iterator_impl &operator=(const iterator_impl &i) iterator_impl &operator=(iterator_impl i)
{ {
m_category = i.m_category; std::swap(m_current, i.m_current);
m_current = i.m_current;
return *this; return *this;
} }
...@@ -257,7 +244,7 @@ class iterator_impl<Category> ...@@ -257,7 +244,7 @@ class iterator_impl<Category>
reference operator*() reference operator*()
{ {
return { *m_category, *m_current }; return m_current;
} }
pointer operator->() pointer operator->()
...@@ -267,18 +254,18 @@ class iterator_impl<Category> ...@@ -267,18 +254,18 @@ class iterator_impl<Category>
operator const row_handle() const operator const row_handle() const
{ {
return { *m_category, *m_current }; return m_current;
} }
operator row_handle() operator row_handle()
{ {
return { *m_category, *m_current }; return m_current;
} }
iterator_impl &operator++() iterator_impl &operator++()
{ {
if (m_current != nullptr) if (m_current)
m_current = m_current->m_next; m_current.m_row = m_current.m_row->m_next;
return *this; return *this;
} }
...@@ -308,8 +295,7 @@ class iterator_impl<Category> ...@@ -308,8 +295,7 @@ class iterator_impl<Category>
/** @endcond */ /** @endcond */
private: private:
category_type *m_category = nullptr; row_handle m_current;
row_type *m_current = nullptr;
}; };
/** /**
...@@ -342,11 +328,11 @@ class iterator_impl<Category, T> ...@@ -342,11 +328,11 @@ class iterator_impl<Category, T>
iterator_impl() = default; iterator_impl() = default;
iterator_impl(const iterator_impl &rhs) = default; iterator_impl(const iterator_impl &rhs) = default;
iterator_impl(iterator_impl &&rhs) = default;
template <typename C2, typename T2> template <typename C2, typename T2>
iterator_impl(const iterator_impl<C2, T2> &rhs) iterator_impl(const iterator_impl<C2, T2> &rhs)
: m_category(rhs.m_category) : m_current(rhs.m_current)
, m_current(rhs.m_current)
, m_value(rhs.m_value) , m_value(rhs.m_value)
, m_item_ix(rhs.m_item_ix) , m_item_ix(rhs.m_item_ix)
{ {
...@@ -354,29 +340,26 @@ class iterator_impl<Category, T> ...@@ -354,29 +340,26 @@ class iterator_impl<Category, T>
template <typename IRowType> template <typename IRowType>
iterator_impl(iterator_impl<IRowType, T> &rhs) iterator_impl(iterator_impl<IRowType, T> &rhs)
: m_category(rhs.m_category) : m_current(const_cast<row_handle&>(rhs.m_current))
, m_current(const_cast<row_type *>(rhs.m_current))
, m_value(rhs.m_value) , m_value(rhs.m_value)
, m_item_ix(rhs.m_item_ix) , m_item_ix(rhs.m_item_ix)
{ {
m_value = get(m_current); m_value = get();
} }
template <typename IRowType> template <typename IRowType>
iterator_impl(const iterator_impl<IRowType> &rhs, const std::array<uint16_t, 1> &cix) iterator_impl(const iterator_impl<IRowType> &rhs, const std::array<uint16_t, 1> &cix)
: m_category(rhs.m_category) : m_current(const_cast<row_handle&>(rhs.m_current))
, m_current(rhs.m_current)
, m_item_ix(cix[0]) , m_item_ix(cix[0])
{ {
m_value = get(); m_value = get();
} }
iterator_impl &operator=(const iterator_impl &i) iterator_impl &operator=(iterator_impl i)
{ {
m_category = i.m_category; std::swap(m_current, i.m_current);
m_current = i.m_current; std::swap(m_item_ix, i.m_item_ix);
m_item_ix = i.m_item_ix; std::swap(m_value, i.m_value);
m_value = i.m_value;
return *this; return *this;
} }
...@@ -394,18 +377,18 @@ class iterator_impl<Category, T> ...@@ -394,18 +377,18 @@ class iterator_impl<Category, T>
operator const row_handle() const operator const row_handle() const
{ {
return { *m_category, *m_current }; return m_current;
} }
operator row_handle() operator row_handle()
{ {
return { *m_category, *m_current }; return m_current;
} }
iterator_impl &operator++() iterator_impl &operator++()
{ {
if (m_current != nullptr) if (m_current)
m_current = m_current->m_next; m_current.m_row = m_current.m_row->m_next;
m_value = get(); m_value = get();
...@@ -439,17 +422,10 @@ class iterator_impl<Category, T> ...@@ -439,17 +422,10 @@ class iterator_impl<Category, T>
private: private:
value_type get() const value_type get() const
{ {
if (m_current != nullptr) return m_current ? m_current[m_item_ix].template as<value_type>() : value_type{};
{
row_handle rh{ *m_category, *m_current };
return rh[m_item_ix].template as<T>();
}
return {};
} }
category_type *m_category = nullptr; row_handle m_current;
row_type *m_current = nullptr;
value_type m_value; value_type m_value;
uint16_t m_item_ix; uint16_t m_item_ix;
}; };
......
...@@ -208,6 +208,7 @@ class row_handle ...@@ -208,6 +208,7 @@ class row_handle
friend class category; friend class category;
friend class category_index; friend class category_index;
friend class row_initializer; friend class row_initializer;
template <typename, typename...> friend class iterator_impl;
row_handle() = default; row_handle() = default;
......
...@@ -113,16 +113,12 @@ namespace colour ...@@ -113,16 +113,12 @@ namespace colour
/** /**
* @brief Struct for delimited strings. * @brief Struct for delimited strings.
*/ */
template <typename StringType>
struct coloured_string_t struct coloured_string_t
{ {
static_assert(std::is_reference_v<StringType> or std::is_pointer_v<StringType>,
"String type must be pointer or reference");
/** /**
* @brief Construct a new coloured string t object * @brief Construct a new coloured string t object
*/ */
coloured_string_t(StringType s, colour_type fc, colour_type bc, style_type st) coloured_string_t(std::string_view s, colour_type fc, colour_type bc, style_type st)
: m_str(s) : m_str(s)
, m_fore_colour(static_cast<int>(fc) + 30) , m_fore_colour(static_cast<int>(fc) + 30)
, m_back_colour(static_cast<int>(bc) + 40) , m_back_colour(static_cast<int>(bc) + 40)
...@@ -152,12 +148,14 @@ namespace colour ...@@ -152,12 +148,14 @@ namespace colour
<< cs.m_str << cs.m_str
<< "\033[0m"; << "\033[0m";
} }
else
os << cs.m_str;
return os; return os;
} }
/// @cond /// @cond
StringType m_str; std::string_view m_str;
int m_fore_colour, m_back_colour; int m_fore_colour, m_back_colour;
int m_style; int m_style;
/// @endcond /// @endcond
...@@ -191,39 +189,13 @@ namespace colour ...@@ -191,39 +189,13 @@ namespace colour
* @param st Text style to use * @param st Text style to use
*/ */
template <typename char_type> template <typename T>
inline auto coloured(const char_type *str, requires std::is_assignable_v<std::string_view, T>
colour::colour_type fg, colour::colour_type bg = colour::colour_type::none, inline auto coloured(T str,
colour::style_type st = colour::style_type::regular)
{
return colour::detail::coloured_string_t<const char_type *>(str, fg, bg, st);
}
/// @brief Manipulator for coloured strings.
template <typename char_type, typename traits_type, typename allocator_type>
inline auto coloured(const std::basic_string<char_type, traits_type, allocator_type> &str,
colour::colour_type fg, colour::colour_type bg = colour::colour_type::none,
colour::style_type st = colour::style_type::regular)
{
return colour::detail::coloured_string_t<const std::basic_string<char_type, traits_type, allocator_type> &>(str, fg, bg, st);
}
/// @brief Manipulator for coloured strings.
template <typename char_type, typename traits_type, typename allocator_type>
inline auto coloured(std::basic_string<char_type, traits_type, allocator_type> &str,
colour::colour_type fg, colour::colour_type bg = colour::colour_type::none,
colour::style_type st = colour::style_type::regular)
{
return colour::detail::coloured_string_t<std::basic_string<char_type, traits_type, allocator_type> &>(str, fg, bg, st);
}
/// @brief Manipulator for coloured strings.
template <typename char_type, typename traits_type>
inline auto coloured(std::basic_string_view<char_type, traits_type> &str,
colour::colour_type fg, colour::colour_type bg = colour::colour_type::none, colour::colour_type fg, colour::colour_type bg = colour::colour_type::none,
colour::style_type st = colour::style_type::regular) colour::style_type st = colour::style_type::regular)
{ {
return colour::detail::coloured_string_t<std::basic_string_view<char_type, traits_type> &>(str, fg, bg, st); return colour::detail::coloured_string_t(str, fg, bg, st);
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
......
...@@ -120,7 +120,7 @@ class validation_category_impl : public std::error_category ...@@ -120,7 +120,7 @@ class validation_category_impl : public std::error_category
case validation_error::missing_key_items: case validation_error::missing_key_items:
return "An index could not be constructed due to missing key items"; return "An index could not be constructed due to missing key items";
case validation_error::item_not_allowed_in_category: case validation_error::item_not_allowed_in_category:
return "Requested item allowed in category according to dictionary"; return "Requested item not allowed in category according to dictionary";
case validation_error::empty_file: case validation_error::empty_file:
return "The file contains no datablocks"; return "The file contains no datablocks";
case validation_error::empty_datablock: case validation_error::empty_datablock:
......
...@@ -521,71 +521,18 @@ category::category(const category &rhs) ...@@ -521,71 +521,18 @@ category::category(const category &rhs)
m_index = new category_index(*this); m_index = new category_index(*this);
} }
category::category(category &&rhs) void swap(category &a, category &b) noexcept
: m_name(std::move(rhs.m_name))
, m_items(std::move(rhs.m_items))
, m_validator(rhs.m_validator)
, m_cat_validator(rhs.m_cat_validator)
, m_parent_links(std::move(rhs.m_parent_links))
, m_child_links(std::move(rhs.m_child_links))
, m_cascade(rhs.m_cascade)
, m_index(rhs.m_index)
, m_head(rhs.m_head)
, m_tail(rhs.m_tail)
{
rhs.m_head = nullptr;
rhs.m_tail = nullptr;
rhs.m_index = nullptr;
}
category &category::operator=(const category &rhs)
{
if (this != &rhs)
{
if (not empty())
clear();
m_name = rhs.m_name;
m_items = rhs.m_items;
m_cascade = rhs.m_cascade;
m_validator = nullptr;
m_cat_validator = nullptr;
delete m_index;
m_index = nullptr;
for (auto r = rhs.m_head; r != nullptr; r = r->m_next)
insert_impl(cend(), clone_row(*r));
m_validator = rhs.m_validator;
m_cat_validator = rhs.m_cat_validator;
if (m_cat_validator != nullptr and m_index == nullptr)
m_index = new category_index(*this);
}
return *this;
}
category &category::operator=(category &&rhs)
{ {
if (this != &rhs) std::swap(a.m_name, b.m_name);
{ std::swap(a.m_items, b.m_items);
m_name = std::move(rhs.m_name); std::swap(a.m_validator, b.m_validator);
m_items = std::move(rhs.m_items); std::swap(a.m_cat_validator, b.m_cat_validator);
m_cascade = rhs.m_cascade; std::swap(a.m_parent_links, b.m_parent_links);
m_validator = rhs.m_validator; std::swap(a.m_child_links, b.m_child_links);
m_cat_validator = rhs.m_cat_validator; std::swap(a.m_cascade, b.m_cascade);
m_parent_links = rhs.m_parent_links; std::swap(a.m_index, b.m_index);
m_child_links = rhs.m_child_links; std::swap(a.m_head, b.m_head);
std::swap(a.m_tail, b.m_tail);
std::swap(m_index, rhs.m_index);
std::swap(m_head, rhs.m_head);
std::swap(m_tail, rhs.m_tail);
}
return *this;
} }
category::~category() category::~category()
...@@ -1712,7 +1659,7 @@ category::iterator category::insert_impl(const_iterator pos, row *n) ...@@ -1712,7 +1659,7 @@ category::iterator category::insert_impl(const_iterator pos, row *n)
m_index->insert(*this, n); m_index->insert(*this, n);
// insert at end, most often this is the case // insert at end, most often this is the case
if (pos.m_current == nullptr) if (pos.m_current.m_row == nullptr)
{ {
if (m_head == nullptr) if (m_head == nullptr)
m_tail = m_head = n; m_tail = m_head = n;
...@@ -1723,7 +1670,7 @@ category::iterator category::insert_impl(const_iterator pos, row *n) ...@@ -1723,7 +1670,7 @@ category::iterator category::insert_impl(const_iterator pos, row *n)
{ {
assert(m_head != nullptr); assert(m_head != nullptr);
if (pos.m_current == m_head) if (pos.m_current.m_row == m_head)
m_head = n->m_next = m_head; m_head = n->m_next = m_head;
else else
n = n->m_next = m_head->m_next; n = n->m_next = m_head->m_next;
......
...@@ -550,7 +550,7 @@ class local_compound_factory_impl : public compound_factory_impl ...@@ -550,7 +550,7 @@ class local_compound_factory_impl : public compound_factory_impl
compound *create(const std::string &id) override; compound *create(const std::string &id) override;
private: private:
const cif::file &m_local_file; cif::file m_local_file;
}; };
compound *local_compound_factory_impl::create(const std::string &id) compound *local_compound_factory_impl::create(const std::string &id)
...@@ -559,11 +559,19 @@ compound *local_compound_factory_impl::create(const std::string &id) ...@@ -559,11 +559,19 @@ compound *local_compound_factory_impl::create(const std::string &id)
for (auto &db : m_local_file) for (auto &db : m_local_file)
{ {
if (db.name() == "comp_" + id) if (db.name() == id)
{ {
cif::datablock db_copy(db); cif::datablock db_copy(db);
result = new compound(db_copy, 1); try
{
result = new compound(db_copy, 1);
}
catch (const std::exception &ex)
{
std::throw_with_nested(std::runtime_error("Error loading compound " + id));
}
std::shared_lock lock(mMutex); std::shared_lock lock(mMutex);
m_compounds.push_back(result); m_compounds.push_back(result);
......
...@@ -38,21 +38,6 @@ datablock::datablock(const datablock &db) ...@@ -38,21 +38,6 @@ datablock::datablock(const datablock &db)
cat.update_links(*this); cat.update_links(*this);
} }
datablock &datablock::operator=(const datablock &db)
{
if (this != &db)
{
std::list<category>::operator=(db);
m_name = db.m_name;
m_validator = db.m_validator;
for (auto &cat : *this)
cat.update_links(*this);
}
return *this;
}
void datablock::set_validator(const validator *v) void datablock::set_validator(const validator *v)
{ {
m_validator = v; m_validator = v;
...@@ -282,7 +267,11 @@ void datablock::write(std::ostream &os) const ...@@ -282,7 +267,11 @@ void datablock::write(std::ostream &os) const
cat_order_t cat_order; cat_order_t cat_order;
for (auto &cat : *this) for (auto &cat : *this)
{
if (cat.name() == "entry" or cat.name() == "audit_conform")
continue;
cat_order.emplace_back(cat.name(), -1, false); cat_order.emplace_back(cat.name(), -1, false);
}
for (auto i = cat_order.begin(); i != cat_order.end(); ++i) for (auto i = cat_order.begin(); i != cat_order.end(); ++i)
calculate_cat_order(cat_order, i, *m_validator); calculate_cat_order(cat_order, i, *m_validator);
...@@ -292,25 +281,18 @@ void datablock::write(std::ostream &os) const ...@@ -292,25 +281,18 @@ void datablock::write(std::ostream &os) const
const auto &[cat_a, count_a, on_stack_a] = a; const auto &[cat_a, count_a, on_stack_a] = a;
const auto &[cat_b, count_b, on_stack_b] = b; const auto &[cat_b, count_b, on_stack_b] = b;
int d = 0; int d = std::get<1>(a) - std::get<1>(b);
if (d == 0)
if (cat_a == "audit_conform") d = cat_b.compare(cat_a);
d = -1;
else if (cat_b == "audit_conform")
d = 1;
else if (cat_a == "entry")
d = -1;
else if (cat_b == "entry")
d = 1;
else
{
d = std::get<1>(a) - std::get<1>(b);
if (d == 0)
d = cat_b.compare(cat_a);
}
return d < 0; }); return d < 0; });
if (auto entry = get("entry"); entry != nullptr)
entry->write(os);
if (auto audit_conform = get("audit_conform"); audit_conform != nullptr)
audit_conform->write(os);
for (auto &&[cat, count, on_stack] : cat_order) for (auto &&[cat, count, on_stack] : cat_order)
get(cat)->write(os); get(cat)->write(os);
} }
...@@ -320,20 +302,13 @@ void datablock::write(std::ostream &os) const ...@@ -320,20 +302,13 @@ void datablock::write(std::ostream &os) const
// and if it exists, _AND_ we have a Validator, write out the // and if it exists, _AND_ we have a Validator, write out the
// audit_conform record. // audit_conform record.
for (auto &cat : *this) if (auto entry = get("entry"); entry != nullptr)
{ entry->write(os);
if (cat.name() != "entry")
continue;
cat.write(os);
break;
}
// If the dictionary declares an audit_conform category, put it in, // If the dictionary declares an audit_conform category, put it in,
// but only if it does not exist already! // but only if it does not exist already!
if (get("audit_conform")) if (auto audit_conform = get("audit_conform"); audit_conform != nullptr)
get("audit_conform")->write(os); audit_conform->write(os);
for (auto &cat : *this) for (auto &cat : *this)
{ {
...@@ -348,7 +323,7 @@ void datablock::write(std::ostream &os, const std::vector<std::string> &item_nam ...@@ -348,7 +323,7 @@ void datablock::write(std::ostream &os, const std::vector<std::string> &item_nam
os << "data_" << m_name << '\n' os << "data_" << m_name << '\n'
<< "# \n"; << "# \n";
std::vector<std::string> cat_order; std::vector<std::string> cat_order{ "entry", "audit_conform" };
for (auto &o : item_name_order) for (auto &o : item_name_order)
{ {
std::string cat_name, item_name; std::string cat_name, item_name;
......
...@@ -4669,47 +4669,6 @@ void PDBFileParser::ConstructEntities() ...@@ -4669,47 +4669,6 @@ void PDBFileParser::ConstructEntities()
} }
} }
} }
// Finish by calculating the formula_weight for each entity
for (auto entity : *getCategory("entity"))
{
auto entity_id = entity["id"].as<std::string>();
float formula_weight = 0;
if (entity["type"] == "polymer")
{
int n = 0;
for (std::string comp_id : getCategory("pdbx_poly_seq_scheme")->find<std::string>(cif::key("entity_id") == entity_id, "mon_id"))
{
auto compound = cif::compound_factory::instance().create(comp_id);
assert(compound);
if (not compound)
throw std::runtime_error("missing information for compound " + comp_id);
formula_weight += compound->formula_weight();
++n;
}
formula_weight -= (n - 1) * 18.015;
}
else if (entity["type"] == "water")
formula_weight = 18.015;
else
{
auto comp_id = getCategory("pdbx_nonpoly_scheme")->find_first<std::optional<std::string>>(cif::key("entity_id") == entity_id, "mon_id");
if (comp_id.has_value())
{
auto compound = cif::compound_factory::instance().create(*comp_id);
assert(compound);
if (not compound)
throw std::runtime_error("missing information for compound " + *comp_id);
formula_weight = compound->formula_weight();
}
}
if (formula_weight > 0)
entity.assign({ { "formula_weight", formula_weight, 3 } });
}
} }
void PDBFileParser::ConstructSugarTrees(int &asymNr) void PDBFileParser::ConstructSugarTrees(int &asymNr)
...@@ -6454,11 +6413,11 @@ file read(std::istream &is) ...@@ -6454,11 +6413,11 @@ file read(std::istream &is)
{ {
std::throw_with_nested(std::runtime_error("Since the file did not start with a valid PDB HEADER line mmCIF was assumed, but that failed.")); std::throw_with_nested(std::runtime_error("Since the file did not start with a valid PDB HEADER line mmCIF was assumed, but that failed."));
} }
// Since we're using the cif::pdb way of reading the file, the data may need
// reconstruction
reconstruct_pdbx(result);
} }
// Since we're using the cif::pdb way of reading the file, the data may need
// reconstruction
reconstruct_pdbx(result);
} }
// Must be a PDB like file, right? // Must be a PDB like file, right?
......
...@@ -92,6 +92,70 @@ condition get_condition(residue_key_type &k) ...@@ -92,6 +92,70 @@ condition get_condition(residue_key_type &k)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
void checkEntities(datablock &db)
{
using namespace cif::literals;
auto &cf = cif::compound_factory::instance();
for (auto entity : db["entity"].find("formula_weight"_key == null or "formula_weight"_key == 0))
{
const auto &[entity_id, type] = entity.get<std::string, std::string>("id", "type");
float formula_weight = 0;
if (type == "polymer")
{
int n = 0;
for (std::string comp_id : db["pdbx_poly_seq_scheme"].find<std::string>("entity_id"_key == entity_id, "mon_id"))
{
auto compound = cf.create(comp_id);
assert(compound);
if (not compound)
throw std::runtime_error("missing information for compound " + comp_id);
formula_weight += compound->formula_weight();
++n;
}
formula_weight -= (n - 1) * 18.015;
}
else if (type == "water")
formula_weight = 18.015;
else if (type == "branched")
{
int n = 0;
for (std::string comp_id : db["pdbx_entity_branch_list"].find<std::string>("entity_id"_key == entity_id, "comp_id"))
{
auto compound = cf.create(comp_id);
assert(compound);
if (not compound)
throw std::runtime_error("missing information for compound " + comp_id);
formula_weight += compound->formula_weight();
++n;
}
formula_weight -= (n - 1) * 18.015;
}
else if (type == "non-polymer")
{
auto comp_id = db["pdbx_nonpoly_scheme"].find_first<std::optional<std::string>>("entity_id"_key == entity_id, "mon_id");
if (comp_id.has_value())
{
auto compound = cf.create(*comp_id);
assert(compound);
if (not compound)
throw std::runtime_error("missing information for compound " + *comp_id);
formula_weight = compound->formula_weight();
}
}
if (formula_weight > 0)
entity.assign({ { "formula_weight", formula_weight, 3 } });
}
}
void createEntityIDs(datablock &db) void createEntityIDs(datablock &db)
{ {
// Suppose the file does not have entity ID's. We have to make up some // Suppose the file does not have entity ID's. We have to make up some
...@@ -386,12 +450,16 @@ void checkAtomRecords(datablock &db) ...@@ -386,12 +450,16 @@ void checkAtomRecords(datablock &db)
auto chem_comp_entry = chem_comp.find_first("id"_key == comp_id); auto chem_comp_entry = chem_comp.find_first("id"_key == comp_id);
std::optional<bool> non_std;
if (cf.is_monomer(comp_id))
non_std = cf.is_std_monomer(comp_id);
if (not chem_comp_entry) if (not chem_comp_entry)
{ {
chem_comp.emplace({ // chem_comp.emplace({ //
{ "id", comp_id }, { "id", comp_id },
{ "type", compound->type() }, { "type", compound->type() },
{ "mon_nstd_flag", cf.is_std_monomer(comp_id) ? "y" : "n" }, { "mon_nstd_flag", non_std },
{ "name", compound->name() }, { "name", compound->name() },
{ "formula", compound->formula() }, { "formula", compound->formula() },
{ "formula_weight", compound->formula_weight() } }); { "formula_weight", compound->formula_weight() } });
...@@ -402,8 +470,8 @@ void checkAtomRecords(datablock &db) ...@@ -402,8 +470,8 @@ void checkAtomRecords(datablock &db)
if (not chem_comp_entry["type"]) if (not chem_comp_entry["type"])
items.emplace_back(item{ "type", compound->type() }); items.emplace_back(item{ "type", compound->type() });
if (not chem_comp_entry["mon_nstd_flag"]) if (not chem_comp_entry["mon_nstd_flag"] and non_std.has_value())
items.emplace_back(item{ "mon_nstd_flag", cf.is_std_monomer(comp_id) ? "y" : "n" }); items.emplace_back(item{ "mon_nstd_flag", non_std });
if (not chem_comp_entry["name"]) if (not chem_comp_entry["name"])
items.emplace_back(item{ "name", compound->name() }); items.emplace_back(item{ "name", compound->name() });
if (not chem_comp_entry["formula"]) if (not chem_comp_entry["formula"])
...@@ -420,15 +488,13 @@ void checkAtomRecords(datablock &db) ...@@ -420,15 +488,13 @@ void checkAtomRecords(datablock &db)
int seq_id = get_seq_id(k); int seq_id = get_seq_id(k);
if (row["label_seq_id"].empty()) if (row["label_seq_id"].empty() and cf.is_monomer(comp_id))
row["label_seq_id"] = std::to_string(seq_id); row["label_seq_id"] = std::to_string(seq_id);
if (row["label_atom_id"].empty()) if (row["label_atom_id"].empty())
row["label_atom_id"] = row["auth_atom_id"].text(); row["label_atom_id"] = row["auth_atom_id"].text();
if (row["label_asym_id"].empty()) if (row["label_asym_id"].empty())
row["label_asym_id"] = row["auth_asym_id"].text(); row["label_asym_id"] = row["auth_asym_id"].text();
if (row["label_seq_id"].empty())
row["label_seq_id"] = row["auth_seq_id"].text();
if (row["label_comp_id"].empty()) if (row["label_comp_id"].empty())
row["label_comp_id"] = row["auth_comp_id"].text(); row["label_comp_id"] = row["auth_comp_id"].text();
if (row["label_atom_id"].empty()) if (row["label_atom_id"].empty())
...@@ -517,7 +583,7 @@ void checkAtomAnisotropRecords(datablock &db) ...@@ -517,7 +583,7 @@ void checkAtomAnisotropRecords(datablock &db)
{ {
if (cif::VERBOSE and std::exchange(warnReplaceTypeSymbol, false)) if (cif::VERBOSE and std::exchange(warnReplaceTypeSymbol, false))
std::clog << "Replacing type_symbol in atom_site_anisotrop record(s)\n"; std::clog << "Replacing type_symbol in atom_site_anisotrop record(s)\n";
row["type_symbol"] != parent["type_symbol"].text(); row["type_symbol"] = parent["type_symbol"].text();
} }
if (row["pdbx_auth_alt_id"].empty()) if (row["pdbx_auth_alt_id"].empty())
...@@ -1263,6 +1329,9 @@ bool reconstruct_pdbx(file &file, std::string_view dictionary) ...@@ -1263,6 +1329,9 @@ bool reconstruct_pdbx(file &file, std::string_view dictionary)
if (db.get("entity") == nullptr) if (db.get("entity") == nullptr)
createEntity(db); createEntity(db);
// fill in missing formula_weight, e.g.
checkEntities(db);
if (db.get("pdbx_poly_seq_scheme") == nullptr) if (db.get("pdbx_poly_seq_scheme") == nullptr)
createPdbxPolySeqScheme(db); createPdbxPolySeqScheme(db);
......
...@@ -190,22 +190,41 @@ std::string trim_left_copy(std::string_view s) ...@@ -190,22 +190,41 @@ std::string trim_left_copy(std::string_view s)
void trim_left(std::string &s) void trim_left(std::string &s)
{ {
auto b = s.begin(); auto in = s.begin(), out = s.begin();
while (b != s.end())
while (in != s.end() and std::isspace(*in))
++in;
if (in == s.end())
s.clear();
else if (in != out)
{ {
if (not std::isspace(*b)) while (in != s.end())
break; *out++ = *in++;
s.erase(out, s.end());
b = std::next(b);
} }
s.erase(s.begin(), b);
} }
void trim(std::string &s) void trim(std::string &s)
{ {
trim_right(s); auto in = s.begin(), out = s.begin(), end = s.end();
trim_left(s);
while (end != s.begin() and std::isspace(*(end - 1)))
--end;
while (in != end and std::isspace(*in))
++in;
if (in == end)
s.clear();
else if (in != out)
{
while (in != end)
*out++ = *in++;
s.erase(out, s.end());
}
else if (end != s.end())
s.erase(end, s.end());
} }
std::string trim_copy(std::string_view s) std::string trim_copy(std::string_view s)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment