/* libobby - Network text editing library
* Copyright (C) 2005 0x539 dev group
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "common.hpp"
#include "serialise/error.hpp"
#include "user_table.hpp"
obby::user_table::user_table()
{
}
obby::user_table::~user_table()
{
clear();
}
void obby::user_table::serialise(serialise::object& obj) const
{
for(base_iterator i = m_user_map.begin(); i != m_user_map.end(); ++ i)
{
serialise::object& user = obj.add_child();
user.set_name("user");
i->second->serialise(user);
}
}
void obby::user_table::deserialise(const serialise::object& obj)
{
for(serialise::object::child_iterator iter = obj.children_begin();
iter != obj.children_end();
++ iter)
{
if(iter->get_name() == "user")
{
// Create new user
user* new_user = new user(*iter);
// Check for conflicts
if(m_user_map.find(new_user->get_id()) !=
m_user_map.end() || new_user->get_id() == 0)
{
format_string str(
_("User ID %0% is already in use")
);
str << new_user->get_id();
delete new_user;
throw serialise::error(
str.str(),
iter->get_line()
);
}
// Insert into user map
m_user_map[new_user->get_id()] = new_user;
}
else
{
// TODO: unexpected_child_error
format_string str(_("Unexpected child node: '%0%'") );
str << iter->get_name();
throw serialise::error(str.str(), iter->get_line() );
}
}
m_signal_deserialised.emit();
}
void obby::user_table::clear()
{
for(base_iterator i = m_user_map.begin(); i != m_user_map.end(); ++ i)
delete i->second;
m_user_map.clear();
}
const obby::user* obby::user_table::add_user(unsigned int id,
const net6::user& user6,
const colour& colour)
{
// Find already exiting user with the given name
user* existing_user = find_int(user6.get_name() );
if(existing_user != NULL)
{
// If this user would be connected, net6 should have denied
// the login process with the "Name is already in use" error
if(existing_user->get_flags() & user::flags::CONNECTED)
throw std::logic_error("obby::user_table::add_user");
// Assign new net6::user to existing obby::user.
existing_user->assign_net6(user6, colour);
return existing_user;
}
else
{
// Make sure the ID is not already in use.
if(id == 0 || m_user_map.find(id) != m_user_map.end() )
throw std::logic_error("obby::user_table::add_user");
// User seems to be here for his first time: Create a new user.
user* new_user = new user(id, user6, colour);
// Insert user into user list
m_user_map[id] = new_user;
return new_user;
}
}
const obby::user* obby::user_table::add_user(unsigned int id,
const std::string& name,
const colour& colour)
{
// Look for an existing user with this name.
user* existing_user = find_int(name);
// We can not assign the new user to this one, because the user
// we are currently adding is not connected to the obby session.
if(existing_user != NULL)
throw std::logic_error("obby::user_table::add_user");
// Make sure the ID is not already in use.
if(id == 0 || m_user_map.find(id) != m_user_map.end() )
throw std::logic_error("obby::user_table::add_user");
user* new_user = new user(id, name, colour);
m_user_map[id] = new_user;
return new_user;
}
void obby::user_table::remove_user(const user& user_to_remove)
{
// Release underlaying net6::user object, this disables the connected
// flag, too. Keep the user in the list to recognize him if he rejoins.
const_cast<user&>(user_to_remove).release_net6();
}
void obby::user_table::set_user_password(const user& user,
const std::string& password)
{
lookup(user.get_id()).set_password(password);
}
void obby::user_table::set_user_colour(const user& user,
const colour& colour)
{
lookup(user.get_id()).set_colour(colour);
}
unsigned int obby::user_table::find_free_id() const
{
unsigned int free_id = 1;
for(base_iterator i = m_user_map.begin(); i != m_user_map.end(); ++ i)
if( i->second->get_id() >= free_id)
free_id = i->second->get_id() + 1;
return free_id;
}
obby::user_table::iterator obby::user_table::begin(user::flags inc_flags,
user::flags exc_flags) const
{
return iterator(m_user_map, m_user_map.begin(), inc_flags, exc_flags);
}
obby::user_table::iterator obby::user_table::end(user::flags inc_flags,
user::flags exc_flags) const
{
return iterator(m_user_map, m_user_map.end(), inc_flags, exc_flags);
}
const obby::user* obby::user_table::find(unsigned int id,
user::flags inc_flags,
user::flags exc_flags) const
{
base_iterator iter = m_user_map.find(id);
if(iter == m_user_map.end() ) return NULL;
user::flags flags = iter->second->get_flags();
if(!iterator::check_flags(flags, inc_flags, exc_flags) ) return NULL;
return iter->second;
}
const obby::user* obby::user_table::find(const net6::user& user,
user::flags inc_flags,
user::flags exc_flags) const
{
for(base_iterator i = m_user_map.begin(); i != m_user_map.end(); ++ i)
{
if(~i->second->get_flags() & user::flags::CONNECTED) continue;
if( &i->second->get_net6() != &user) continue;
user::flags flags = i->second->get_flags();
if(!iterator::check_flags(flags, inc_flags, exc_flags) )
continue;
return i->second;
}
return NULL;
}
const obby::user* obby::user_table::find(const std::string& name,
user::flags inc_flags,
user::flags exc_flags) const
{
for(base_iterator i = m_user_map.begin(); i != m_user_map.end(); ++ i)
{
if(i->second->get_name() != name) continue;
user::flags flags = i->second->get_flags();
if(!iterator::check_flags(flags, inc_flags, exc_flags) )
continue;
return i->second;
}
return NULL;
}
obby::user_table::size_type obby::user_table::count(user::flags inc_flags,
user::flags exc_flags) const
{
// No criteria: Optimize by returning the cached value from the map
if(inc_flags == user::flags::NONE && exc_flags == user::flags::NONE)
return m_user_map.size();
size_type c = 0;
for(iterator iter = begin(inc_flags, exc_flags);
iter != end(inc_flags, exc_flags);
++ iter)
{
++ c;
}
return c;
}
obby::user_table::signal_deserialised_type
obby::user_table::deserialised_event() const
{
return m_signal_deserialised;
}
obby::user& obby::user_table::lookup(unsigned int id)
{
base_iterator iter = m_user_map.find(id);
if(iter == m_user_map.end() )
throw std::logic_error("obby::user_table::lookup");
return *iter->second;
}
obby::user* obby::user_table::find_int(const std::string& name)
{
for(base_iterator iter = m_user_map.begin();
iter != m_user_map.end();
++ iter)
{
if(iter->second->get_name() == name)
return iter->second;
}
return NULL;
}
syntax highlighted by Code2HTML, v. 0.9.1