# Class category

- Defined in File category.hpp

## Nested Relationships

### Nested Types

- Struct category::item_entry

- Struct category::key_element_type

- Struct category::link

## Class Documentation

class category

  The class category is a sequence container for rows of data values. You could think of it as a std::vector<cif::row_handle> like class.

  A category_validator can be assigned to an object of category after which this class can validate contained data and use an index to keep key values unique.

  Public Types

  enum class output_format

    Various supported output formats.

    Values:

    enumerator cif
    enumerator csv
    enumerator tsv
    enumerator list
    enumerator column
    enumerator markdown
    enumerator table
    enumerator box
  using key_type = std::vector<key_element_type>

    The key type.

  using value_provider_type = std::function<item_value(const item_value&)>

    The type for a function that provides a value to insert based on a value that is the default or the previous value

  Public Functions

  category() = default

    Default constructor.

  category(std::string_view name)

    Constructor taking a name.

  inline category(std::string_view name, row_initializer &&rows)

    Constructor creating a category named name and filled with rows.

    Parameters:

      - name – Name for the new category

      - rows – The data stored in the category

  category(const category &rhs)

    Copy constructor.

  inline category(category &&rhs) noexcept

    < Move constructor

  inline category &operator=(category rhs)

    Assignment operator.

  ~category()

    Destructor.

    Note

    Please note that the destructor is not virtual. It is assumed that you will not derive from this class.

  inline const std::string &name() const

    Returns the name of the category.

  inline void name(std::string_view new_name)

    Rename category to new_name.

  inline bool is_dirty() const

    Return true if the category has been modified since last open/save.

  inline void set_dirty(bool dirty)

    Mark the category as modified according to dirty.

  iset key_fields() const

    Returns the cif::iset of key item names. Retrieved from the category_validator for this category.

  iset key_items() const

    Returns the cif::iset of key item names. Retrieved from the category_validator for this category.

  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.

  void set_validator(const validator *v, datablock &db)

    Set the validator for this category to v.

    Parameters:

      - v – The category_validator to assign. A nullptr value is allowed.

      - db – The enclosing datablock

  void update_links(const datablock &db)

    Update the links in this category.

    Parameters:

      db – The enclosing datablock

  inline const validator *get_validator() const

    Return the global validator for the data.

    Returns:

      The validator or nullptr if not assigned

  inline const category_validator *get_cat_validator() const

    Return the category validator for this category.

    Returns:

      The category_validator or nullptr if not assigned

  bool is_valid() const

    Validate the data stored using the assigned category_validator.

    Returns:

      Returns true is all validations pass

  bool validate_links() const

    Validate links, that means, values in this category should have an accompanying value in parent categories.

    Note

    The code makes one exception when validating missing links and that’s between atom_site and a parent pdbx_poly_seq_scheme or entity_poly_seq. This particular case should be skipped because it is wrong: there are atoms that are not part of a polymer, and thus will have no parent in those categories.

    Returns:

      Returns true is all validations pass

  void strip()

    Strip removes items from this category that are invalid according to the assigned validator.

  bool operator==(const category &rhs) const

    Equality operator, returns true if rhs is equal to this.

    Parameters:

      rhs – The object to compare with

    Returns:

      True if the data contained is equal

  inline bool operator!=(const category &rhs) const

    Unequality operator, returns true if rhs is not equal to this.

    Parameters:

      rhs – The object to compare with

    Returns:

      True if the data contained is not equal

  inline reference front()

    Return a reference to the first row in this category.

    Returns:

      Reference to the first row in this category. The result is undefined if the category is empty.

  inline const_reference front() const

    Return a const reference to the first row in this category.

    Returns:

      const reference to the first row in this category. The result is undefined if the category is empty.

  inline reference back()

    Return a reference to the last row in this category.

    Returns:

      Reference to the last row in this category. The result is undefined if the category is empty.

  inline const_reference back() const

    Return a const reference to the last row in this category.

    Returns:

      const reference to the last row in this category. The result is undefined if the category is empty.

  inline iterator begin()

    Return an iterator to the first row.

  inline iterator end()

    Return an iterator pointing past the last row.

  inline const_iterator begin() const

    Return a const iterator to the first row.

  inline const_iterator end() const

    Return a const iterator pointing past the last row.

  inline const_iterator cbegin() const

    Return a const iterator to the first row.

  inline const_iterator cend() const

    Return an iterator pointing past the last row.

  inline std::size_t size() const

    Return a count of the rows in this container.

  inline std::size_t max_size() const

    Return the theoretical maximum number or rows that can be stored.

  inline bool empty() const

    Return true if the category is empty.

  row_handle operator[](const key_type &key)

    Return a row_handle for the row specified by key.

    Parameters:

      key – The value for the key, items specified in the dictionary should have a value

    Returns:

      The row found in the index, or an undefined row_handle

  const_row_handle operator[](const key_type &key) const

    Return a const_row_handle for the row specified by key.

    Parameters:

      key – The value for the key, items specified in the dictionary should have a value

    Returns:

      The row found in the index, or an undefined row_handle

  template<typename ...Ts, typename ...Ns>
  inline const_iterator_proxy<Ts...> rows(Ns... names) const

    Return a special const iterator for all rows in this category. This iterator can be used in a structured binding context. E.g.:

        for (const auto &[name, value] : cat.rows<std::string,int>("item_name", "item_value"))
          std::cout << name << ": " << value << '\n';

    Template Parameters:

      Ts – The types for the items requested

    Parameters:

      names – The names for the items requested

  template<typename ...Ts, typename ...Ns>
  inline iterator_proxy<Ts...> rows(Ns... names)

    Return a special iterator for all rows in this category. This iterator can be used in a structured binding context. E.g.:

        for (const auto &[name, value] : cat.rows<std::string,int>("item_name", "item_value"))
          std::cout << name << ": " << value << '\n';

        // or in case we only need one item:

        for (int id : cat.rows<int>("id"))
          std::cout << id << '\n';

    Template Parameters:

      Ts – The types for the items requested

    Parameters:

      names – The names for the items requested

  inline conditional_iterator_proxy find(condition &&cond)

    Return a special iterator to loop over all rows that conform to cond.

        for (row_handle rh : cat.find(cif::key("first_name") == "John" and cif::key("last_name") == "Doe"))
           .. // do something with rh

    Parameters:

      cond – The condition for the query

    Returns:

      A special iterator that loops over all elements that match. The iterator can be dereferenced to a row_handle

  inline conditional_iterator_proxy find(iterator pos, condition &&cond)

    Return a special iterator to loop over all rows that conform to cond starting at pos.

    Parameters:

      - pos – Where to start searching

      - cond – The condition for the query

    Returns:

      A special iterator that loops over all elements that match. The iterator can be dereferenced to a row_handle

  inline const_conditional_iterator_proxy find(condition &&cond) const

    Return a special const iterator to loop over all rows that conform to cond.

    Parameters:

      cond – The condition for the query

    Returns:

      A special iterator that loops over all elements that match. The iterator can be dereferenced to a const row_handle

  inline const_conditional_iterator_proxy find(const_iterator pos, condition &&cond) const

    Return a special const iterator to loop over all rows that conform to cond starting at pos.

    Parameters:

      - pos – Where to start searching

      - cond – The condition for the query

    Returns:

      A special iterator that loops over all elements that match. The iterator can be dereferenced to a const row_handle

  template<typename ...Ts, typename ...Ns>
  inline conditional_iterator_proxy<Ts...> find(condition &&cond, Ns... names)

    Return a special iterator to loop over all rows that conform to cond. The resulting iterator can be used in a structured binding context.

        for (const auto &[name, value] : cat.find<std::string,int>(cif::key("item_value") > 10, "item_name", "item_value"))
           std::cout << name << ": " << value << '\n';

    Parameters:

      - cond – The condition for the query

      - names – The names for the items requested

    Template Parameters:

      Ts – The types for the items requested

    Returns:

      A special iterator that loops over all elements that match.

  template<typename ...Ts, typename ...Ns>
  inline const_conditional_iterator_proxy<Ts...> find(condition &&cond, Ns... names) const

    Return a special const iterator to loop over all rows that conform to cond. The resulting iterator can be used in a structured binding context.

    Parameters:

      - cond – The condition for the query

      - names – The names for the items requested

    Template Parameters:

      Ts – The types for the items requested

    Returns:

      A special iterator that loops over all elements that match.

  template<typename ...Ts, typename ...Ns>
  inline conditional_iterator_proxy<Ts...> find(iterator pos, condition &&cond, Ns... names)

    Return a special iterator to loop over all rows that conform to cond starting at pos. The resulting iterator can be used in a structured binding context.

    Parameters:

      - pos – Iterator pointing to the location where to start

      - cond – The condition for the query

      - names – The names for the items requested

    Template Parameters:

      Ts – The types for the items requested

    Returns:

      A special iterator that loops over all elements that match.

  template<typename ...Ts, typename ...Ns>
  inline const_conditional_iterator_proxy<Ts...> find(const_iterator pos, condition &&cond, Ns... names) const

    Return a special const iterator to loop over all rows that conform to cond starting at pos. The resulting iterator can be used in a structured binding context.

    Parameters:

      - pos – Iterator pointing to the location where to start

      - cond – The condition for the query

      - names – The names for the items requested

    Template Parameters:

      Ts – The types for the items requested

    Returns:

      A special iterator that loops over all elements that match.

  inline row_handle find1(condition &&cond)

    Return the row handle for the row that matches cond Throws multiple_results_error if there are is not exactly one row matching cond.

    Parameters:

      cond – The condition to search for

    Returns:

      Row handle to the row found

  inline row_handle find1(iterator pos, condition &&cond)

    Return the row handle for the row that matches cond starting at pos Throws multiple_results_error if there are is not exactly one row matching cond.

    Parameters:

      - pos – The position to start the search

      - cond – The condition to search for

    Returns:

      Row handle to the row found

  inline const_row_handle find1(condition &&cond) const

    Return the const row handle for the row that matches cond Throws multiple_results_error if there are is not exactly one row matching cond.

    Parameters:

      cond – The condition to search for

    Returns:

      Row handle to the row found

  inline const_row_handle find1(const_iterator pos, condition &&cond) const

    Return const the row handle for the row that matches cond starting at pos Throws multiple_results_error if there are is not exactly one row matching cond.

    Parameters:

      - pos – The position to start the search

      - cond – The condition to search for

    Returns:

      Row handle to the row found

  template<typename T>
  inline T find1(condition &&cond, std::string_view item) const

    Return value for the item named item for the single row that matches cond. Throws multiple_results_error if there are is not exactly one row.

    Template Parameters:

      The – type to use for the result

    Parameters:

      - cond – The condition to search for

      - item – The name of the item to return the value for

    Returns:

      The value found

  template<typename T>
  inline T find1(condition &&cond, std::string_view item) const

    Return value for the item named item for the single row that matches cond. Throws multiple_results_error if there are is not exactly one row.

    Template Parameters:

      The – type to use for the result

    Parameters:

      - cond – The condition to search for

      - item – The name of the item to return the value for

    Returns:

      The value found

  template<typename T>
  inline T find1(const_iterator pos, condition &&cond, std::string_view item) const

    Return value for the item named item for the single row that matches cond when starting to search at pos. Throws multiple_results_error if there are is not exactly one row.

    Template Parameters:

      The – type to use for the result

    Parameters:

      - pos – The location to start the search

      - cond – The condition to search for

      - item – The name of the item to return the value for

    Returns:

      The value found

  template<typename T>
  inline T find1(const_iterator pos, condition &&cond, std::string_view item) const

    Return a value of type std::optional<T> for the item named item for the single row that matches cond when starting to search at pos. If the row was not found, an empty value is returned.

    Template Parameters:

      The – type to use for the result

    Parameters:

      - pos – The location to start the search

      - cond – The condition to search for

      - item – The name of the item to return the value for

    Returns:

      The value found, can be empty if no row matches the condition

  template<typename ...Ts, typename ...Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
  inline std::tuple<Ts...> find1(condition &&cond, Cs... items) const

    Return a std::tuple for the values for the items named in items for the single row that matches cond Throws multiple_results_error if there are is not exactly one row.

    Template Parameters:

      The – types to use for the resulting tuple

    Parameters:

      - cond – The condition to search for

      - items – The names of the items to return the value for

    Returns:

      The values found as a single tuple of type std::tuple<Ts…>

  template<typename ...Ts, typename ...Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
  inline std::tuple<Ts...> find1(const_iterator pos, condition &&cond, Cs... items) const

    Return a std::tuple for the values for the items named in items for the single row that matches cond when starting to search at pos Throws multiple_results_error if there are is not exactly one row.

    Template Parameters:

      The – types to use for the resulting tuple

    Parameters:

      - pos – The location to start the search

      - cond – The condition to search for

      - items – The names of the items to return the value for

    Returns:

      The values found as a single tuple of type std::tuple<Ts…>

  inline row_handle find_first(condition &&cond)

    Return a row handle to the first row that matches cond.

    Parameters:

      cond – The condition to search for

    Returns:

      The handle to the row that matches or an empty row_handle

  inline row_handle find_first(iterator pos, condition &&cond)

    Return a row handle to the first row that matches cond starting at pos.

    Parameters:

      - pos – The location to start searching

      - cond – The condition to search for

    Returns:

      The handle to the row that matches or an empty row_handle

  inline const_row_handle find_first(condition &&cond) const

    Return a const row handle to the first row that matches cond.

    Parameters:

      cond – The condition to search for

    Returns:

      The const handle to the row that matches or an empty row_handle

  inline const_row_handle find_first(const_iterator pos, condition &&cond) const

    Return a const row handle to the first row that matches cond starting at pos.

    Parameters:

      - pos – The location to start searching

      - cond – The condition to search for

    Returns:

      The const handle to the row that matches or an empty row_handle

  template<typename T>
  inline T find_first(condition &&cond, std::string_view item) const

    Return the value for item item for the first row that matches condition cond.

    Template Parameters:

      The – type of the value to return

    Parameters:

      - cond – The condition to search for

      - item – The item for which the value should be returned

    Returns:

      The value found or a default constructed value if not found

  template<typename T>
  inline T find_first(const_iterator pos, condition &&cond, std::string_view item) const

    Return the value for item item for the first row that matches condition cond when starting the search at pos.

    Template Parameters:

      The – type of the value to return

    Parameters:

      - pos – The location to start searching

      - cond – The condition to search for

      - item – The item for which the value should be returned

    Returns:

      The value found or a default constructed value if not found

  template<typename ...Ts, typename ...Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
  inline std::tuple<Ts...> find_first(condition &&cond, Cs... items) const

    Return a tuple containing the values for the items items for the first row that matches condition cond.

    Template Parameters:

      The – types of the values to return

    Parameters:

      - cond – The condition to search for

      - items – The items for which the values should be returned

    Returns:

      The values found or default constructed values if not found

  template<typename ...Ts, typename ...Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
  inline std::tuple<Ts...> find_first(const_iterator pos, condition &&cond, Cs... items) const

    Return a tuple containing the values for the items items for the first row that matches condition cond when starting the search at pos.

    Template Parameters:

      The – types of the values to return

    Parameters:

      - pos – The location to start searching

      - cond – The condition to search for

      - items – The items for which the values should be returned

    Returns:

      The values found or default constructed values if not found

  template<typename T>
  inline T find_max(std::string_view item, condition &&cond) const

    Return the maximum value for item item for all rows that match condition cond.

    Template Parameters:

      The – type of the value to return

    Parameters:

      - item – The item to use for the value

      - cond – The condition to search for

    Returns:

      The value found or the minimal value for the type

  template<typename T>
  inline T find_max(std::string_view item) const

    Return the maximum value for item item for all rows.

    Template Parameters:

      The – type of the value to return

    Parameters:

      item – The item to use for the value

    Returns:

      The value found or the minimal value for the type

  template<typename T>
  inline T find_min(std::string_view item, condition &&cond) const

    Return the minimum value for item item for all rows that match condition cond.

    Template Parameters:

      The – type of the value to return

    Parameters:

      - item – The item to use for the value

      - cond – The condition to search for

    Returns:

      The value found or the maximum value for the type

  template<typename T>
  inline T find_min(std::string_view item) const

    Return the maximum value for item item for all rows.

    Template Parameters:

      The – type of the value to return

    Parameters:

      item – The item to use for the value

    Returns:

      The value found or the maximum value for the type

  inline bool exists(condition &&cond) const

    Return whether a row exists that matches condition cond.

    Parameters:

      cond – The condition to match

    Returns:

      True if a row exists

  inline bool contains(condition &&cond) const

    Return whether a row exists that matches condition cond.

    Parameters:

      cond – The condition to match

    Returns:

      True if a row exists

  inline std::size_t count(condition &&cond) const

    Return the total number of rows that match condition cond.

    Parameters:

      cond – The condition to match

    Returns:

      The count

  bool has_children(const_row_handle r) const

    Using the relations defined in the validator, return whether the row in r has any children in other categories

  bool has_parents(const_row_handle r) const

    Using the relations defined in the validator, return whether the row in r has any parents in other categories

  std::vector<const_row_handle> get_children(const_row_handle r, const category &childCat) const

    Using the relations defined in the validator, return the row handles for all rows in childCat that are linked to row r

  std::vector<const_row_handle> get_parents(const_row_handle r, const category &parentCat) const

    Using the relations defined in the validator, return the row handles for all rows in parentCat that are linked to row r

  std::vector<const_row_handle> get_linked(const_row_handle r, const category &cat) const

    Using the relations defined in the validator, return the row handles for all rows in cat that are in any way linked to row r

  std::vector<row_handle> get_children(row_handle r, category &childCat)

    Using the relations defined in the validator, return the row handles for all rows in childCat that are linked to row r

  std::vector<row_handle> get_parents(row_handle r, category &parentCat)

    Using the relations defined in the validator, return the row handles for all rows in parentCat that are linked to row r

  std::vector<row_handle> get_linked(row_handle r, category &cat)

    Using the relations defined in the validator, return the row handles for all rows in cat that are in any way linked to row r

  iterator erase(iterator pos)

    Erase the row pointed to by pos and return the iterator to the row following pos.

  inline void erase(row_handle rh)

    Erase row rh.

  std::size_t erase(condition &&cond)

    Erase all rows that match condition cond.

    Parameters:

      cond – The condition

    Returns:

      The number of rows that have been erased

  std::size_t erase(condition &&cond, std::function<void(row_handle)> &&visit)

    Erase all rows that match condition cond calling the visitor function visit for each before actually erasing it.

    Parameters:

      - cond – The condition

      - visit – The visitor function

    Returns:

      The number of rows that have been erased

  inline iterator emplace(row_initializer &&ri)

    Emplace the values in ri in a new row.

    Parameters:

      ri – An object containing the values to insert

    Returns:

      iterator to the newly created row

  template<typename ItemIter>
  inline iterator emplace(ItemIter b, ItemIter e)

    Create a new row and emplace the values in the range b to e in it.

    Parameters:

      - b – Iterator to the beginning of the range of item_values

      - e – Iterator to the end of the range of item_values

    Returns:

      iterator to the newly created row

  inline void emplace(const_iterator b, const_iterator e)

    Create rows with the content of the data in [ b, to e).

  void clear()

    Completely erase all rows contained in this category.

  std::string get_unique_id(std::function<std::string(int)> generator = cif::cif_id_for_number)

    generate a new, unique ID. Pass it an ID generating function based on a sequence number. This function will be called until the result is unique in the context of this category

  inline std::string get_unique_id(const std::string &prefix)

    Generate a new, unique ID based on a string prefix followed by a number.

    Parameters:

      prefix – The string prefix

    Returns:

      a new unique ID

  std::string get_unique_value(std::string_view item_name)

    Generate a new, unique value for a item named item_name.

    Parameters:

      item_name – The name of the item

    Returns:

      a new unique value

  inline void update_value(condition &&cond, std::string_view item_name, value_provider_type &&value_provider)

    Update a single item named item_name in the rows that match cond to values provided by a callback function value_provider making sure the linked categories are updated according to the link. 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, value_provider_type &&value_provider)

    Update a single item named item_name in the rows rows to values provided by a callback function value_provider making sure the linked categories are updated according to the link. That means, child categories are updated if the links are absolute and unique. If they are not, the child category rows are split.

  inline void update_value(condition &&cond, std::string_view item_name, const item_value &value)

    Update a single item named item_name in the rows that match cond to value value making sure the linked categories are updated according to the link. That means, child categories are updated if the links are absolute and unique. If they are not, the child category rows are split.

  inline void update_value(const std::vector<row_handle> &rows, std::string_view item_name, const item_value &value)

    Update a single item named item_name in rows to value value making sure the linked categories are updated according to the link. That means, child categories are updated if the links are absolute and unique. If they are not, the child category rows are split.

  uint16_t get_item_ix(std::string_view item_name) const

    Return the index number for item_name.

  inline const std::string &get_item_name(uint16_t ix) const

    Return the name for item with index ix.

    Parameters:

      ix – The index number

    Returns:

      The name of the item

  uint16_t add_item(std::string_view item_name)

    Make sure a item with name item_name is known and return its index number.

    Parameters:

      item_name – The name of the item

    Returns:

      The index number of the item

  void remove_item(std::string_view item_name)

    Remove item name colum_name.

    Parameters:

      item_name – The item to be removed

  void drop_empty_items()

    Drop items in this category that contain empty values in all rows.

  void rename_item(std::string_view from_name, std::string_view to_name)

    Rename item from_name to to_name.

  inline bool has_item(std::string_view name) const

    Return whether a item with name name exists in this category.

    Parameters:

      name – The name of the item

    Returns:

      True if the item exists

  std::vector<std::string> get_items() const

    Return the items in this category.

  inline uint16_t get_item_count() const noexcept

    Return the number of items (colums) in this category.

  void sort(std::function<int(row_handle, row_handle)> f)

    Sort the rows using comparator function f.

    Parameters:

      f – The comparator function taking two row_handles and returning an int indicating whether the first is smaller, equal or larger than the second. ( respectively a value <0, 0, or >0 )

  void reorder_by_index()

    Reorder the rows in the category using the index defined by the category_validator.

  std::vector<std::string> get_item_order() const

    This function returns effectively the list of fully qualified item names, that is category_name + ‘.’ + item_name for each item

  void write(std::ostream &os) const

    Write the contents of the category to the std::ostream os.

  void write(std::ostream &os, output_format fmt, const std::vector<std::string> &order, bool addMissingItems = true)

    Write the contents of the category to the std::ostream os and use order as the order of the items. If addMissingItems is false, items that do not contain any value will be suppressed. Use this version to write out.

    Parameters:

      - os – The std::ostream to write to

      - fmt – The format to use

      - order – The order in which the items should appear

      - addMissingItems – When false, empty items are suppressed from the output

  inline void write(std::ostream &os, const std::vector<std::string> &order, bool addMissingItems = true)

    Write the contents of the category to the std::ostream os and use order as the order of the items. If addMissingItems is false, items that do not contain any value will be suppressed.

    Parameters:

      - os – The std::ostream to write to

      - order – The order in which the items should appear

      - addMissingItems – When false, empty items are suppressed from the output

  Friends

  friend void swap(category &a, category &b) noexcept

    Swap two categories.

  inline friend std::ostream &operator<<(std::ostream &os, const category &cat)

    friend function to make it possible to do:

        std::cout << my_category;

  struct key_element_type

    The type of an element of the key_type.

    Public Members

    std::string name

      Name of the item.

    item_value value

      Value to be found.

    bool may_be_null = false

      If true, value should be same or empty.