// 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. bool ircd::m::room::members::empty() const { return empty(string_view{}, string_view{}); } bool ircd::m::room::members::empty(const string_view &membership) const { return empty(membership, string_view{}); } bool ircd::m::room::members::empty(const string_view &membership, const string_view &host) const { return for_each(membership, host, closure{[] (const user::id &user_id) noexcept { return false; }}); } size_t ircd::m::room::members::count() const { return count(string_view{}, string_view{}); } size_t ircd::m::room::members::count(const string_view &membership) const { return count(membership, string_view{}); } size_t ircd::m::room::members::count(const string_view &membership, const string_view &host) const { size_t ret{0}; for_each(membership, host, closure{[&ret] (const user::id &user_id) noexcept { ++ret; return true; }}); return ret; } bool ircd::m::room::members::for_each(const closure &closure) const { return for_each(string_view{}, closure); } bool ircd::m::room::members::for_each(const closure_idx &closure) const { return for_each(string_view{}, closure); } bool ircd::m::room::members::for_each(const string_view &membership, const closure &closure) const { return for_each(membership, string_view{}, closure); } bool ircd::m::room::members::for_each(const string_view &membership, const closure_idx &closure) const { return for_each(membership, string_view{}, closure); } bool ircd::m::room::members::for_each(const string_view &membership, const string_view &host, const closure &closure) const { const m::room::state state { room }; const bool present { state.present() }; const closure_idx _closure { [&closure](const auto &user_id, const auto &event_idx) { return closure(user_id); } }; // joined members optimization. Only possible when seeking // membership="join" on the present state of the room. if(membership == "join" && present) return for_each_join_present(host, _closure); return this->for_each(membership, host, _closure); } bool ircd::m::room::members::for_each(const string_view &membership, const string_view &host, const closure_idx &closure) const { const m::room::state state { room }; const bool present { state.present() }; // joined members optimization. Only possible when seeking // membership="join" on the present state of the room. if(membership == "join" && present) return for_each_join_present(host, [&closure, &state] (const id::user &user_id, event::idx event_idx) { if(!event_idx) event_idx = state.get(std::nothrow, "m.room.member", user_id); if(unlikely(!event_idx)) { log::error { log, "Failed member:%s event_idx:%lu in room_joined of %s", string_view{user_id}, event_idx, string_view{state.room_id}, }; return true; } return closure(user_id, event_idx); }); return state.for_each("m.room.member", [this, &host, &membership, &closure] (const string_view &type, const string_view &state_key, const event::idx &event_idx) { const m::user::id &user_id { state_key }; if(host && user_id.host() != host) return true; return !membership || m::membership(event_idx, membership)? closure(user_id, event_idx): true; }); } bool ircd::m::room::members::for_each_join_present(const string_view &host, const closure_idx &closure) const { db::domain &index { dbs::room_joined }; char keybuf[dbs::ROOM_JOINED_KEY_MAX_SIZE]; const string_view &key { dbs::room_joined_key(keybuf, room.room_id, host) }; auto it { index.begin(key) }; for(; bool(it); ++it) { const auto &[origin, user_id] { dbs::room_joined_key(it->first) }; if(host && origin != host) break; const event::idx event_idx { it->second.size() >= sizeof(event::idx)? event::idx(byte_view(it->second)): 0UL }; if(!closure(user_id, event_idx)) return false; } return true; }