/* * Copyright (C) 2016 Charybdis Development Team * Copyright (C) 2016 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #define HAVE_IRCD_DB_OBJECT_H namespace ircd { namespace db { template struct transaction { string_view index; database::snapshot snapshot; //something transaction; transaction(const string_view &index = {}) :index{index} ,snapshot{*d} {} }; template struct value { }; template struct value { mutable column h; transaction *t; value(const string_view &name, transaction &t) :h{!name.empty()? column{*d, name} : column{}} ,t{&t} {} value() :t{nullptr} {} }; template struct object { struct iterator; using key_type = string_view; using mapped_type = value; using value_type = std::pair; using pointer = value_type *; using reference = value_type &; using size_type = size_t; using difference_type = ptrdiff_t; transaction *t; iterator begin(); iterator end(); object(transaction &t) :t{&t} {} object() :t{nullptr} {} }; template struct object::iterator { using key_type = string_view; using mapped_type = value; using value_type = std::pair; using pointer = value_type *; using reference = value_type &; using size_type = size_t; using difference_type = ptrdiff_t; friend class object; protected: transaction *t; decltype(database::columns)::iterator it; value_type last; value_type val; void seek_next(); public: const value_type *operator->() const { return &val; } const value_type &operator*() const { return *operator->(); } bool operator==(const iterator &o) const { return it == o.it; } bool operator!=(const iterator &o) const { return it != o.it; } bool operator<(const iterator &o) const { return it < o.it; } iterator &operator++() { ++it; seek_next(); return *this; } iterator(transaction &t) :t{&t} {} iterator() :t{nullptr} {} }; template typename object::iterator object::end() { iterator ret{}; ret.it = std::end(d->columns); return ret; } template typename object::iterator object::begin() { iterator ret{*t}; ret.it = std::begin(d->columns); ret.seek_next(); return ret; } template void object::iterator::seek_next() { const auto ptc(tokens_count(prefix, ".")); while(it != std::end(d->columns)) { const auto &pair(*it); if(!startswith(pair.first, prefix)) { ++it; continue; } const auto ktc(tokens_count(pair.first, ".")); if(ktc != ptc + 1) { const auto com(std::min(tokens_count(last.first, "."), ptc + 1)); if(!com || token(last.first, ".", com - 1) == token(pair.first, ".", com - 1)) { ++it; continue; } } bool bad(false); const auto com(std::min(ktc, ptc)); if(com) for(size_t i(0); i < com - 1 && !bad; i++) if(token(prefix, ".", i) != token(pair.first, ".", i)) bad = true; if(bad) { ++it; continue; } val.first = pair.first; last.first = pair.first; val.first = lstrip(val.first, prefix); val.first = lstrip(val.first, '.'); val.first = split(val.first, '.').first; val.second = value{pair.first, *t}; break; } } /* template struct value :value { // hold iterator operator string_view() const { std::cout << "read [" << this->name << "] " << std::endl; return {}; } value &operator=(const string_view &val) { std::cout << "write [" << this->name << "] " << val << std::endl; return *this; } value(const string_view &name) :value{name} {} friend std::ostream &operator<<(std::ostream &s, const value &v) { s << string_view{v}; return s; } }; */ template struct value :value { int64_t def; operator int64_t() const try { const auto val(read(this->h, this->t->index)); return lex_cast(val); } catch(const not_found &e) { return def; } value &operator=(const int64_t &val) { write(this->h, this->t->index, lex_cast(val)); return *this; } value(const string_view &name, transaction &t, const int64_t &def = 0) :value{name, t} ,def{def} {} }; } // namespace db } // namespace ircd