0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-20 08:51:18 +01:00
construct/include/ircd/m/id.h

191 lines
4.5 KiB
C
Raw Normal View History

/*
* charybdis: 21st Century IRC++d
*
* Copyright (C) 2016 Charybdis Development Team
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
*
* 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_M_ID_H
2017-09-07 13:07:58 +02:00
namespace ircd::m
{
IRCD_M_EXCEPTION(error, INVALID_MXID, http::BAD_REQUEST)
IRCD_M_EXCEPTION(INVALID_MXID, BAD_SIGIL, http::BAD_REQUEST)
2017-09-07 13:07:58 +02:00
IRCD_OVERLOAD(generate)
2017-09-07 13:07:58 +02:00
struct id;
}
2017-09-07 13:07:58 +02:00
//
// Interface to a string representing an mxid. The m::id itself is just a
// string_view over some existing data. m::id::buf is an m::id with an
// internal array providing the buffer.
//
struct ircd::m::id
:string_view
{
2017-09-07 13:07:58 +02:00
struct event;
struct user;
struct room;
struct alias;
2017-10-16 06:48:53 +02:00
2017-09-07 13:07:58 +02:00
template<class T, size_t SIZE = 256> struct buf;
2017-09-07 13:07:58 +02:00
enum sigil
{
EVENT = '$',
USER = '@',
ROOM = '!',
ALIAS = '#',
}
sigil;
2017-09-07 13:07:58 +02:00
// Checks
bool valid() const; // Fully qualified mxid
bool valid_local() const; // Local part is valid (may or may not have host)
void validate() const; // valid() | throws
2017-09-07 13:07:58 +02:00
// Extract elements
string_view local() const { return split(*this, ':').first; }
string_view host() const { return split(*this, ':').second; }
2017-10-16 06:48:53 +02:00
string_view name() const { return lstrip(local(), sigil); }
string_view hostname() const;
uint16_t hostport() const;
2017-10-16 06:48:53 +02:00
protected:
struct generator;
2017-09-07 13:07:58 +02:00
public:
IRCD_USING_OVERLOAD(generate, m::generate);
2017-10-16 06:48:53 +02:00
id(const enum sigil &, const mutable_buffer &, const generate_t &, const string_view &host);
id(const enum sigil &, const mutable_buffer &, const string_view &name, const string_view &host);
id(const enum sigil &, const mutable_buffer &, const string_view &id);
id(const enum sigil &, const string_view &id);
id(const enum sigil &);
id(const string_view &id);
id() = default;
2017-09-07 13:07:58 +02:00
};
namespace ircd::m
{
2017-09-07 13:07:58 +02:00
bool valid_sigil(const char &c);
bool valid_sigil(const string_view &id);
enum id::sigil sigil(const char &c);
enum id::sigil sigil(const string_view &id);
const char *reflect(const enum id::sigil &);
}
2017-10-25 18:47:03 +02:00
/// ID object backed by an internal buffer of wost-case size.
///
2017-09-07 13:07:58 +02:00
template<class T,
size_t MAX = 256>
struct ircd::m::id::buf
:T
{
2017-09-25 03:05:42 +02:00
static constexpr const size_t SIZE
{
MAX
};
2017-09-07 13:07:58 +02:00
private:
2017-10-16 06:48:53 +02:00
fixed_buffer<mutable_buffer, SIZE> b;
2017-09-07 13:07:58 +02:00
public:
2017-10-16 06:48:53 +02:00
operator const fixed_buffer<mutable_buffer, SIZE> &() const
{
return b;
}
operator mutable_buffer()
{
return b;
}
2017-09-07 13:07:58 +02:00
template<class... args>
buf(args&&... a)
2017-10-16 06:48:53 +02:00
:T{b, std::forward<args>(a)...}
{}
2017-09-07 13:07:58 +02:00
buf() = default;
buf &operator=(const string_view &s)
{
2017-10-16 06:48:53 +02:00
static_cast<T &>(*this) = T{b, s};
return *this;
}
2017-09-07 13:07:58 +02:00
};
2017-09-07 13:07:58 +02:00
//
// convenience typedefs
//
struct ircd::m::id::event
:ircd::m::id
{
using buf = m::id::buf<event>;
template<class... args> event(args&&... a) :m::id{EVENT, std::forward<args>(a)...} {}
};
2017-09-07 13:07:58 +02:00
struct ircd::m::id::user
:ircd::m::id
{
using buf = m::id::buf<user>;
template<class... args> user(args&&... a) :m::id{USER, std::forward<args>(a)...} {}
};
struct ircd::m::id::room
:ircd::m::id
{
using buf = m::id::buf<room>;
template<class... args> room(args&&... a) :m::id{ROOM, std::forward<args>(a)...} {}
};
struct ircd::m::id::alias
:ircd::m::id
{
using buf = m::id::buf<alias>;
template<class... args> alias(args&&... a) :m::id{ALIAS, std::forward<args>(a)...} {}
};
2017-10-16 06:48:53 +02:00
inline uint16_t
ircd::m::id::hostport()
const try
{
const auto port
{
split(host(), ':').second
};
return port? lex_cast<uint16_t>(port) : 8448;
}
catch(const std::exception &e)
{
return 8448;
}
inline ircd::string_view
ircd::m::id::hostname()
const
{
return split(host(), ':').first;
}