diff --git a/include/ircd/mode_lease.h b/include/ircd/mode_lease.h new file mode 100644 index 000000000..98599213b --- /dev/null +++ b/include/ircd/mode_lease.h @@ -0,0 +1,82 @@ +/* + * 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_MODE_LEASE_H + +#ifdef __cplusplus +namespace ircd { + +template &table> +class mode_lease +{ + using mask_t = typename mode_table::mask_t; + + char c = '\0'; + + virtual void release() { table[c] = { 0 }; } + + public: + explicit operator const char &() const { return c; } + operator const mask_t &() const { return static_cast(table[c]); } + bool operator!() const { return !c; } + + template mode_lease(const char &c, args&&...); + mode_lease() = default; + mode_lease(mode_lease &&) noexcept; + mode_lease(const mode_lease &) = delete; + ~mode_lease() noexcept; +}; + +template &table> +template +mode_lease::mode_lease(const char &c, + args&&... a) +:c(c) +{ + if(!!table[c]) + throw mode_filled("Character [%c] is already leased", c); + + table[c] = { find_slot(table), std::forward(a)... }; +} + +template &table> +mode_lease::mode_lease(mode_lease &&other) +noexcept +:c(other.c) +{ + other.c = '\0'; +} + +template &table> +mode_lease::~mode_lease() +noexcept +{ + if(c) + release(); +} + +} // namespace ircd +#endif // __cplusplus diff --git a/include/ircd/mode_table.h b/include/ircd/mode_table.h index c5336a97d..e78384ee3 100644 --- a/include/ircd/mode_table.h +++ b/include/ircd/mode_table.h @@ -25,6 +25,8 @@ #ifdef __cplusplus namespace ircd { +IRCD_EXCEPTION(error, mode_filled) + /* The mode_table is a generic template to replace the arrays mapping characters to mode flags * (or other structures) like `extern uint umode_table[256]` or `struct chm chmode_table[256]`. * Instead an `mode_table` or `mode_table` etc can be used. diff --git a/include/ircd/stdinc.h b/include/ircd/stdinc.h index aed08649c..bb428fbd3 100644 --- a/include/ircd/stdinc.h +++ b/include/ircd/stdinc.h @@ -75,6 +75,7 @@ namespace ircd #include "s_assert.h" #include "match.h" #include "mode_table.h" +#include "mode_lease.h" #include "cache.h" #include "whowas.h"