// Matrix Construct // // Copyright (C) Matrix Construct Developers, Authors & Contributors // Copyright (C) 2016-2018 Jason Volk // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. #pragma once #define HAVE_IRCD_M_DBS_CURSOR_H struct ircd::m::dbs::cursor { template struct const_iterator_base; struct const_reverse_iterator; struct const_iterator; using iterator_type = const_iterator; db::index index; const_iterator end(const string_view &key = {}); const_iterator begin(const string_view &key = {}); const_reverse_iterator rend(const string_view &key = {}); const_reverse_iterator rbegin(const string_view &key = {}); cursor(const string_view &index) :index{*dbs::events, index} {} }; template struct ircd::m::dbs::cursor::const_iterator_base { using value_type = const event; using pointer = value_type *; using reference = value_type &; using difference_type = size_t; using iterator_category = std::bidirectional_iterator_tag; index_iterator idx; std::array cell; db::row row; mutable event v; mutable bool stale{true}; bool invalid{true}; operator bool() const; bool operator!() const; bool operator==(const const_iterator_base &o) const; bool operator!=(const const_iterator_base &o) const; bool row_valid() const; string_view row_key() const; value_type &operator*() const; value_type *operator->() const; protected: bool seek_row(); public: const_iterator_base &operator++(); const_iterator_base &operator--(); const_iterator_base(); const_iterator_base(const cursor &, index_iterator, const db::gopts & = {}); }; struct ircd::m::dbs::cursor::const_iterator :const_iterator_base { using const_iterator_base::const_iterator_base; }; struct ircd::m::dbs::cursor::const_reverse_iterator :const_iterator_base { using const_iterator_base::const_iterator_base; }; // // cursor // inline ircd::m::dbs::cursor::const_reverse_iterator ircd::m::dbs::cursor::rbegin(const string_view &key) { return const_reverse_iterator { *this, index.rbegin(key), {} }; } inline ircd::m::dbs::cursor::const_reverse_iterator ircd::m::dbs::cursor::rend(const string_view &key) { return const_reverse_iterator { *this, index.rend(key), {} }; } inline ircd::m::dbs::cursor::const_iterator ircd::m::dbs::cursor::begin(const string_view &key) { return const_iterator { *this, index.begin(key), {} }; } inline ircd::m::dbs::cursor::const_iterator ircd::m::dbs::cursor::end(const string_view &key) { return const_iterator { *this, index.end(key), {} }; } // // const iterator // template ircd::m::dbs::cursor::const_iterator_base::const_iterator_base(const cursor &c, index_iterator idx, const db::gopts &opts) :idx{std::move(idx)} ,cell{} ,row { *dbs::events, bool(this->idx) && this->idx->second? this->idx->second: bool(this->idx)? this->idx->first: string_view{}, event{}, cell, opts } ,stale { true } ,invalid { !this->idx || !row_valid() } {} template ircd::m::dbs::cursor::const_iterator_base & ircd::m::dbs::cursor::const_iterator_base::operator++() { while(!(invalid = !bool(++idx))) if(seek_row()) break; return *this; } template ircd::m::dbs::cursor::const_iterator_base & ircd::m::dbs::cursor::const_iterator_base::operator--() { while(!(invalid = !bool(--idx))) if(seek_row()) break; return *this; } template bool ircd::m::dbs::cursor::const_iterator_base::seek_row() { if(!db::seek(row, row_key())) return false; stale = true; return true; } template typename ircd::m::dbs::cursor::const_iterator_base::value_type * ircd::m::dbs::cursor::const_iterator_base::operator->() const { return &this->operator*(); } template typename ircd::m::dbs::cursor::const_iterator_base::value_type & ircd::m::dbs::cursor::const_iterator_base::operator*() const { if(!stale) return v; assign(v, row, row_key()); stale = false; return v; } template bool ircd::m::dbs::cursor::const_iterator_base::row_valid() const { return row.valid(row_key()); } template ircd::string_view ircd::m::dbs::cursor::const_iterator_base::row_key() const { if(!idx) return {}; if(idx->second) return idx->second; assert(bool(idx->first)); return idx->first; } template bool ircd::m::dbs::cursor::const_iterator_base::operator!() const { return !static_cast(*this); } template ircd::m::dbs::cursor::const_iterator_base::operator bool() const { if(invalid) return false; if(!idx) return false; return row_valid(); } template bool ircd::m::dbs::cursor::const_iterator_base::operator!=(const const_iterator_base &o) const { return !(*this == o); } template bool ircd::m::dbs::cursor::const_iterator_base::operator==(const const_iterator_base &o) const { if(row_key() != o.row_key()) return false; if(!row_valid() && !o.row_valid()) return true; if(!row_valid() || !o.row_valid()) return false; return true; }