Commit d496ebf6 by Maarten L. Hekkelman

backup of documentation

parent 1719ed69
...@@ -275,14 +275,7 @@ set(project_headers ...@@ -275,14 +275,7 @@ set(project_headers
add_library(cifpp ${project_sources} ${project_headers} ${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp) add_library(cifpp ${project_sources} ${project_headers} ${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp)
add_library(cifpp::cifpp ALIAS cifpp) add_library(cifpp::cifpp ALIAS cifpp)
set(EXPORT_DOXYGEN_CONTENT [[ generate_export_header(cifpp EXPORT_FILE_NAME ${PROJECT_SOURCE_DIR}/include/cif++/exports.hpp)
/** @file exports.hpp */
]])
generate_export_header(cifpp EXPORT_FILE_NAME ${PROJECT_SOURCE_DIR}/include/cif++/exports.hpp
CUSTOM_CONTENT_FROM_VARIABLE EXPORT_DOXYGEN_CONTENT)
if(BOOST_REGEX) if(BOOST_REGEX)
target_compile_definitions(cifpp PRIVATE USE_BOOST_REGEX=1 BOOST_REGEX_STANDALONE=1) target_compile_definitions(cifpp PRIVATE USE_BOOST_REGEX=1 BOOST_REGEX_STANDALONE=1)
......
...@@ -59,11 +59,13 @@ class datablock : public std::list<category> ...@@ -59,11 +59,13 @@ class datablock : public std::list<category>
{ {
} }
/** @cond */
datablock(const datablock &); datablock(const datablock &);
datablock(datablock &&) = default; datablock(datablock &&) = default;
datablock &operator=(const datablock &); datablock &operator=(const datablock &);
datablock &operator=(datablock &&) = default; datablock &operator=(datablock &&) = default;
/** @endcond */
// -------------------------------------------------------------------- // --------------------------------------------------------------------
......
...@@ -100,10 +100,12 @@ class file : public std::list<datablock> ...@@ -100,10 +100,12 @@ class file : public std::list<datablock>
load(is); load(is);
} }
/** @cond */
file(const file &) = default; file(const file &) = default;
file(file &&) = default; file(file &&) = default;
file &operator=(const file &) = default; file &operator=(const file &) = default;
file &operator=(file &&) = default; file &operator=(file &&) = default;
/** @endcond */
/** /**
* @brief Set the validator object to @a v * @brief Set the validator object to @a v
......
...@@ -31,6 +31,13 @@ ...@@ -31,6 +31,13 @@
#include <string> #include <string>
#include <vector> #include <vector>
/**
* @file forward_decl.hpp
*
* File containing only forward declarations
*
*/
namespace cif namespace cif
{ {
......
...@@ -13,27 +13,29 @@ ...@@ -13,27 +13,29 @@
#include <zlib.h> #include <zlib.h>
/// \file gzio.hpp /** \file gzio.hpp
/// *
/// Single header file for the implementation of stream classes * Single header file for the implementation of stream classes
/// that can transparently read and write compressed files. * that can transparently read and write compressed files.
/// *
/// The gzio::istream_buf class sniffs the input and decides whether to use * The gzio::istream_buf class sniffs the input and decides whether to use
/// a decompressor if a signature was recognized. * a decompressor if a signature was recognized.
/// *
/// There's also an ifstream and ofstream class here that can * There's also an ifstream and ofstream class here that can
/// read and write compressed files. In this case the decission * read and write compressed files. In this case the decission
/// whether to use a compressions/decompression algorithm is * whether to use a compressions/decompression algorithm is
/// based on the extension of the \a filename argument. * based on the extension of the \a filename argument.
*
// This is a stripped down version of the gxrio library from * This is a stripped down version of the gxrio library from
// https://github.com/mhekkel/gxrio.git * https://github.com/mhekkel/gxrio.git
// Most notably, the lzma support has been removed since getting * Most notably, the lzma support has been removed since getting
// that to work in Windows proved to be too much work. * that to work in Windows proved to be too much work.
*/
namespace cif::gzio namespace cif::gzio
{ {
/** The default buffer size to use */
const size_t kDefaultBufferSize = 256; const size_t kDefaultBufferSize = 256;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -50,6 +52,8 @@ template <typename CharT, typename Traits> ...@@ -50,6 +52,8 @@ template <typename CharT, typename Traits>
class basic_streambuf : public std::basic_streambuf<CharT, Traits> class basic_streambuf : public std::basic_streambuf<CharT, Traits>
{ {
public: public:
/** @cond */
using char_type = CharT; using char_type = CharT;
using traits_type = Traits; using traits_type = Traits;
...@@ -77,14 +81,21 @@ class basic_streambuf : public std::basic_streambuf<CharT, Traits> ...@@ -77,14 +81,21 @@ class basic_streambuf : public std::basic_streambuf<CharT, Traits>
return *this; return *this;
} }
/** @endcond */
/** Set the upstream streambuf to @a upstream */
void set_upstream(streambuf_type *upstream) void set_upstream(streambuf_type *upstream)
{ {
m_upstream = upstream; m_upstream = upstream;
} }
/** @cond */
virtual basic_streambuf *init(streambuf_type *sb) = 0; virtual basic_streambuf *init(streambuf_type *sb) = 0;
virtual basic_streambuf *close() = 0; virtual basic_streambuf *close() = 0;
/** @endcond */
protected: protected:
/// \brief The upstream streambuf object, usually this is a basic_filebuf /// \brief The upstream streambuf object, usually this is a basic_filebuf
streambuf_type *m_upstream = nullptr; streambuf_type *m_upstream = nullptr;
...@@ -105,6 +116,8 @@ template <typename CharT, typename Traits, size_t BufferSize = kDefaultBufferSiz ...@@ -105,6 +116,8 @@ template <typename CharT, typename Traits, size_t BufferSize = kDefaultBufferSiz
class basic_igzip_streambuf : public basic_streambuf<CharT, Traits> class basic_igzip_streambuf : public basic_streambuf<CharT, Traits>
{ {
public: public:
/** @cond */
static_assert(sizeof(CharT) == 1, "Unfortunately, support for wide characters is not implemented yet."); static_assert(sizeof(CharT) == 1, "Unfortunately, support for wide characters is not implemented yet.");
using char_type = CharT; using char_type = CharT;
...@@ -121,6 +134,8 @@ class basic_igzip_streambuf : public basic_streambuf<CharT, Traits> ...@@ -121,6 +134,8 @@ class basic_igzip_streambuf : public basic_streambuf<CharT, Traits>
basic_igzip_streambuf(const basic_igzip_streambuf &) = delete; basic_igzip_streambuf(const basic_igzip_streambuf &) = delete;
/** @endcond */
/// \brief Move constructor /// \brief Move constructor
basic_igzip_streambuf(basic_igzip_streambuf &&rhs) basic_igzip_streambuf(basic_igzip_streambuf &&rhs)
: base_type(std::move(rhs)) : base_type(std::move(rhs))
...@@ -141,6 +156,8 @@ class basic_igzip_streambuf : public basic_streambuf<CharT, Traits> ...@@ -141,6 +156,8 @@ class basic_igzip_streambuf : public basic_streambuf<CharT, Traits>
} }
} }
/** @cond */
basic_igzip_streambuf &operator=(const basic_igzip_streambuf &) = delete; basic_igzip_streambuf &operator=(const basic_igzip_streambuf &) = delete;
/// \brief Move operator= implementation /// \brief Move operator= implementation
...@@ -171,6 +188,8 @@ class basic_igzip_streambuf : public basic_streambuf<CharT, Traits> ...@@ -171,6 +188,8 @@ class basic_igzip_streambuf : public basic_streambuf<CharT, Traits>
close(); close();
} }
/** @endcond */
/// \brief This closes the zlib stream and sets the get pointers to null. /// \brief This closes the zlib stream and sets the get pointers to null.
base_type *close() override base_type *close() override
{ {
...@@ -302,6 +321,8 @@ template <typename CharT, typename Traits, size_t BufferSize = kDefaultBufferSiz ...@@ -302,6 +321,8 @@ template <typename CharT, typename Traits, size_t BufferSize = kDefaultBufferSiz
class basic_ogzip_streambuf : public basic_streambuf<CharT, Traits> class basic_ogzip_streambuf : public basic_streambuf<CharT, Traits>
{ {
public: public:
/** @cond */
static_assert(sizeof(CharT) == 1, "Unfortunately, support for wide characters is not implemented yet."); static_assert(sizeof(CharT) == 1, "Unfortunately, support for wide characters is not implemented yet.");
using char_type = CharT; using char_type = CharT;
...@@ -332,6 +353,8 @@ class basic_ogzip_streambuf : public basic_streambuf<CharT, Traits> ...@@ -332,6 +353,8 @@ class basic_ogzip_streambuf : public basic_streambuf<CharT, Traits>
basic_ogzip_streambuf &operator=(const basic_ogzip_streambuf &) = delete; basic_ogzip_streambuf &operator=(const basic_ogzip_streambuf &) = delete;
/** @endcond */
/// \brief Move operator= /// \brief Move operator=
basic_ogzip_streambuf &operator=(basic_ogzip_streambuf &&rhs) basic_ogzip_streambuf &operator=(basic_ogzip_streambuf &&rhs)
{ {
...@@ -487,6 +510,8 @@ template <typename CharT, typename Traits> ...@@ -487,6 +510,8 @@ template <typename CharT, typename Traits>
class basic_istream : public std::basic_istream<CharT, Traits> class basic_istream : public std::basic_istream<CharT, Traits>
{ {
public: public:
/** @cond */
using base_type = std::basic_istream<CharT, Traits>; using base_type = std::basic_istream<CharT, Traits>;
using traits_type = Traits; using traits_type = Traits;
...@@ -498,6 +523,8 @@ class basic_istream : public std::basic_istream<CharT, Traits> ...@@ -498,6 +523,8 @@ class basic_istream : public std::basic_istream<CharT, Traits>
using gzip_streambuf_type = basic_igzip_streambuf<char_type, traits_type>; using gzip_streambuf_type = basic_igzip_streambuf<char_type, traits_type>;
/** @endcond */
/// \brief Regular move constructor /// \brief Regular move constructor
basic_istream(basic_istream &&rhs) basic_istream(basic_istream &&rhs)
: base_type(std::move(rhs)) : base_type(std::move(rhs))
...@@ -591,6 +618,8 @@ template <typename CharT, typename Traits> ...@@ -591,6 +618,8 @@ template <typename CharT, typename Traits>
class basic_ifstream : public basic_istream<CharT, Traits> class basic_ifstream : public basic_istream<CharT, Traits>
{ {
public: public:
/** @cond */
using base_type = basic_istream<CharT, Traits>; using base_type = basic_istream<CharT, Traits>;
using char_type = CharT; using char_type = CharT;
...@@ -608,6 +637,8 @@ class basic_ifstream : public basic_istream<CharT, Traits> ...@@ -608,6 +637,8 @@ class basic_ifstream : public basic_istream<CharT, Traits>
close(); close();
} }
/** @endcond */
/// \brief Construct an ifstream /// \brief Construct an ifstream
/// \param filename Null terminated string specifying the file to open /// \param filename Null terminated string specifying the file to open
/// \param mode The mode in which to open the file /// \param mode The mode in which to open the file
...@@ -647,10 +678,13 @@ class basic_ifstream : public basic_istream<CharT, Traits> ...@@ -647,10 +678,13 @@ class basic_ifstream : public basic_istream<CharT, Traits>
this->rdbuf(&m_filebuf); this->rdbuf(&m_filebuf);
} }
/** @cond */
basic_ifstream(const basic_ifstream &) = delete; basic_ifstream(const basic_ifstream &) = delete;
basic_ifstream &operator=(const basic_ifstream &) = delete; basic_ifstream &operator=(const basic_ifstream &) = delete;
/** @endcond */
/// \brief Move version of operator= /// \brief Move version of operator=
basic_ifstream &operator=(basic_ifstream &&rhs) basic_ifstream &operator=(basic_ifstream &&rhs)
{ {
...@@ -777,6 +811,8 @@ template <typename CharT, typename Traits> ...@@ -777,6 +811,8 @@ template <typename CharT, typename Traits>
class basic_ostream : public std::basic_ostream<CharT, Traits> class basic_ostream : public std::basic_ostream<CharT, Traits>
{ {
public: public:
/** @cond */
using base_type = std::basic_ostream<CharT, Traits>; using base_type = std::basic_ostream<CharT, Traits>;
using char_type = CharT; using char_type = CharT;
...@@ -785,6 +821,8 @@ class basic_ostream : public std::basic_ostream<CharT, Traits> ...@@ -785,6 +821,8 @@ class basic_ostream : public std::basic_ostream<CharT, Traits>
using z_streambuf_type = basic_streambuf<char_type, traits_type>; using z_streambuf_type = basic_streambuf<char_type, traits_type>;
using upstreambuf_type = std::basic_streambuf<char_type, traits_type>; using upstreambuf_type = std::basic_streambuf<char_type, traits_type>;
/** @endcond */
/// \brief Regular move constructor /// \brief Regular move constructor
basic_ostream(basic_ostream &&rhs) basic_ostream(basic_ostream &&rhs)
: base_type(std::move(rhs)) : base_type(std::move(rhs))
...@@ -846,6 +884,8 @@ template <typename CharT, typename Traits> ...@@ -846,6 +884,8 @@ template <typename CharT, typename Traits>
class basic_ofstream : public basic_ostream<CharT, Traits> class basic_ofstream : public basic_ostream<CharT, Traits>
{ {
public: public:
/** @cond */
using base_type = basic_ostream<CharT, Traits>; using base_type = basic_ostream<CharT, Traits>;
using char_type = CharT; using char_type = CharT;
...@@ -861,6 +901,8 @@ class basic_ofstream : public basic_ostream<CharT, Traits> ...@@ -861,6 +901,8 @@ class basic_ofstream : public basic_ostream<CharT, Traits>
close(); close();
} }
/** @endcond */
/// \brief Construct an ofstream /// \brief Construct an ofstream
/// \param filename Null terminated string specifying the file to open /// \param filename Null terminated string specifying the file to open
/// \param mode The mode in which to open the file /// \param mode The mode in which to open the file
...@@ -899,10 +941,14 @@ class basic_ofstream : public basic_ostream<CharT, Traits> ...@@ -899,10 +941,14 @@ class basic_ofstream : public basic_ostream<CharT, Traits>
this->rdbuf(&m_filebuf); this->rdbuf(&m_filebuf);
} }
/** @cond */
basic_ofstream(const basic_ofstream &) = delete; basic_ofstream(const basic_ofstream &) = delete;
basic_ofstream &operator=(const basic_ofstream &) = delete; basic_ofstream &operator=(const basic_ofstream &) = delete;
/** @endcond */
/// \brief Move operator= /// \brief Move operator=
basic_ofstream &operator=(basic_ofstream &&rhs) basic_ofstream &operator=(basic_ofstream &&rhs)
{ {
...@@ -1032,11 +1078,13 @@ class basic_ofstream : public basic_ostream<CharT, Traits> ...@@ -1032,11 +1078,13 @@ class basic_ofstream : public basic_ostream<CharT, Traits>
// -------------------------------------------------------------------- // --------------------------------------------------------------------
/// \brief Convenience typedefs /// \brief Convenience typedef for a regular istream
using istream = basic_istream<char, std::char_traits<char>>; using istream = basic_istream<char, std::char_traits<char>>;
/// \brief Convenience typedef for a file ifstream
using ifstream = basic_ifstream<char, std::char_traits<char>>; using ifstream = basic_ifstream<char, std::char_traits<char>>;
// using ostream = basic_ostream<char, std::char_traits<char>>; /// \brief Convenience typedef for a file ofstream
using ofstream = basic_ofstream<char, std::char_traits<char>>; using ofstream = basic_ofstream<char, std::char_traits<char>>;
} // namespace gzio } // namespace gzio
...@@ -41,16 +41,18 @@ ...@@ -41,16 +41,18 @@
#include <optional> #include <optional>
#include <utility> #include <utility>
/// \file item.hpp /** \file item.hpp
/// This file contains the declaration of item but also the item_value and item_handle *
/// These handle the storage of and access to the data for a single data field. * This file contains the declaration of item but also the item_value and item_handle
* These handle the storage of and access to the data for a single data field.
*/
namespace cif namespace cif
{ {
// -------------------------------------------------------------------- // --------------------------------------------------------------------
/// \brief item is a transient class that is used to pass data into rows /// \brief item is a transient class that is used to pass data into rows
/// but it also takes care of formatting data. /// but it also takes care of formatting data.
class item class item
{ {
public: public:
...@@ -109,7 +111,7 @@ class item ...@@ -109,7 +111,7 @@ class item
/// \brief constructor for an item with name \a name and as /// \brief constructor for an item with name \a name and as
/// content a the formatted integral value \a value /// content a the formatted integral value \a value
template <typename T, std::enable_if_t<std::is_integral_v<T> and not std::is_same_v<T,bool>, int> = 0> template <typename T, std::enable_if_t<std::is_integral_v<T> and not std::is_same_v<T, bool>, int> = 0>
item(const std::string_view name, const T &value) item(const std::string_view name, const T &value)
: m_name(name) : m_name(name)
{ {
...@@ -126,7 +128,7 @@ class item ...@@ -126,7 +128,7 @@ class item
/// \brief constructor for an item with name \a name and as /// \brief constructor for an item with name \a name and as
/// content a the formatted boolean value \a value /// content a the formatted boolean value \a value
template <typename T, std::enable_if_t<std::is_same_v<T,bool>, int> = 0> template <typename T, std::enable_if_t<std::is_same_v<T, bool>, int> = 0>
item(const std::string_view name, const T &value) item(const std::string_view name, const T &value)
: m_name(name) : m_name(name)
{ {
...@@ -141,16 +143,15 @@ class item ...@@ -141,16 +143,15 @@ class item
{ {
} }
/** @cond */
item(const item &rhs) = default; item(const item &rhs) = default;
item(item &&rhs) noexcept = default; item(item &&rhs) noexcept = default;
item &operator=(const item &rhs) = default; item &operator=(const item &rhs) = default;
item &operator=(item &&rhs) noexcept = default; item &operator=(item &&rhs) noexcept = default;
/** @endcond */
std::string_view name() const { return m_name; } std::string_view name() const { return m_name; } ///< Return the name of the item
std::string_view value() const { return m_value; } std::string_view value() const { return m_value; } ///< Return the value of the item
/// \brief replace the content of the stored value with \a v /// \brief replace the content of the stored value with \a v
void value(std::string_view v) { m_value = v; } void value(std::string_view v) { m_value = v; }
...@@ -168,11 +169,13 @@ class item ...@@ -168,11 +169,13 @@ class item
size_t length() const { return m_value.length(); } size_t length() const { return m_value.length(); }
/// \brief support for structured binding /// \brief support for structured binding
template<size_t N> template <size_t N>
decltype(auto) get() const decltype(auto) get() const
{ {
if constexpr (N == 0) return name(); if constexpr (N == 0)
else if constexpr (N == 1) return value(); return name();
else if constexpr (N == 1)
return value();
} }
private: private:
...@@ -190,7 +193,9 @@ class item ...@@ -190,7 +193,9 @@ class item
struct item_value struct item_value
{ {
/** @cond */
item_value() = default; item_value() = default;
/** @endcond */
/// \brief constructor /// \brief constructor
item_value(std::string_view text) item_value(std::string_view text)
...@@ -210,6 +215,7 @@ struct item_value ...@@ -210,6 +215,7 @@ struct item_value
} }
} }
/** @cond */
item_value(item_value &&rhs) item_value(item_value &&rhs)
: 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))
...@@ -236,24 +242,29 @@ struct item_value ...@@ -236,24 +242,29 @@ struct item_value
item_value(const item_value &) = delete; item_value(const item_value &) = delete;
item_value &operator=(const item_value &) = delete; item_value &operator=(const item_value &) = delete;
/** @endcond */
/** operator bool, allows easy checking for empty items */
explicit operator bool() const explicit operator bool() const
{ {
return m_length != 0; return m_length != 0;
} }
size_t m_length = 0; size_t m_length = 0; ///< Length of the data
union union
{ {
char m_local_data[8]; char m_local_data[8]; ///< Storage area for small strings (strings smaller than kBufferSize)
char *m_data; char *m_data; ///< Pointer to a string stored in the heap
uint64_t m_storage; uint64_t m_storage; ///< Alternative storage of the data, used in move operations
}; };
/** The maximum length of locally stored strings */
static constexpr size_t kBufferSize = sizeof(m_local_data); static constexpr size_t kBufferSize = sizeof(m_local_data);
// By using std::string_view instead of c_str we obain a // By using std::string_view instead of c_str we obain a
// nice performance gain since we avoid many calls to strlen. // nice performance gain since we avoid many calls to strlen.
/** Return the content of the item as a std::string_view */
constexpr inline std::string_view text() const constexpr inline std::string_view text() const
{ {
return { m_length >= kBufferSize ? m_data : m_local_data, m_length }; return { m_length >= kBufferSize ? m_data : m_local_data, m_length };
...@@ -268,6 +279,7 @@ struct item_value ...@@ -268,6 +279,7 @@ struct item_value
struct item_handle struct item_handle
{ {
public: public:
/** @cond */
// conversion helper class // conversion helper class
template <typename T, typename = void> template <typename T, typename = void>
struct item_value_as; struct item_value_as;
...@@ -279,7 +291,22 @@ struct item_handle ...@@ -279,7 +291,22 @@ struct item_handle
assign_value(v); assign_value(v);
return *this; return *this;
} }
/** @endcond */
/**
* @brief A method with a variable number of arguments that will be concatenated and
* assigned as a string. Use it like this:
*
* @code{.cpp}
* cif::item_handle ih;
* is.os("The result of ", 1, " * ", 42, " is of course ", 42);
* @endcode
*
* And the content will then be `The result of 1 * 42 is of course 42`.
*
* @tparam Ts Types of the parameters
* @param v The parameters to concatenate
*/
template <typename... Ts> template <typename... Ts>
void os(const Ts &...v) void os(const Ts &...v)
{ {
...@@ -288,8 +315,10 @@ struct item_handle ...@@ -288,8 +315,10 @@ struct item_handle
this->operator=(ss.str()); this->operator=(ss.str());
} }
/** Swap contents of this and @a b */
void swap(item_handle &b); void swap(item_handle &b);
/** Return the contents of this item as type @tparam T */
template <typename T = std::string> template <typename T = std::string>
auto as() const -> T auto as() const -> T
{ {
...@@ -297,18 +326,36 @@ struct item_handle ...@@ -297,18 +326,36 @@ struct item_handle
return item_value_as<value_type>::convert(*this); return item_value_as<value_type>::convert(*this);
} }
/** Return the contents of this item as type @tparam T or, if not
* set, use @a dv as the default value.
*/
template <typename T> template <typename T>
auto value_or(const T &dv) const auto value_or(const T &dv) const
{ {
return empty() ? dv : this->as<T>(); return empty() ? dv : this->as<T>();
} }
/**
* @brief Compare the contents of this item with value @a value
* optionally ignoring character case, if @a icase is true.
* Returns 0 if both are equal, -1 if this sorts before @a value
* and 1 if this sorts after @a value
*
* @tparam T Type of the value @a value
* @param value The value to compare with
* @param icase Flag indicating if we should compare character case sensitive
* @return -1, 0 or 1
*/
template <typename T> template <typename T>
int compare(const T &value, bool icase = true) const int compare(const T &value, bool icase = true) const
{ {
return item_value_as<T>::compare(*this, value, icase); return item_value_as<T>::compare(*this, value, icase);
} }
/**
* @brief Compare the value contained with the value @a value and
* return true if both are equal.
*/
template <typename T> template <typename T>
bool operator==(const T &value) const bool operator==(const T &value) const
{ {
...@@ -323,39 +370,53 @@ struct item_handle ...@@ -323,39 +370,53 @@ struct item_handle
return not operator==(value); return not operator==(value);
} }
// empty means either null or unknown /**
* @brief Returns true if the content string is empty or
* only contains '.' meaning null or '?' meaning unknown
* in a mmCIF context
*/
bool empty() const bool empty() const
{ {
auto txt = text(); auto txt = text();
return txt.empty() or (txt.length() == 1 and (txt.front() == '.' or txt.front() == '?')); return txt.empty() or (txt.length() == 1 and (txt.front() == '.' or txt.front() == '?'));
} }
/** Easy way to test for an empty item */
explicit operator bool() const { return not empty(); } explicit operator bool() const { return not empty(); }
// is_null means the field contains '.' /// is_null return true if the field contains '.'
bool is_null() const bool is_null() const
{ {
auto txt = text(); auto txt = text();
return txt.length() == 1 and txt.front() == '.'; return txt.length() == 1 and txt.front() == '.';
} }
// is_unknown means the field contains '?' /// is_unknown returns true if the field contains '?'
bool is_unknown() const bool is_unknown() const
{ {
auto txt = text(); auto txt = text();
return txt.length() == 1 and txt.front() == '?'; return txt.length() == 1 and txt.front() == '?';
} }
/** Return a std::string_view for the contents */
std::string_view text() const; std::string_view text() const;
/**
* @brief Construct a new item handle object
*
* @param column Column index
* @param row Reference to the row
*/
item_handle(uint16_t column, row_handle &row) item_handle(uint16_t column, row_handle &row)
: m_column(column) : m_column(column)
, m_row_handle(row) , m_row_handle(row)
{ {
} }
static CIFPP_EXPORT const item_handle s_null_item; /** A variable holding an empty item */
CIFPP_EXPORT static const item_handle s_null_item;
/** friend to swap two item handles */
friend void swap(item_handle a, item_handle b) friend void swap(item_handle a, item_handle b)
{ {
a.swap(b); a.swap(b);
...@@ -372,6 +433,7 @@ struct item_handle ...@@ -372,6 +433,7 @@ struct item_handle
// So sad that older gcc implementations of from_chars did not support floats yet... // So sad that older gcc implementations of from_chars did not support floats yet...
/** @cond */
template <typename T> template <typename T>
struct item_handle::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T> and not std::is_same_v<T, bool>>> struct item_handle::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T> and not std::is_same_v<T, bool>>>
{ {
...@@ -546,22 +608,33 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_same_v<T, std::str ...@@ -546,22 +608,33 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_same_v<T, std::str
} }
}; };
/** @endcond */
} // namespace cif } // namespace cif
namespace std namespace std
{ {
template<> struct tuple_size<::cif::item> /** @cond */
: public std::integral_constant<std::size_t, 2> {};
template <>
struct tuple_size<::cif::item>
: public std::integral_constant<std::size_t, 2>
{
};
template<> struct tuple_element<0, ::cif::item> template <>
struct tuple_element<0, ::cif::item>
{ {
using type = decltype(std::declval<::cif::item>().name()); using type = decltype(std::declval<::cif::item>().name());
}; };
template<> struct tuple_element<1, ::cif::item> template <>
struct tuple_element<1, ::cif::item>
{ {
using type = decltype(std::declval<::cif::item>().value()); using type = decltype(std::declval<::cif::item>().value());
}; };
} /** @endcond */
\ No newline at end of file
} // namespace std
\ No newline at end of file
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