<commit_before>/*
   Copyright (c) 2010, The Mineserver Project
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
 * Neither the name of the The Mineserver Project nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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.
 */

#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <deque>
#include <fstream>
#include <vector>
#include <ctime>
#include <math.h>
#ifdef WIN32
  #include <winsock2.h>
#else
  #include <netinet/in.h>
  #include <string.h>
#endif

#include "logger.h"
#include "constants.h"

#include "tools.h"
#include "map.h"
#include "user.h"
#include "chat.h"
#include "config.h"
#include "tools.h"
#include "physics.h"

namespace
{

  void reportError(User *user, std::string message)
  {
    Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + "Error! " + COLOR_RED + message, Chat::USER);
  }

  void playerList(User *user, std::string command, std::deque<std::string> args)
  {
    Chat::get().sendUserlist(user);
  }

  void about(User *user, std::string command, std::deque<std::string> args)
  {
    Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + Conf::get().sValue("servername")+
                        "Running Mineserver v." + VERSION, Chat::USER);
  }

  void rules(User *user, std::string command, std::deque<std::string> args)
  {
    User *tUser = user;
    if(!args.empty() && user->admin)
      tUser = getUserByNick(args[0]);
    if(tUser != NULL)
    {
      // Send rules
      std::ifstream ifs( RULESFILE.c_str());
      std::string temp;

      if(ifs.fail())
      {
        std::cout << "> Warning: " << RULESFILE << " not found." << std::endl;
        return;
      }
      else
      {
        while(getline(ifs, temp))
        {
          // If not a comment
          if(!temp.empty() && temp[0] != COMMENTPREFIX)
            Chat::get().sendMsg(tUser, temp, Chat::USER);
        }
        ifs.close();
      }
    }
    else
      reportError(user, "User " + args[0] + " not found (see /players)");
  }
}

void home(User *user, std::string command, std::deque<std::string> args)
{
  Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + "Teleported you home!", Chat::USER);
  user->teleport(Map::get().spawnPos.x(), Map::get().spawnPos.y() + 2, Map::get().spawnPos.z());
}

void kit(User *user, std::string command, std::deque<std::string> args)
{
  if(args.size() == 1)
  {
    std::vector<int> kitItems = Conf::get().vValue("kit_" + args[0]);
    // If kit is found
    if(!kitItems.empty())
    {
      for(uint32 i=0;i<kitItems.size();i++)
      {
        spawnedItem item;
        item.EID     = generateEID();
        item.item    = kitItems[i];
        item.count   = 1;
        item.health=0;
        item.pos.x() = static_cast<int>(user->pos.x*32 + (rand() % 30));
        item.pos.y() = static_cast<int>(user->pos.y*32);
        item.pos.z() = static_cast<int>(user->pos.z*32 + (rand() % 30));
        Map::get().sendPickupSpawn(item);
      }
    }
    else
      reportError(user, "Kit " + args[0] + " not found");
  }
  else
    reportError(user, "Usage: /kit name");
}

void saveMap(User *user, std::string command, std::deque<std::string> args)
{
  Map::get().saveWholeMap();
  Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + "SERVER:" + COLOR_RED + " Saved map to disc",
                      Chat::USER);
}

void kick(User *user, std::string command, std::deque<std::string> args)
{
  if(!args.empty())
  {
    std::string victim = args[0];

    User *tUser        = getUserByNick(victim);

    if(tUser != NULL)
    {
      args.pop_front();
      std::string kickMsg;
      if(args.empty())
        kickMsg = Conf::get().sValue("default_kick_message");
      else
      {
        while(!args.empty())
        {
          kickMsg += args[0] + " ";
          args.pop_front();
        }
      }

      tUser->kick(kickMsg);
    }
    else
      reportError(user, "User " + victim + " not found (see /players)");
  }
  else
    reportError(user, "Usage: /kick user [reason]");
}

void setTime(User *user, std::string command, std::deque<std::string> args)
{
  if(args.size() == 1)
  {
    Map::get().mapTime = (sint64)atoi(args[0].c_str());
    Packet pkt;
    pkt << (sint8)PACKET_TIME_UPDATE << (sint64)Map::get().mapTime;
    if(Users.size())
      Users[0]->sendAll((uint8*)pkt.getWrite(), pkt.getWriteLen());
    Chat::get().sendMsg(user, COLOR_MAGENTA + "Time set to " + args[0], Chat::USER);
  }
  else
    reportError(user, "Usage: /settime time (time = 0-24000)");
}

void setHealth(User *user, std::string command, std::deque<std::string> args)
{
  if(args.size() == 2)
  {
    user->sethealth(atoi(args[1].c_str()));
  }
  else
    reportError(user, "Usage: /sethealth [player] health (health = 0-20)");
}

void coordinateTeleport(User *user, std::string command, std::deque<std::string> args)
{
  if(args.size() == 3)
  {
    LOG(user->nick + " teleport to: " + args[0] + " " + args[1] + " " + args[2]);
    double x = atof(args[0].c_str());
    double y = atof(args[1].c_str());
    double z = atof(args[2].c_str());
    user->teleport(x, y, z);
  }
  else
    reportError(user, "Usage: /ctp x y z");
}

void userTeleport(User *user, std::string command, std::deque<std::string> args)
{
  if(args.size() == 1)
  {
    LOG(user->nick + " teleport to: " + args[0]);
    User *tUser = getUserByNick(args[0]);
    if(tUser != NULL)
      user->teleport(tUser->pos.x, tUser->pos.y + 2, tUser->pos.z);
    else
      reportError(user, "User " + args[0] + " not found (see /players)");
  }
  else if(args.size() == 2)
  {
    LOG(user->nick + ": teleport " + args[0] + " to " + args[1]);

    User *whoUser = getUserByNick(args[0]);
    User *toUser   = getUserByNick(args[1]);

    if(whoUser != NULL && toUser != NULL)
    {
      whoUser->teleport(toUser->pos.x, toUser->pos.y + 2, toUser->pos.z);
      Chat::get().sendMsg(user, COLOR_MAGENTA + "Teleported!", Chat::USER);
    }
    else
    {
      reportError(user, "User " + (whoUser == NULL ? args[0] : args[1])+
                  " not found (see /players");
    }
  }
  else
    reportError(user, "Usage: /tp [player] targetplayer");
}

void showPosition(User *user, std::string command, std::deque<std::string> args)
{
  if(args.size() == 1)
  {
    User *tUser = getUserByNick(args[0]);
    if(tUser != NULL)
      Chat::get().sendMsg(user, COLOR_MAGENTA + args[0] + " is at: " + dtos(tUser->pos.x)
                                                                     + " "
                                                                     + dtos(tUser->pos.y)
                                                                     + " "
                                                                     + dtos(tUser->pos.z), Chat::USER);
    else
      reportError(user, "User " + args[0] + " not found (see /players)");
  }
  else if(args.size() == 0)
  {
    Chat::get().sendMsg(user, COLOR_MAGENTA + "You are at: " + dtos(user->pos.x)
                                                             + " "
                                                             + dtos(user->pos.y)
                                                             + " "
                                                             + dtos(user->pos.z), Chat::USER);
  }
  else
    reportError(user, "Usage: /gps [player]");
}

void regenerateLighting(User *user, std::string command, std::deque<std::string> args)
{
  printf("Regenerating lighting for chunk %d,%d\n", blockToChunk((sint32)user->pos.x), blockToChunk((sint32)user->pos.z));
  //First load the map
  if(Map::get().loadMap(blockToChunk((sint32)user->pos.x), blockToChunk((sint32)user->pos.z)))
  {
    //Then regenerate lighting
    Map::get().generateLight(blockToChunk((sint32)user->pos.x), blockToChunk((sint32)user->pos.z));
  }
}

void reloadConfiguration(User *user, std::string command, std::deque<std::string> args)
{
  Chat::get().loadAdmins(ADMINFILE);
  Conf::get().load(CONFIGFILE);

  // Set physics enable state based on config
  Physics::get().enabled = ((Conf::get().iValue("liquid_physics") == 0) ? false : true);

  Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + "SERVER:" + COLOR_RED+
                      " Reloaded admins and config", Chat::USER);

  // Note that the MOTD is loaded on-demand each time it is requested
}

bool isValidItem(int id)
{
  if(id < 1)  // zero or negative items are all invalid
    return false;

  if(id > 91 && id < 256)  // these are undefined blocks and items
    return false;

  if(id == 2256 || id == 2257)  // records are special cased
    return true;

  if(id > 350)  // high items are invalid
    return false;

  if(id >= BLOCK_RED_CLOTH && id <= BLOCK_GRAY_CLOTH)  // coloured cloth causes client crashes
    return false;

  return true;
}

int roundUpTo(int x, int nearest)
{
  x += (nearest - 1);
  x /= nearest;
  x *= nearest;
  return x;
}

void giveItems(User *user, std::string command, std::deque<std::string> args)
{
  User *tUser = NULL;
  int itemId = 0, itemCount = 1, itemStacks = 1;

  if(args.size() == 2 || args.size() == 3)
  {
    tUser = getUserByNick(args[0]);

    //First check if item is a number
    itemId = atoi(args[1].c_str());

    //If item was not a number, search the name from config
    if(itemId == 0)
      itemId = Conf::get().iValue(args[1]);

    // Check item validity
    if(!isValidItem(itemId))
    {
      reportError(user, "Item " + args[1] + " not found.");
      return;
    }

    if(args.size() == 3)
    {
      itemCount = atoi(args[2].c_str());
      // If multiple stacks
      itemStacks = roundUpTo(itemCount, 64) / 64;
      itemCount  -= (itemStacks-1) * 64;
    }
  }
  else
  {
    reportError(user, "Usage: /give player item [count]");
	  return;
  }

  if(tUser)
  {
    int amount = 64;
    for(int i = 0; i < itemStacks; i++)
    {
      // if last stack
      if(i == itemStacks - 1)
        amount = itemCount;

      spawnedItem item;
      item.EID     = generateEID();
      item.item    = itemId;
      item.health  = 0;
      item.count   = amount;
      item.pos.x() = static_cast<int>(tUser->pos.x * 32);
      item.pos.y() = static_cast<int>(tUser->pos.y * 32);
      item.pos.z() = static_cast<int>(tUser->pos.z * 32);

      Map::get().sendPickupSpawn(item);
    }

    Chat::get().sendMsg(user, COLOR_RED + user->nick + " spawned " + args[1], Chat::ADMINS);
  }
  else
    reportError(user, "User " + args[0] + " not found (see /players)");
}

void Chat::registerStandardCommands()
{
  registerCommand("players", playerList, false);
  registerCommand("about", about, false);
  registerCommand("rules", rules, false);
  registerCommand("home", home, false);
  registerCommand("kit", kit, false);
  registerCommand("save", saveMap, true);
  registerCommand("kick", kick, true);
  registerCommand("ctp", coordinateTeleport, true);
  registerCommand("tp", userTeleport, true);
  registerCommand("reload", reloadConfiguration, true);
  registerCommand("give", giveItems, true);
  registerCommand("gps", showPosition, true);
  registerCommand("settime", setTime, true);
  registerCommand("regen", regenerateLighting, true);
  registerCommand("sethealth", setHealth, true);
}
<commit_msg>ban + unban + whitelist<commit_after>/*
   Copyright (c) 2010, The Mineserver Project
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
 * Neither the name of the The Mineserver Project nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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.
 */

#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <deque>
#include <fstream>
#include <vector>
#include <ctime>
#include <math.h>
#ifdef WIN32
  #include <winsock2.h>
#else
  #include <netinet/in.h>
  #include <string.h>
#endif

#include "logger.h"
#include "constants.h"

#include "tools.h"
#include "map.h"
#include "user.h"
#include "chat.h"
#include "config.h"
#include "tools.h"
#include "physics.h"

namespace
{

  void reportError(User *user, std::string message)
  {
    Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + "Error! " + COLOR_RED + message, Chat::USER);
  }

  void playerList(User *user, std::string command, std::deque<std::string> args)
  {
    Chat::get().sendUserlist(user);
  }

  void about(User *user, std::string command, std::deque<std::string> args)
  {
    Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + Conf::get().sValue("servername")+
                        "Running Mineserver v." + VERSION, Chat::USER);
  }

  void rules(User *user, std::string command, std::deque<std::string> args)
  {
    User *tUser = user;
    if(!args.empty() && user->admin)
      tUser = getUserByNick(args[0]);
    if(tUser != NULL)
    {
      // Send rules
      std::ifstream ifs( RULESFILE.c_str());
      std::string temp;

      if(ifs.fail())
      {
        std::cout << "> Warning: " << RULESFILE << " not found." << std::endl;
        return;
      }
      else
      {
        while(getline(ifs, temp))
        {
          // If not a comment
          if(!temp.empty() && temp[0] != COMMENTPREFIX)
            Chat::get().sendMsg(tUser, temp, Chat::USER);
        }
        ifs.close();
      }
    }
    else
      reportError(user, "User " + args[0] + " not found (see /players)");
  }
}

void home(User *user, std::string command, std::deque<std::string> args)
{
  Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + "Teleported you home!", Chat::USER);
  user->teleport(Map::get().spawnPos.x(), Map::get().spawnPos.y() + 2, Map::get().spawnPos.z());
}

void kit(User *user, std::string command, std::deque<std::string> args)
{
  if(!args.empty())
  {
    std::vector<int> kitItems = Conf::get().vValue("kit_" + args[0]);
    // If kit is found
    if(!kitItems.empty())
    {
      for(uint32 i=0;i<kitItems.size();i++)
      {
        spawnedItem item;
        item.EID     = generateEID();
        item.item    = kitItems[i];
        item.count   = 1;
        item.health=0;
        item.pos.x() = static_cast<int>(user->pos.x*32 + (rand() % 30));
        item.pos.y() = static_cast<int>(user->pos.y*32);
        item.pos.z() = static_cast<int>(user->pos.z*32 + (rand() % 30));
        Map::get().sendPickupSpawn(item);
      }
    }
    else
      reportError(user, "Kit " + args[0] + " not found");
  }
}

void saveMap(User *user, std::string command, std::deque<std::string> args)
{
  Map::get().saveWholeMap();
  Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + "SERVER:" + COLOR_RED + " Saved map to disc",
                      Chat::USER);
}

void ban(User *user, std::string command, std::deque<std::string> args)
{
	std::string victim = args[0];
    User *tUser        = getUserByNick(victim);

	std::fstream bannedf;
	bannedf.open("banned.txt",std::fstream::app);
	bannedf << victim << std::endl;
	bannedf.close();

	if(tUser != NULL)
    {
      args.pop_front();
      std::string kickMsg;
      if(args.empty())
        kickMsg = Conf::get().sValue("default_banned_message");
      else
      {
        while(!args.empty())
        {
          kickMsg += args[0] + " ";
          args.pop_front();
        }
      }

      tUser->kick(kickMsg);
    }
    else
		Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + victim +" was banned in his absence!", Chat::USER);

	// Reload list with banned users
	Chat::get().loadBanned(BANNEDFILE);
}

void unban(User *user, std::string command, std::deque<std::string> args)
{
	std::string victim = args[0];
    User *tUser        = getUserByNick(victim);

	std::string line;
    std::ifstream in("banned.txt");

    std::ofstream out("banned.tmp");

    while( getline(in,line) )
    {
        if(line != victim)
            out << line << "\n";
    }
    in.close();
    out.close();

    remove("banned.txt");
    rename("banned.tmp","banned.txt");

	// Reload list with banned users
	Chat::get().loadBanned(BANNEDFILE);
}

void kick(User *user, std::string command, std::deque<std::string> args)
{
  if(!args.empty())
  {
    std::string victim = args[0];

    User *tUser        = getUserByNick(victim);

    if(tUser != NULL)
    {
      args.pop_front();
      std::string kickMsg;
      if(args.empty())
        kickMsg = Conf::get().sValue("default_kick_message");
      else
      {
        while(!args.empty())
        {
          kickMsg += args[0] + " ";
          args.pop_front();
        }
      }

      tUser->kick(kickMsg);
    }
    else
      reportError(user, "User " + victim + " not found (see /players)");
  }
  else
    reportError(user, "Usage: /kick user [reason]");
}

void setTime(User *user, std::string command, std::deque<std::string> args)
{
  if(args.size() == 1)
  {
    Map::get().mapTime = (sint64)atoi(args[0].c_str());
    Packet pkt;
    pkt << (sint8)PACKET_TIME_UPDATE << (sint64)Map::get().mapTime;
    if(Users.size())
      Users[0]->sendAll((uint8*)pkt.getWrite(), pkt.getWriteLen());
    Chat::get().sendMsg(user, COLOR_MAGENTA + "Time set to " + args[0], Chat::USER);
  }
  else
    reportError(user, "Usage: /settime time (time = 0-24000)");
}

void coordinateTeleport(User *user, std::string command, std::deque<std::string> args)
{
  if(args.size() > 2)
  {
    LOG(user->nick + " teleport to: " + args[0] + " " + args[1] + " " + args[2]);
    double x = atof(args[0].c_str());
    double y = atof(args[1].c_str());
    double z = atof(args[2].c_str());
    user->teleport(x, y, z);
  }
}

void userTeleport(User *user, std::string command, std::deque<std::string> args)
{
  if(args.size() == 1)
  {
    LOG(user->nick + " teleport to: " + args[0]);
    User *tUser = getUserByNick(args[0]);
    if(tUser != NULL)
      user->teleport(tUser->pos.x, tUser->pos.y + 2, tUser->pos.z);
    else
      reportError(user, "User " + args[0] + " not found (see /players)");
  }
  else if(args.size() == 2)
  {
    LOG(user->nick + ": teleport " + args[0] + " to " + args[1]);

    User *whoUser = getUserByNick(args[0]);
    User *toUser   = getUserByNick(args[1]);

    if(whoUser != NULL && toUser != NULL)
    {
      whoUser->teleport(toUser->pos.x, toUser->pos.y + 2, toUser->pos.z);
      Chat::get().sendMsg(user, COLOR_MAGENTA + "Teleported!", Chat::USER);
    }
    else
    {
      reportError(user, "User " + (whoUser == NULL ? args[0] : args[1])+
                  " not found (see /players");
    }
  }
}

void showPosition(User *user, std::string command, std::deque<std::string> args)
{
  if(args.size() == 1)
  {
    User *tUser = getUserByNick(args[0]);
    if(tUser != NULL)
      Chat::get().sendMsg(user, COLOR_MAGENTA + args[0] + " is at: " + dtos(tUser->pos.x)
                                                                     + " "
                                                                     + dtos(tUser->pos.y)
                                                                     + " "
                                                                     + dtos(tUser->pos.z), Chat::USER);
    else
      reportError(user, "User " + args[0] + " not found (see /players)");
  }
  else
  {
    Chat::get().sendMsg(user, COLOR_MAGENTA + "You are at: " + dtos(user->pos.x)
                                                             + " "
                                                             + dtos(user->pos.y)
                                                             + " "
                                                             + dtos(user->pos.z), Chat::USER);
  }
}

void regenerateLighting(User *user, std::string command, std::deque<std::string> args)
{
  printf("Regenerating lighting for chunk %d,%d\n", blockToChunk((sint32)user->pos.x), blockToChunk((sint32)user->pos.z));
  //First load the map
  if(Map::get().loadMap(blockToChunk((sint32)user->pos.x), blockToChunk((sint32)user->pos.z)))
  {
    //Then regenerate lighting
    Map::get().generateLight(blockToChunk((sint32)user->pos.x), blockToChunk((sint32)user->pos.z));
  }
}

void reloadConfiguration(User *user, std::string command, std::deque<std::string> args)
{
  Chat::get().loadAdmins(ADMINFILE);
  Chat::get().loadBanned(BANNEDFILE);
  Chat::get().loadWhitelist(WHITELISTFILE);
  Conf::get().load(CONFIGFILE);

  // Set physics enable state based on config
  Physics::get().enabled = ((Conf::get().iValue("liquid_physics") == 0) ? false : true);

  Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + "SERVER:" + COLOR_RED+
                      " Reloaded admins and config", Chat::USER);

  // Note that the MOTD is loaded on-demand each time it is requested
}

bool isValidItem(int id)
{
  if(id < 1)  // zero or negative items are all invalid
    return false;

  if(id > 91 && id < 256)  // these are undefined blocks and items
    return false;

  if(id == 2256 || id == 2257)  // records are special cased
    return true;

  if(id > 350)  // high items are invalid
    return false;

  if(id >= BLOCK_RED_CLOTH && id <= BLOCK_GRAY_CLOTH)  // coloured cloth causes client crashes
    return false;

  return true;
}

int roundUpTo(int x, int nearest)
{
  x += (nearest - 1);
  x /= nearest;
  x *= nearest;
  return x;
}

void giveItems(User *user, std::string command, std::deque<std::string> args)
{
  User *tUser = NULL;
  int itemId = 0, itemCount = 1, itemStacks = 1;

  if(args.size() > 1)
  {
    tUser = getUserByNick(args[0]);

    //First check if item is a number
    itemId = atoi(args[1].c_str());

    //If item was not a number, search the name from config
    if(itemId == 0)
      itemId = Conf::get().iValue(args[1]);

    // Check item validity
    if(!isValidItem(itemId))
    {
      reportError(user, "Item " + args[1] + " not found.");
      return;
    }

    if(args.size() > 2)
    {
      itemCount = atoi(args[2].c_str());
      // If multiple stacks
      itemStacks = roundUpTo(itemCount, 64) / 64;
      itemCount  -= (itemStacks-1) * 64;
    }
  }
  else
  {
    reportError(user, "Too few parameters.");
	  return;
  }

  if(tUser)
  {
    int amount = 64;
    for(int i = 0; i < itemStacks; i++)
    {
      // if last stack
      if(i == itemStacks - 1)
        amount = itemCount;

      spawnedItem item;
      item.EID     = generateEID();
      item.item    = itemId;
      item.health  = 0;
      item.count   = amount;
      item.pos.x() = static_cast<int>(tUser->pos.x * 32);
      item.pos.y() = static_cast<int>(tUser->pos.y * 32);
      item.pos.z() = static_cast<int>(tUser->pos.z * 32);

      Map::get().sendPickupSpawn(item);
    }

    Chat::get().sendMsg(user, COLOR_RED + user->nick + " spawned " + args[1], Chat::ADMINS);
  }
  else
    reportError(user, "User " + args[0] + " not found (see /players)");
}

void Chat::registerStandardCommands()
{
  registerCommand("players", playerList, false);
  registerCommand("about", about, false);
  registerCommand("rules", rules, false);
  registerCommand("home", home, false);
  registerCommand("ban", ban, true);
  registerCommand("unban", unban, true);
  registerCommand("kit", kit, false);
  registerCommand("save", saveMap, true);
  registerCommand("kick", kick, true);
  registerCommand("ctp", coordinateTeleport, true);
  registerCommand("tp", userTeleport, true);
  registerCommand("reload", reloadConfiguration, true);
  registerCommand("give", giveItems, true);
  registerCommand("gps", showPosition, true);
  registerCommand("settime", setTime, true);  registerCommand("regen", regenerateLighting, true);
}
<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include "Models/StateSpace/Filters/SparseMatrix.hpp"

#include "test_utils/test_utils.hpp"

namespace {

  using namespace BOOM;
  using std::endl;

  class SparseMatrixTest : public ::testing::Test {
   protected:
    SparseMatrixTest() {
      GlobalRng::rng.seed(8675309);
    }
  };

  void CheckLeftInverse(const Ptr<SparseMatrixBlock> &block,
                        const Vector &rhs) {
    BlockDiagonalMatrix mat;
    mat.add_block(block);

    Vector lhs = mat.left_inverse(rhs);
    Vector rhs_new = mat * lhs;

    EXPECT_TRUE(VectorEquals(rhs, rhs_new))
        << "Vectors were not equal." << endl
        << rhs << endl
        << rhs_new;
  }

  TEST_F(SparseMatrixTest, LeftInverseIdentity) {
    NEW(IdentityMatrix, mat)(3);
    Vector x(3);
    x.randomize();
    CheckLeftInverse(mat, x);
  }

  TEST_F(SparseMatrixTest, LeftInverseSkinnyColumn) {
    NEW(FirstElementSingleColumnMatrix, column)(12);
    Vector errors(1);
    errors.randomize();
    Vector x(12);
    x[0] = errors[0];
    CheckLeftInverse(column, x);
  }
}  // namespace
<commit_msg>Add testing for concrete sparse matrix classes.<commit_after>#include "gtest/gtest.h"

#include "Models/StateSpace/Filters/SparseMatrix.hpp"

#include "test_utils/test_utils.hpp"

namespace {

  using namespace BOOM;
  using std::endl;

  class SparseMatrixTest : public ::testing::Test {
   protected:
    SparseMatrixTest() {
      GlobalRng::rng.seed(8675309);
    }
  };

  void CheckSparseMatrixBlock(
      const Ptr<SparseMatrixBlock> &sparse,
      const Matrix &dense) {
    EXPECT_TRUE(MatrixEquals(sparse->dense(), dense));

    EXPECT_EQ(sparse->nrow(), dense.nrow())
        << endl << sparse->dense() << endl << dense;
    EXPECT_EQ(sparse->ncol(), dense.ncol())
        << endl << sparse->dense() << endl << dense;

    Vector rhs_vector(dense.ncol());
    rhs_vector.randomize();
    Vector lhs_vector(dense.nrow());
    sparse->multiply(VectorView(lhs_vector), rhs_vector);
    EXPECT_TRUE(VectorEquals(lhs_vector, dense * rhs_vector))
        << endl << sparse->dense() << endl << dense << endl
        << "rhs = " << rhs_vector << endl
        << "sparse * rhs = " << lhs_vector << endl
        << "dense * rhs = " << dense * rhs_vector << endl;

    Vector original_lhs = lhs_vector;
    lhs_vector.randomize();
    rhs_vector.randomize();
    sparse->multiply_and_add(VectorView(lhs_vector), rhs_vector);
    EXPECT_TRUE(VectorEquals(lhs_vector, original_lhs + dense * rhs_vector))
        << endl << sparse->dense() << endl << dense << endl
        << "rhs = " << rhs_vector << endl
        << "lhs = " << original_lhs << endl
        << "lhs + sparse * rhs = " << lhs_vector << endl
        << "lhs + dense * rhs = " << lhs_vector + dense * rhs_vector << endl;

    Vector rhs_tmult_vector(dense.nrow());
    Vector lhs_tmult_vector(dense.ncol());
    sparse->Tmult(VectorView(lhs_tmult_vector), rhs_tmult_vector);
    EXPECT_TRUE(VectorEquals(lhs_tmult_vector,
                             rhs_tmult_vector * dense));

    // Only check multiply_inplace and friends if the matrix is square.
    if (dense.nrow() == dense.ncol()) {
      Vector original_rhs = rhs_vector;
      sparse->multiply_inplace(VectorView(rhs_vector));
      EXPECT_TRUE(VectorEquals(rhs_vector, dense * original_rhs))
        << endl << sparse->dense() << endl << dense << endl
        << "rhs = " << original_rhs << endl
        << "sparse->multiply_inplace(rhs) = " << rhs_vector << endl
        << "dense * rhs = " << dense * original_rhs << endl;

      Matrix rhs_matrix(dense.ncol(), dense.ncol());
      rhs_matrix.randomize();
      Matrix original_rhs_matrix = rhs_matrix;
      sparse->matrix_multiply_inplace(SubMatrix(rhs_matrix));
      EXPECT_TRUE(MatrixEquals(rhs_matrix, dense * original_rhs_matrix))
        << endl << sparse->dense() << endl << dense << endl
        << "rhs = " << original_rhs_matrix << endl
        << "sparse->matrix_multiply_inplace(rhs) = " << rhs_matrix << endl
        << "dense * rhs = " << dense * original_rhs_matrix << endl;

      original_rhs_matrix = rhs_matrix;
      sparse->matrix_transpose_premultiply_inplace(SubMatrix(rhs_matrix));
      EXPECT_TRUE(MatrixEquals(rhs_matrix,
                               dense.transpose() * original_rhs_matrix))
        << endl << sparse->dense() << endl << dense << endl
        << "rhs = " << original_rhs_matrix << endl
        << "sparse->matrix_transpose_multiply_inplace(rhs) = " << rhs_matrix << endl
        << "dense * rhs = " << dense.transpose() * original_rhs_matrix << endl;
    }

    Matrix summand(dense.nrow(), dense.ncol());
    summand.randomize();
    Matrix original_summand(summand);
    sparse->add_to(SubMatrix(summand));
    EXPECT_TRUE(MatrixEquals(summand, dense + original_summand))
        << endl << sparse->dense() << endl << dense << endl
        << "B = " << original_summand << endl
        << "sparse->add_to(B) = " << summand << endl
        << "dense + B = " << dense + original_summand << endl;
  }

  void CheckLeftInverse(const Ptr<SparseMatrixBlock> &block,
                        const Vector &rhs) {
    BlockDiagonalMatrix mat;
    mat.add_block(block);

    Vector lhs = mat.left_inverse(rhs);
    Vector rhs_new = mat * lhs;

    EXPECT_TRUE(VectorEquals(rhs, rhs_new))
        << "Vectors were not equal." << endl
        << rhs << endl
        << rhs_new;
  }

  TEST_F(SparseMatrixTest, LeftInverseIdentity) {
    NEW(IdentityMatrix, mat)(3);
    Vector x(3);
    x.randomize();
    CheckLeftInverse(mat, x);
  }

  TEST_F(SparseMatrixTest, LeftInverseSkinnyColumn) {
    NEW(FirstElementSingleColumnMatrix, column)(12);
    Vector errors(1);
    errors.randomize();
    Vector x(12);
    x[0] = errors[0];
    CheckLeftInverse(column, x);
  }

  TEST_F(SparseMatrixTest, IdentityMatrix) {
    NEW(IdentityMatrix, I3)(3);
    SpdMatrix I3_dense(3, 1.0);
    CheckSparseMatrixBlock(I3, I3_dense);

    NEW(IdentityMatrix, I1)(1);
    SpdMatrix I1_dense(1, 1.0);
    CheckSparseMatrixBlock(I1, I1_dense);
  }

  TEST_F(SparseMatrixTest, LocalTrend) {
    NEW(LocalLinearTrendMatrix, T)();
    Matrix Tdense = T->dense();
    EXPECT_TRUE(VectorEquals(Tdense.row(0), Vector{1, 1}));
    EXPECT_TRUE(VectorEquals(Tdense.row(1), Vector{0, 1}));
    CheckSparseMatrixBlock(T, Tdense);
  }

  TEST_F(SparseMatrixTest, DenseMatrixTest) {
    Matrix square(4, 4);
    square.randomize();
    NEW(DenseMatrix, square_kalman)(square);
    CheckSparseMatrixBlock(square_kalman, square);

    Matrix rectangle(3, 4);
    rectangle.randomize();
    NEW(DenseMatrix, rectangle_kalman)(rectangle);
    CheckSparseMatrixBlock(rectangle_kalman, rectangle);
  }

  TEST_F(SparseMatrixTest, SpdTest) {
    SpdMatrix spd(3);
    spd.randomize();

    NEW(DenseSpd, spd_kalman)(spd);
    CheckSparseMatrixBlock(spd_kalman, spd);

    NEW(SpdParams, sparams)(spd);
    NEW(DenseSpdParamView, spd_view)(sparams);
    CheckSparseMatrixBlock(spd_view, spd);
  }

  TEST_F(SparseMatrixTest, Diagonal) {
    Vector values(4);
    values.randomize();

    NEW(DiagonalMatrixBlock, diag)(values);
    Matrix D(4, 4, 0.0);
    D.set_diag(values);

    CheckSparseMatrixBlock(diag, D);

    NEW(VectorParams, vprm)(values);
    NEW(DiagonalMatrixBlockVectorParamView, diag_view)(vprm);
    CheckSparseMatrixBlock(diag_view, D);
  }

  TEST_F(SparseMatrixTest, Seasonal) {
    NEW(SeasonalStateSpaceMatrix, seasonal)(4);
    Matrix seasonal_dense(4, 4, 0.0);
    seasonal_dense.row(0) = -1;
    seasonal_dense.subdiag(1) = 1.0;

    CheckSparseMatrixBlock(seasonal, seasonal_dense);
  }

  TEST_F(SparseMatrixTest, AutoRegression) {
    Vector elements(4);
    elements.randomize();
    NEW(GlmCoefs, rho)(elements);
    NEW(AutoRegressionTransitionMatrix, rho_kalman)(rho);
    Matrix rho_dense(4, 4);
    rho_dense.row(0) = elements;
    rho_dense.subdiag(1) = 1.0;

    CheckSparseMatrixBlock(rho_kalman, rho_dense);
  }

  TEST_F(SparseMatrixTest, EmptyTest) {
    Matrix empty;
    NEW(EmptyMatrix, empty_kalman)();
    CheckSparseMatrixBlock(empty_kalman, empty);
  }

  TEST_F(SparseMatrixTest, ConstantTest) {
    SpdMatrix dense(4, 8.7);
    NEW(ConstantMatrix, sparse)(4, 8.7);
    CheckSparseMatrixBlock(sparse, dense);

    NEW(UnivParams, prm)(8.7);
    NEW(ConstantMatrixParamView, sparse_view)(4, prm);
    CheckSparseMatrixBlock(sparse_view, dense);
  }

  TEST_F(SparseMatrixTest, ZeroTest) {
    NEW(ZeroMatrix, sparse)(7);
    Matrix dense(7, 7, 0.0);
    CheckSparseMatrixBlock(sparse, dense);
  }

  TEST_F(SparseMatrixTest, ULC) {
    NEW(UpperLeftCornerMatrix, sparse)(5, 19.2);
    Matrix dense(5, 5, 0.0);
    dense(0, 0) = 19.2;
    CheckSparseMatrixBlock(sparse, dense);

    NEW(UnivParams, prm)(19.2);
    NEW(UpperLeftCornerMatrixParamView, sparse_view)(5, prm);
    CheckSparseMatrixBlock(sparse_view, dense);
  }

  TEST_F(SparseMatrixTest, FirstElementSingleColumnMatrixTest) {
    NEW(FirstElementSingleColumnMatrix, sparse)(7);
    Matrix dense(7, 1, 0.0);
    dense(0, 0) = 1.0;
    CheckSparseMatrixBlock(sparse, dense);
  }

  TEST_F(SparseMatrixTest, ZeroPaddedIdTest) {
    NEW(ZeroPaddedIdentityMatrix, sparse)(20, 4);
    Matrix dense(20, 4);
    dense.set_diag(1.0);
    CheckSparseMatrixBlock(sparse, dense);
  }

  TEST_F(SparseMatrixTest, SingleSparseDiagonalElementMatrixTest) {
    NEW(SingleSparseDiagonalElementMatrix, sparse)(12, 18.7, 5);
    Matrix dense(12, 12, 0.0);
    dense(5, 5) = 18.7;
    CheckSparseMatrixBlock(sparse, dense);

    NEW(UnivParams, prm)(18.7);
    NEW(SingleSparseDiagonalElementMatrixParamView, sparse_view)(12, prm, 5);
    CheckSparseMatrixBlock(sparse_view, dense);
  }

  TEST_F(SparseMatrixTest, SingleElementInFirstRowTest) {
    NEW(SingleElementInFirstRow, sparse_square)(5, 5, 3, 12.9);
    Matrix dense(5, 5, 0.0);
    dense(0, 3) = 12.9;
    CheckSparseMatrixBlock(sparse_square, dense);

    NEW(SingleElementInFirstRow, sparse_rectangle)(5, 8, 0, 99.99);
    Matrix wide(5, 8, 0.0);
    wide(0, 0) = 99.99;
    CheckSparseMatrixBlock(sparse_rectangle, wide);

    NEW(SingleElementInFirstRow, sparse_tall)(20, 4, 2, 13.7);
    Matrix tall(20, 4, 0.0);
    tall(0, 2) = 13.7;
    CheckSparseMatrixBlock(sparse_tall, tall);
  }

  TEST_F(SparseMatrixTest, UpperLeftDiagonalTest) {
    std::vector<Ptr<UnivParams>> params;
    params.push_back(new UnivParams(3.2));
    params.push_back(new UnivParams(1.7));
    params.push_back(new UnivParams(-19.8));

    NEW(UpperLeftDiagonalMatrix, sparse)(params, 17);
    Matrix dense(17, 17, 0.0);
    for (int i = 0; i < params.size(); ++i) {
      dense(i, i) = params[i]->value();
    }
    CheckSparseMatrixBlock(sparse, dense);

    Vector scale_factor(3);
    scale_factor.randomize();
    dense.diag() *= scale_factor;
    NEW(UpperLeftDiagonalMatrix, sparse2)(params, 17, scale_factor);
    CheckSparseMatrixBlock(sparse2, dense);
  }

  TEST_F(SparseMatrixTest, IdenticalRowsMatrixTest) {
    SparseVector row(20);
    row[0] = 8;
    row[17] = 6;
    row[12] = 7;
    row[9] = 5;
    row[3] = 3;
    row[1] = 0;
    row[2] = 9;
    NEW(IdenticalRowsMatrix, sparse)(row, 20);
    Matrix dense(20, 20, 0.0);
    dense.col(0) = 8;
    dense.col(17) = 6;
    dense.col(12) = 7;
    dense.col(9) = 5;
    dense.col(3) = 3;
    dense.col(1) = 0;
    dense.col(2) = 9;
    CheckSparseMatrixBlock(sparse, dense);
  }

  Matrix ConstraintMatrix(int dim) {
    Matrix ans(dim, dim, 0.0);
    ans.set_diag(1.0);
    return ans - Matrix(dim, dim, 1.0 / dim);
  }

  TEST_F(SparseMatrixTest, EffectConstrainedMatrixBlockTest) {
    NEW(SeasonalStateSpaceMatrix, seasonal)(12);
    NEW(EffectConstrainedMatrixBlock, constrained_seasonal)(
        seasonal);
    CheckSparseMatrixBlock(constrained_seasonal,
                           seasonal->dense() * ConstraintMatrix(11));

  }

  TEST_F(SparseMatrixTest, GenericSparseMatrixBlockTest) {
    NEW(GenericSparseMatrixBlock, sparse)(12, 18);
    (*sparse)(3, 7) = 19;
    (*sparse)(5, 2) = -4;

    Matrix dense(12, 18, 0.0);
    dense(3, 7) = 19;
    dense(5, 2) = -4;
    CheckSparseMatrixBlock(sparse, dense);
  }

}  // namespace
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
/*=========================================================================
 *
 *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
 *
 *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
 *
 *  For complete copyright, license and disclaimer of warranty information
 *  please refer to the NOTICE file at the top of the ITK source tree.
 *
 *=========================================================================*/
#include "itkMultiThreader.h"
#include "itkObjectFactory.h"
#include "itksys/SystemTools.hxx"
#include <stdlib.h>

namespace itk
{
ThreadIdType MultiThreader::GetGlobalDefaultNumberOfThreadsByPlatform()
{
  int num;
  // If we are not multithreading, the number of threads should
  // always be 1
  num = 1;
  return num;
}

void MultiThreader::MultipleMethodExecute()
{
  ThreadIdType thread_loop;

  // obey the global maximum number of threads limit
  if ( m_NumberOfThreads > m_GlobalMaximumNumberOfThreads )
    {
    m_NumberOfThreads = m_GlobalMaximumNumberOfThreads;
    }

  for ( thread_loop = 0; thread_loop < m_NumberOfThreads; thread_loop++ )
    {
    if ( m_MultipleMethod[thread_loop] == (ThreadFunctionType)0 )
      {
      itkExceptionMacro(<< "No multiple method set for: " << thread_loop);
      return;
      }
    }

  // There is no multi threading, so there is only one thread.
  m_ThreadInfoArray[0].UserData    = m_MultipleData[0];
  m_ThreadInfoArray[0].NumberOfThreads = m_NumberOfThreads;
  ( m_MultipleMethod[0] )( (void *)( &m_ThreadInfoArray[0] ) );
}

ThreadIdType MultiThreader::SpawnThread(ThreadFunctionType f, void *UserData)
{
  int id = 0;

  while ( id < ITK_MAX_THREADS )
    {
    if ( !m_SpawnedThreadActiveFlagLock[id]  )
      {
      m_SpawnedThreadActiveFlagLock[id] = MutexLock::New();
      }
    m_SpawnedThreadActiveFlagLock[id]->Lock();
    if ( m_SpawnedThreadActiveFlag[id] == 0 )
      {
      // We've got a useable thread id, so grab it
      m_SpawnedThreadActiveFlag[id] = 1;
      m_SpawnedThreadActiveFlagLock[id]->Unlock();
      break;
      }
    m_SpawnedThreadActiveFlagLock[id]->Unlock();

    id++;
    }

  if ( id >= ITK_MAX_THREADS )
    {
    itkExceptionMacro(<< "You have too many active threads!");
    }

  m_SpawnedThreadInfoArray[id].UserData        = UserData;
  m_SpawnedThreadInfoArray[id].NumberOfThreads = 1;
  m_SpawnedThreadInfoArray[id].ActiveFlag = &m_SpawnedThreadActiveFlag[id];
  m_SpawnedThreadInfoArray[id].ActiveFlagLock = m_SpawnedThreadActiveFlagLock[id];

  // There is no multi threading, so there is only one thread.
  // This won't work - so give an error message.
  itkExceptionMacro(<< "Cannot spawn thread in a single threaded environment!");
  m_SpawnedThreadActiveFlagLock[id] = 0;
  id = -1;
  return id;
}

void MultiThreader::TerminateThread(ThreadIdType ThreadID)
{
  if ( !m_SpawnedThreadActiveFlag[ThreadID] )
    {
    return;
    }

  m_SpawnedThreadActiveFlagLock[ThreadID]->Lock();
  m_SpawnedThreadActiveFlag[ThreadID] = 0;
  m_SpawnedThreadActiveFlagLock[ThreadID]->Unlock();

  // There is no multi threading, so there is only one thread.
  // This won't work - so give an error message.
  itkExceptionMacro(<< "Cannot terminate thread in single threaded environment!");

  m_SpawnedThreadActiveFlagLock[ThreadID] = 0;
  m_SpawnedThreadActiveFlagLock[ThreadID] = 0;
}

void
MultiThreader
::ThreadPoolWaitForSingleMethodThread(ThreadProcessIdType threadHandle)
{
  // No threading library specified.  Do nothing.  No joining or waiting
  // necessary.
}

ThreadProcessIdType
MultiThreader
::ThreadPoolDispatchSingleMethodThread(MultiThreader::ThreadInfoStruct *threadInfo)
{
  // No threading library specified.  Do nothing.  The computation
  // will be run by the main execution thread.
}
void
MultiThreader
::SpawnWaitForSingleMethodThread(ThreadProcessIdType threadHandle)
{
  // No threading library specified.  Do nothing.  No joining or waiting
  // necessary.
}

ThreadProcessIdType
MultiThreader
::SpawnDispatchSingleMethodThread(MultiThreader::ThreadInfoStruct *threadInfo)
{
  // No threading library specified.  Do nothing.  The computation
  // will be run by the main execution thread.
}
} // end namespace itk
<commit_msg>COMP: Fix unused parameter warnings in itkMultiThreaderNoThreads.<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
/*=========================================================================
 *
 *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
 *
 *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
 *
 *  For complete copyright, license and disclaimer of warranty information
 *  please refer to the NOTICE file at the top of the ITK source tree.
 *
 *=========================================================================*/
#include "itkMultiThreader.h"
#include "itkObjectFactory.h"
#include "itksys/SystemTools.hxx"
#include <stdlib.h>

namespace itk
{
ThreadIdType MultiThreader::GetGlobalDefaultNumberOfThreadsByPlatform()
{
  int num;
  // If we are not multithreading, the number of threads should
  // always be 1
  num = 1;
  return num;
}

void MultiThreader::MultipleMethodExecute()
{
  ThreadIdType thread_loop;

  // obey the global maximum number of threads limit
  if ( m_NumberOfThreads > m_GlobalMaximumNumberOfThreads )
    {
    m_NumberOfThreads = m_GlobalMaximumNumberOfThreads;
    }

  for ( thread_loop = 0; thread_loop < m_NumberOfThreads; thread_loop++ )
    {
    if ( m_MultipleMethod[thread_loop] == (ThreadFunctionType)0 )
      {
      itkExceptionMacro(<< "No multiple method set for: " << thread_loop);
      return;
      }
    }

  // There is no multi threading, so there is only one thread.
  m_ThreadInfoArray[0].UserData    = m_MultipleData[0];
  m_ThreadInfoArray[0].NumberOfThreads = m_NumberOfThreads;
  ( m_MultipleMethod[0] )( (void *)( &m_ThreadInfoArray[0] ) );
}

ThreadIdType MultiThreader::SpawnThread(ThreadFunctionType itkNotUsed( f ), void *UserData)
{
  int id = 0;

  while ( id < ITK_MAX_THREADS )
    {
    if ( !m_SpawnedThreadActiveFlagLock[id]  )
      {
      m_SpawnedThreadActiveFlagLock[id] = MutexLock::New();
      }
    m_SpawnedThreadActiveFlagLock[id]->Lock();
    if ( m_SpawnedThreadActiveFlag[id] == 0 )
      {
      // We've got a useable thread id, so grab it
      m_SpawnedThreadActiveFlag[id] = 1;
      m_SpawnedThreadActiveFlagLock[id]->Unlock();
      break;
      }
    m_SpawnedThreadActiveFlagLock[id]->Unlock();

    id++;
    }

  if ( id >= ITK_MAX_THREADS )
    {
    itkExceptionMacro(<< "You have too many active threads!");
    }

  m_SpawnedThreadInfoArray[id].UserData        = UserData;
  m_SpawnedThreadInfoArray[id].NumberOfThreads = 1;
  m_SpawnedThreadInfoArray[id].ActiveFlag = &m_SpawnedThreadActiveFlag[id];
  m_SpawnedThreadInfoArray[id].ActiveFlagLock = m_SpawnedThreadActiveFlagLock[id];

  // There is no multi threading, so there is only one thread.
  // This won't work - so give an error message.
  itkExceptionMacro(<< "Cannot spawn thread in a single threaded environment!");
  m_SpawnedThreadActiveFlagLock[id] = 0;
  id = -1;
  return id;
}

void MultiThreader::TerminateThread(ThreadIdType ThreadID)
{
  if ( !m_SpawnedThreadActiveFlag[ThreadID] )
    {
    return;
    }

  m_SpawnedThreadActiveFlagLock[ThreadID]->Lock();
  m_SpawnedThreadActiveFlag[ThreadID] = 0;
  m_SpawnedThreadActiveFlagLock[ThreadID]->Unlock();

  // There is no multi threading, so there is only one thread.
  // This won't work - so give an error message.
  itkExceptionMacro(<< "Cannot terminate thread in single threaded environment!");

  m_SpawnedThreadActiveFlagLock[ThreadID] = 0;
  m_SpawnedThreadActiveFlagLock[ThreadID] = 0;
}

void
MultiThreader
::ThreadPoolWaitForSingleMethodThread(ThreadProcessIdType itkNotUsed( threadHandle ))
{
  // No threading library specified.  Do nothing.  No joining or waiting
  // necessary.
}

ThreadProcessIdType
MultiThreader
::ThreadPoolDispatchSingleMethodThread(MultiThreader::ThreadInfoStruct * itkNotUsed( threadInfo ))
{
  // No threading library specified.  Do nothing.  The computation
  // will be run by the main execution thread.
  return 0;
}
void
MultiThreader
::SpawnWaitForSingleMethodThread(ThreadProcessIdType itkNotUsed( threadHandle ))
{
  // No threading library specified.  Do nothing.  No joining or waiting
  // necessary.
}

ThreadProcessIdType
MultiThreader
::SpawnDispatchSingleMethodThread(MultiThreader::ThreadInfoStruct * itkNotUsed( threadInfo ))
{
  // No threading library specified.  Do nothing.  The computation
  // will be run by the main execution thread.
  return 0;
}
} // end namespace itk
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include <mitkPolhemusInterface.h>
#define _USE_MATH_DEFINES
#include <math.h>

#include <PDI.h>

BYTE  MotionBuf[0x1FA400];

mitk::PolhemusInterface::PolhemusInterface() : m_continousTracking(false)
{
  m_pdiDev = new CPDIdev();
  m_numberOfTools = 0;
}

mitk::PolhemusInterface::~PolhemusInterface()
{
  delete m_pdiDev;
}

bool mitk::PolhemusInterface::InitializeDevice()
{
  m_pdiDev->ResetTracker();
  m_pdiDev->ResetSAlignment(-1);
  m_pdiDev->Trace(TRUE, 7);
  m_continousTracking = false;
  return true;
}

bool mitk::PolhemusInterface::SetupDevice()
{
  m_pdiDev->SetPnoBuffer(MotionBuf, 0x1FA400);
  m_pdiDev->SetMetric(true); //use cm instead of inches

  m_pdiDev->StartPipeExport();

  CPDImdat pdiMDat;
  pdiMDat.Empty();
  pdiMDat.Append(PDI_MODATA_FRAMECOUNT);
  pdiMDat.Append(PDI_MODATA_POS);
  pdiMDat.Append(PDI_MODATA_ORI);
  m_pdiDev->SetSDataList(-1, pdiMDat);

  CPDIbiterr cBE;
  m_pdiDev->GetBITErrs(cBE);

  if (!(cBE.IsClear())) { m_pdiDev->ClearBITErrs(); }

  return true;
}

bool mitk::PolhemusInterface::StartTracking()
{
  LPCTSTR	szWindowClass = _T("PDIconsoleWinClass");
  HINSTANCE hInst = GetModuleHandle(0);
  HWND	hwnd = CreateWindowEx(
    WS_EX_NOACTIVATE,//WS_EX_STATICEDGE, //
    szWindowClass,
    _T("MyWindowName"),
    WS_POPUP,
    0, 0, 1, 1,
    HWND_MESSAGE,
    0,
    hInst,
    0);

  m_continousTracking = true;
  return m_pdiDev->StartContPno(hwnd);
}

bool mitk::PolhemusInterface::StopTracking()
{
  m_continousTracking = false;
  m_pdiDev->StopContPno();
  return true;
}

bool mitk::PolhemusInterface::Connect()
{
  bool returnValue;
  //Initialize, and if it is not successful, return false.
  if (!InitializeDevice())
  {
    returnValue = false;
  }
  //Connect
  else if (m_pdiDev->CnxReady())
  {
    returnValue = true;
  }
  //If it is not successful, search for connections.
  else
  {
    CPDIser  pdiSer;
    m_pdiDev->SetSerialIF(&pdiSer);

    ePiCommType eType = m_pdiDev->DiscoverCnx();
    switch (eType)
    {
    case PI_CNX_USB:
      MITK_INFO << "USB Connection: " << m_pdiDev->GetLastResultStr();
      break;
    case PI_CNX_SERIAL:
      MITK_INFO << "Serial Connection: " << m_pdiDev->GetLastResultStr();
      break;
    default:
      MITK_INFO << "DiscoverCnx result: " << m_pdiDev->GetLastResultStr();
      break;
    }

    //Setup device
    if (!SetupDevice())
    {
      returnValue = false;
    }
    else
    {
      returnValue = m_pdiDev->CnxReady();
    }
  }

  if (returnValue)
  {
    m_numberOfTools = this->GetNumberOfTools();
    //On first startUp or if number of tools changed
    if (m_Hemispheres.empty() || m_Hemispheres.size() != m_numberOfTools)
    {
      //Set Hemisphere for all tools to default 1,0,0...
      mitk::Vector3D temp;
      mitk::FillVector3D(temp, 1, 0, 0);
      m_Hemispheres.clear();
      m_Hemispheres.assign(m_numberOfTools, temp);
      this->SetHemisphere(-1, temp);
    }
  }

  return returnValue;

}

bool mitk::PolhemusInterface::Disconnect()
{
  bool returnValue = true;
  //If Tracking is running, stop tracking first
  if (m_continousTracking)
  {
    this->StopTracking();
  }

  returnValue = m_pdiDev->Disconnect();
  MITK_INFO << "Disconnect: " << m_pdiDev->GetLastResultStr();
  return returnValue;
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::GetLastFrame()
{
  PBYTE pBuf;
  DWORD dwSize;

  //read one frame
  if (!m_pdiDev->LastPnoPtr(pBuf, dwSize)) { MITK_WARN << m_pdiDev->GetLastResultStr(); }

  std::vector<mitk::PolhemusInterface::trackingData> returnValue = ParsePolhemusRawData(pBuf, dwSize);

  if (returnValue.empty()) { MITK_WARN << "Cannot parse data / no tools present"; }

  return returnValue;
}

unsigned int mitk::PolhemusInterface::GetNumberOfTools()
{
  if (m_continousTracking) return GetLastFrame().size();
  else return GetSingleFrame().size();
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::GetSingleFrame()
{
  if (m_continousTracking)
  {
    MITK_WARN << "Cannot get a single frame when continuous tracking is on!";
    return std::vector<mitk::PolhemusInterface::trackingData>();
  }
  PBYTE pBuf;
  DWORD dwSize;

  //read one frame
  if (!m_pdiDev->ReadSinglePnoBuf(pBuf, dwSize)) {
    MITK_WARN << m_pdiDev->GetLastResultStr();
    return std::vector<mitk::PolhemusInterface::trackingData>();
  }

  return ParsePolhemusRawData(pBuf, dwSize);
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::ParsePolhemusRawData(PBYTE pBuf, DWORD dwSize)
{
  std::vector<mitk::PolhemusInterface::trackingData> returnValue;

  DWORD i = 0;

  while (i < dwSize)
  {
    BYTE ucSensor = pBuf[i + 2];
    SHORT shSize = pBuf[i + 6];

    // skip rest of header
    i += 8;

    PDWORD pFC = (PDWORD)(&pBuf[i]);
    PFLOAT pPno = (PFLOAT)(&pBuf[i + 4]);

    mitk::PolhemusInterface::trackingData currentTrackingData;

    currentTrackingData.id = ucSensor;

    currentTrackingData.pos[0] = pPno[0] * 10; //from cm to mm
    currentTrackingData.pos[1] = pPno[1] * 10;
    currentTrackingData.pos[2] = pPno[2] * 10;

    double azimuthAngle = pPno[3] / 180 * M_PI; //from degree to rad
    double elevationAngle = pPno[4] / 180 * M_PI;
    double rollAngle = pPno[5] / 180 * M_PI;
    vnl_quaternion<double> eulerQuat(rollAngle, elevationAngle, azimuthAngle);
    currentTrackingData.rot = eulerQuat;

    returnValue.push_back(currentTrackingData);
    i += shSize;
  }
  return returnValue;
}

void mitk::PolhemusInterface::SetHemisphereTrackingEnabled(bool _HeisphereTrackingEnabeled)
{
  //HemisphereTracking is switched on by SetSHemiTrack(-1). "-1" means for all sensors.
  //To switch heisphere tracking of, you need to set a hemisphere vector by calling SetSHemisphere(-1, { (float)1,0,0 })
  if (_HeisphereTrackingEnabeled)
  {
    m_pdiDev->SetSHemiTrack(-1);
  }
  else if (!m_Hemispheres.empty())
  {
    for (int i = 0; i < m_numberOfTools; ++i)
      SetHemisphere(i + 1, m_Hemispheres.at(i));
  }
  else
  {
    //Default Hemisphere
    mitk::Vector3D temp;
    mitk::FillVector3D(temp, 1, 0, 0);
    m_Hemispheres.clear();
    m_Hemispheres.assign(m_numberOfTools, temp);
    this->SetHemisphere(-1, temp);
    //MITK_INFO << m_pdiDev->GetLastResultStr();
  }
}

void mitk::PolhemusInterface::ToggleHemisphere(int _tool)
{
  BOOL _hemiTrack;
  //m_hemisphere indices start at 0, tool count starts at 1
  //-1 == all tools
  if (_tool == -1)
  {
    for (int i = 0; i < m_numberOfTools; ++i)
    {
      //is hemiTrack on?
      m_pdiDev->GetSHemiTrack(i+1,_hemiTrack);

      m_Hemispheres.at(i)[0] = -m_Hemispheres.at(i)[0];
      m_Hemispheres.at(i)[1] = -m_Hemispheres.at(i)[1];
      m_Hemispheres.at(i)[2] = -m_Hemispheres.at(i)[2];
      SetHemisphere(i+1, m_Hemispheres.at(i));
      if (_hemiTrack) m_pdiDev->SetSHemiTrack(i+1);
    }
  }
  else
  {
    //is hemiTrack on?
    m_pdiDev->GetSHemiTrack(_tool, _hemiTrack);

    m_Hemispheres.at(_tool - 1)[0] = -m_Hemispheres.at(_tool - 1)[0];
    m_Hemispheres.at(_tool - 1)[1] = -m_Hemispheres.at(_tool - 1)[1];
    m_Hemispheres.at(_tool - 1)[2] = -m_Hemispheres.at(_tool - 1)[2];
    SetHemisphere(_tool, m_Hemispheres.at(_tool - 1));
    if (_hemiTrack) m_pdiDev->SetSHemiTrack(_tool);
  }

}

void mitk::PolhemusInterface::SetHemisphere(int _tool, mitk::Vector3D _hemisphere)
{
  m_pdiDev->SetSHemisphere(_tool, { (float)_hemisphere[0], (float)_hemisphere[1], (float)_hemisphere[2] });
}

void mitk::PolhemusInterface::PrintStatus()
{
  MITK_INFO << "Polhemus status: " << this->m_pdiDev->CnxReady();
}<commit_msg>Window handle is not necessary and is not used. Parameter replaced by 0, works aswell.<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include <mitkPolhemusInterface.h>
#define _USE_MATH_DEFINES
#include <math.h>

#include <PDI.h>

BYTE  MotionBuf[0x1FA400];

mitk::PolhemusInterface::PolhemusInterface() : m_continousTracking(false)
{
  m_pdiDev = new CPDIdev();
  m_numberOfTools = 0;
}

mitk::PolhemusInterface::~PolhemusInterface()
{
  delete m_pdiDev;
}

bool mitk::PolhemusInterface::InitializeDevice()
{
  m_pdiDev->ResetTracker();
  m_pdiDev->ResetSAlignment(-1);
  m_pdiDev->Trace(TRUE, 7);
  m_continousTracking = false;
  return true;
}

bool mitk::PolhemusInterface::SetupDevice()
{
  m_pdiDev->SetPnoBuffer(MotionBuf, 0x1FA400);
  m_pdiDev->SetMetric(true); //use cm instead of inches

  m_pdiDev->StartPipeExport();

  CPDImdat pdiMDat;
  pdiMDat.Empty();
  pdiMDat.Append(PDI_MODATA_FRAMECOUNT);
  pdiMDat.Append(PDI_MODATA_POS);
  pdiMDat.Append(PDI_MODATA_ORI);
  m_pdiDev->SetSDataList(-1, pdiMDat);

  CPDIbiterr cBE;
  m_pdiDev->GetBITErrs(cBE);

  if (!(cBE.IsClear())) { m_pdiDev->ClearBITErrs(); }

  return true;
}

bool mitk::PolhemusInterface::StartTracking()
{
  m_continousTracking = true;
  return m_pdiDev->StartContPno(0);
}

bool mitk::PolhemusInterface::StopTracking()
{
  m_continousTracking = false;
  m_pdiDev->StopContPno();
  return true;
}

bool mitk::PolhemusInterface::Connect()
{
  bool returnValue;
  //Initialize, and if it is not successful, return false.
  if (!InitializeDevice())
  {
    returnValue = false;
  }
  //Connect
  else if (m_pdiDev->CnxReady())
  {
    returnValue = true;
  }
  //If it is not successful, search for connections.
  else
  {
    CPDIser  pdiSer;
    m_pdiDev->SetSerialIF(&pdiSer);

    ePiCommType eType = m_pdiDev->DiscoverCnx();
    switch (eType)
    {
    case PI_CNX_USB:
      MITK_INFO << "USB Connection: " << m_pdiDev->GetLastResultStr();
      break;
    case PI_CNX_SERIAL:
      MITK_INFO << "Serial Connection: " << m_pdiDev->GetLastResultStr();
      break;
    default:
      MITK_INFO << "DiscoverCnx result: " << m_pdiDev->GetLastResultStr();
      break;
    }

    //Setup device
    if (!SetupDevice())
    {
      returnValue = false;
    }
    else
    {
      returnValue = m_pdiDev->CnxReady();
    }
  }

  if (returnValue)
  {
    m_numberOfTools = this->GetNumberOfTools();
    //On first startUp or if number of tools changed
    if (m_Hemispheres.empty() || m_Hemispheres.size() != m_numberOfTools)
    {
      //Set Hemisphere for all tools to default 1,0,0...
      mitk::Vector3D temp;
      mitk::FillVector3D(temp, 1, 0, 0);
      m_Hemispheres.clear();
      m_Hemispheres.assign(m_numberOfTools, temp);
      this->SetHemisphere(-1, temp);
    }
  }

  return returnValue;

}

bool mitk::PolhemusInterface::Disconnect()
{
  bool returnValue = true;
  //If Tracking is running, stop tracking first
  if (m_continousTracking)
  {
    this->StopTracking();
  }

  returnValue = m_pdiDev->Disconnect();
  MITK_INFO << "Disconnect: " << m_pdiDev->GetLastResultStr();
  return returnValue;
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::GetLastFrame()
{
  PBYTE pBuf;
  DWORD dwSize;

  //read one frame
  if (!m_pdiDev->LastPnoPtr(pBuf, dwSize)) { MITK_WARN << m_pdiDev->GetLastResultStr(); }

  std::vector<mitk::PolhemusInterface::trackingData> returnValue = ParsePolhemusRawData(pBuf, dwSize);

  if (returnValue.empty()) { MITK_WARN << "Cannot parse data / no tools present"; }

  return returnValue;
}

unsigned int mitk::PolhemusInterface::GetNumberOfTools()
{
  if (m_continousTracking) return GetLastFrame().size();
  else return GetSingleFrame().size();
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::GetSingleFrame()
{
  if (m_continousTracking)
  {
    MITK_WARN << "Cannot get a single frame when continuous tracking is on!";
    return std::vector<mitk::PolhemusInterface::trackingData>();
  }
  PBYTE pBuf;
  DWORD dwSize;

  //read one frame
  if (!m_pdiDev->ReadSinglePnoBuf(pBuf, dwSize)) {
    MITK_WARN << m_pdiDev->GetLastResultStr();
    return std::vector<mitk::PolhemusInterface::trackingData>();
  }

  return ParsePolhemusRawData(pBuf, dwSize);
}

std::vector<mitk::PolhemusInterface::trackingData> mitk::PolhemusInterface::ParsePolhemusRawData(PBYTE pBuf, DWORD dwSize)
{
  std::vector<mitk::PolhemusInterface::trackingData> returnValue;

  DWORD i = 0;

  while (i < dwSize)
  {
    BYTE ucSensor = pBuf[i + 2];
    SHORT shSize = pBuf[i + 6];

    // skip rest of header
    i += 8;

    PDWORD pFC = (PDWORD)(&pBuf[i]);
    PFLOAT pPno = (PFLOAT)(&pBuf[i + 4]);

    mitk::PolhemusInterface::trackingData currentTrackingData;

    currentTrackingData.id = ucSensor;

    currentTrackingData.pos[0] = pPno[0] * 10; //from cm to mm
    currentTrackingData.pos[1] = pPno[1] * 10;
    currentTrackingData.pos[2] = pPno[2] * 10;

    double azimuthAngle = pPno[3] / 180 * M_PI; //from degree to rad
    double elevationAngle = pPno[4] / 180 * M_PI;
    double rollAngle = pPno[5] / 180 * M_PI;
    vnl_quaternion<double> eulerQuat(rollAngle, elevationAngle, azimuthAngle);
    currentTrackingData.rot = eulerQuat;

    returnValue.push_back(currentTrackingData);
    i += shSize;
  }
  return returnValue;
}

void mitk::PolhemusInterface::SetHemisphereTrackingEnabled(bool _HeisphereTrackingEnabeled)
{
  //HemisphereTracking is switched on by SetSHemiTrack(-1). "-1" means for all sensors.
  //To switch heisphere tracking of, you need to set a hemisphere vector by calling SetSHemisphere(-1, { (float)1,0,0 })
  if (_HeisphereTrackingEnabeled)
  {
    m_pdiDev->SetSHemiTrack(-1);
  }
  else if (!m_Hemispheres.empty())
  {
    for (int i = 0; i < m_numberOfTools; ++i)
      SetHemisphere(i + 1, m_Hemispheres.at(i));
  }
  else
  {
    //Default Hemisphere
    mitk::Vector3D temp;
    mitk::FillVector3D(temp, 1, 0, 0);
    m_Hemispheres.clear();
    m_Hemispheres.assign(m_numberOfTools, temp);
    this->SetHemisphere(-1, temp);
    //MITK_INFO << m_pdiDev->GetLastResultStr();
  }
}

void mitk::PolhemusInterface::ToggleHemisphere(int _tool)
{
  BOOL _hemiTrack;
  //m_hemisphere indices start at 0, tool count starts at 1
  //-1 == all tools
  if (_tool == -1)
  {
    for (int i = 0; i < m_numberOfTools; ++i)
    {
      //is hemiTrack on?
      m_pdiDev->GetSHemiTrack(i+1,_hemiTrack);

      m_Hemispheres.at(i)[0] = -m_Hemispheres.at(i)[0];
      m_Hemispheres.at(i)[1] = -m_Hemispheres.at(i)[1];
      m_Hemispheres.at(i)[2] = -m_Hemispheres.at(i)[2];
      SetHemisphere(i+1, m_Hemispheres.at(i));
      if (_hemiTrack) m_pdiDev->SetSHemiTrack(i+1);
    }
  }
  else
  {
    //is hemiTrack on?
    m_pdiDev->GetSHemiTrack(_tool, _hemiTrack);

    m_Hemispheres.at(_tool - 1)[0] = -m_Hemispheres.at(_tool - 1)[0];
    m_Hemispheres.at(_tool - 1)[1] = -m_Hemispheres.at(_tool - 1)[1];
    m_Hemispheres.at(_tool - 1)[2] = -m_Hemispheres.at(_tool - 1)[2];
    SetHemisphere(_tool, m_Hemispheres.at(_tool - 1));
    if (_hemiTrack) m_pdiDev->SetSHemiTrack(_tool);
  }

}

void mitk::PolhemusInterface::SetHemisphere(int _tool, mitk::Vector3D _hemisphere)
{
  m_pdiDev->SetSHemisphere(_tool, { (float)_hemisphere[0], (float)_hemisphere[1], (float)_hemisphere[2] });
}

void mitk::PolhemusInterface::PrintStatus()
{
  MITK_INFO << "Polhemus status: " << this->m_pdiDev->CnxReady();
}<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "rtl/uuid.h"
#include "osl/thread.h"
#include "osl/mutex.hxx"

#include "uno/environment.hxx"
#include "uno/mapping.hxx"
#include "uno/lbnames.h"
#include "typelib/typedescription.h"

#include "current.hxx"

using namespace ::osl;
using namespace ::rtl;
using namespace ::cppu;
using namespace ::com::sun::star::uno;

namespace cppu
{

//--------------------------------------------------------------------------------------------------
class SAL_NO_VTABLE XInterface
{
public:
    virtual void SAL_CALL slot_queryInterface() = 0;
    virtual void SAL_CALL acquire() throw () = 0;
    virtual void SAL_CALL release() throw () = 0;
protected:
    ~XInterface() {}
        // avoid warnings about virtual members and non-virtual dtor
};
//--------------------------------------------------------------------------------------------------
static typelib_InterfaceTypeDescription * get_type_XCurrentContext()
{
    static typelib_InterfaceTypeDescription * s_type_XCurrentContext = 0;
    if (0 == s_type_XCurrentContext)
    {
        ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
        if (0 == s_type_XCurrentContext)
        {
            OUString sTypeName( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XCurrentContext") );
            typelib_InterfaceTypeDescription * pTD = 0;
            typelib_TypeDescriptionReference * pMembers[1] = { 0 };
            OUString sMethodName0(
                RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XCurrentContext::getValueByName") );
            typelib_typedescriptionreference_new(
                &pMembers[0],
                typelib_TypeClass_INTERFACE_METHOD,
                sMethodName0.pData );
            typelib_typedescription_newInterface(
                &pTD,
                sTypeName.pData, 0x00000000, 0x0000, 0x0000, 0x00000000, 0x00000000,
                * typelib_static_type_getByTypeClass( typelib_TypeClass_INTERFACE ),
                1,
                pMembers );

            typelib_typedescription_register( (typelib_TypeDescription**)&pTD );
            typelib_typedescriptionreference_release( pMembers[0] );

            typelib_InterfaceMethodTypeDescription * pMethod = 0;
            typelib_Parameter_Init aParameters[1];
            OUString sParamName0( RTL_CONSTASCII_USTRINGPARAM("Name") );
            OUString sParamType0( RTL_CONSTASCII_USTRINGPARAM("string") );
            aParameters[0].pParamName = sParamName0.pData;
            aParameters[0].eTypeClass = typelib_TypeClass_STRING;
            aParameters[0].pTypeName = sParamType0.pData;
            aParameters[0].bIn = sal_True;
            aParameters[0].bOut = sal_False;
            rtl_uString * pExceptions[1];
            OUString sExceptionName0(
                RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.RuntimeException") );
            pExceptions[0] = sExceptionName0.pData;
            OUString sReturnType0( RTL_CONSTASCII_USTRINGPARAM("any") );
            typelib_typedescription_newInterfaceMethod(
                &pMethod,
                3, sal_False,
                sMethodName0.pData,
                typelib_TypeClass_ANY, sReturnType0.pData,
                1, aParameters, 1, pExceptions );
            typelib_typedescription_register( (typelib_TypeDescription**)&pMethod );
            typelib_typedescription_release( (typelib_TypeDescription*)pMethod );
            // another static ref:
            ++reinterpret_cast< typelib_TypeDescription * >( pTD )->
                nStaticRefCount;
            s_type_XCurrentContext = pTD;
        }
    }
    return s_type_XCurrentContext;
}

//##################################################################################################

//==================================================================================================
class ThreadKey
{
    sal_Bool     _bInit;
    oslThreadKey _hThreadKey;
    oslThreadKeyCallbackFunction _pCallback;

public:
    inline oslThreadKey getThreadKey() SAL_THROW(());

    inline ThreadKey( oslThreadKeyCallbackFunction pCallback ) SAL_THROW(());
    inline ~ThreadKey() SAL_THROW(());
};
//__________________________________________________________________________________________________
inline ThreadKey::ThreadKey( oslThreadKeyCallbackFunction pCallback ) SAL_THROW(())
    : _bInit( sal_False )
    , _pCallback( pCallback )
{
}
//__________________________________________________________________________________________________
inline ThreadKey::~ThreadKey() SAL_THROW(())
{
    if (_bInit)
    {
        ::osl_destroyThreadKey( _hThreadKey );
    }
}
//__________________________________________________________________________________________________
inline oslThreadKey ThreadKey::getThreadKey() SAL_THROW(())
{
    if (! _bInit)
    {
        MutexGuard aGuard( Mutex::getGlobalMutex() );
        if (! _bInit)
        {
            _hThreadKey = ::osl_createThreadKey( _pCallback );
            _bInit = sal_True;
        }
    }
    return _hThreadKey;
}

//==================================================================================================
extern "C" void SAL_CALL delete_IdContainer( void * p )
{
    if (p)
    {
        IdContainer * pId = reinterpret_cast< IdContainer * >( p );
        if (pId->pCurrentContext)
        {
            (*pId->pCurrentContextEnv->releaseInterface)(
                pId->pCurrentContextEnv, pId->pCurrentContext );
            (*((uno_Environment *)pId->pCurrentContextEnv)->release)(
                (uno_Environment *)pId->pCurrentContextEnv );
        }
        if (pId->bInit)
        {
            ::rtl_byte_sequence_release( pId->pLocalThreadId );
            ::rtl_byte_sequence_release( pId->pCurrentId );
        }
        delete pId;
    }
}
//==================================================================================================
IdContainer * getIdContainer() SAL_THROW(())
{
    static ThreadKey s_key( delete_IdContainer );
    oslThreadKey aKey = s_key.getThreadKey();

    IdContainer * pId = reinterpret_cast< IdContainer * >( ::osl_getThreadKeyData( aKey ) );
    if (! pId)
    {
        pId = new IdContainer();
        pId->pCurrentContext = 0;
        pId->pCurrentContextEnv = 0;
        pId->bInit = sal_False;
        ::osl_setThreadKeyData( aKey, pId );
    }
    return pId;
}

}

//##################################################################################################
extern "C" CPPU_DLLPUBLIC sal_Bool SAL_CALL uno_setCurrentContext(
    void * pCurrentContext,
    rtl_uString * pEnvTypeName, void * pEnvContext )
    SAL_THROW_EXTERN_C()
{
    IdContainer * pId = getIdContainer();
    OSL_ASSERT( pId );

    // free old one
    if (pId->pCurrentContext)
    {
        (*pId->pCurrentContextEnv->releaseInterface)(
            pId->pCurrentContextEnv, pId->pCurrentContext );
        (*((uno_Environment *)pId->pCurrentContextEnv)->release)(
            (uno_Environment *)pId->pCurrentContextEnv );
        pId->pCurrentContextEnv = 0;

        pId->pCurrentContext = 0;
    }

    if (pCurrentContext)
    {
        uno_Environment * pEnv = 0;
        ::uno_getEnvironment( &pEnv, pEnvTypeName, pEnvContext );
        OSL_ASSERT( pEnv && pEnv->pExtEnv );
        if (pEnv)
        {
            if (pEnv->pExtEnv)
            {
                pId->pCurrentContextEnv = pEnv->pExtEnv;
                (*pId->pCurrentContextEnv->acquireInterface)(
                    pId->pCurrentContextEnv, pCurrentContext );
                pId->pCurrentContext = pCurrentContext;
            }
            else
            {
                (*pEnv->release)( pEnv );
                return sal_False;
            }
        }
        else
        {
            return sal_False;
        }
    }
    return sal_True;
}
//##################################################################################################
extern "C" CPPU_DLLPUBLIC sal_Bool SAL_CALL uno_getCurrentContext(
    void ** ppCurrentContext, rtl_uString * pEnvTypeName, void * pEnvContext )
    SAL_THROW_EXTERN_C()
{
    IdContainer * pId = getIdContainer();
    OSL_ASSERT( pId );

    Environment target_env;

    // release inout parameter
    if (*ppCurrentContext)
    {
        target_env = Environment(rtl::OUString(pEnvTypeName), pEnvContext);
        OSL_ASSERT( target_env.is() );
        if (! target_env.is())
            return sal_False;
        uno_ExtEnvironment * pEnv = target_env.get()->pExtEnv;
        OSL_ASSERT( 0 != pEnv );
        if (0 == pEnv)
            return sal_False;
        (*pEnv->releaseInterface)( pEnv, *ppCurrentContext );

        *ppCurrentContext = 0;
    }

    // case: null-ref
    if (0 == pId->pCurrentContext)
        return sal_True;

    if (! target_env.is())
    {
        target_env = Environment(rtl::OUString(pEnvTypeName), pEnvContext);
        OSL_ASSERT( target_env.is() );
        if (! target_env.is())
            return sal_False;
    }

    Mapping mapping((uno_Environment *) pId->pCurrentContextEnv, target_env.get());
    OSL_ASSERT( mapping.is() );
    if (! mapping.is())
        return sal_False;

    mapping.mapInterface(ppCurrentContext, pId->pCurrentContext, ::cppu::get_type_XCurrentContext() );

    return sal_True;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Dead code<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "rtl/uuid.h"
#include "osl/thread.h"
#include "osl/mutex.hxx"

#include "uno/environment.hxx"
#include "uno/mapping.hxx"
#include "uno/lbnames.h"
#include "typelib/typedescription.h"

#include "current.hxx"

using namespace ::osl;
using namespace ::rtl;
using namespace ::cppu;
using namespace ::com::sun::star::uno;

namespace cppu
{

static typelib_InterfaceTypeDescription * get_type_XCurrentContext()
{
    static typelib_InterfaceTypeDescription * s_type_XCurrentContext = 0;
    if (0 == s_type_XCurrentContext)
    {
        ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
        if (0 == s_type_XCurrentContext)
        {
            OUString sTypeName( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XCurrentContext") );
            typelib_InterfaceTypeDescription * pTD = 0;
            typelib_TypeDescriptionReference * pMembers[1] = { 0 };
            OUString sMethodName0(
                RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XCurrentContext::getValueByName") );
            typelib_typedescriptionreference_new(
                &pMembers[0],
                typelib_TypeClass_INTERFACE_METHOD,
                sMethodName0.pData );
            typelib_typedescription_newInterface(
                &pTD,
                sTypeName.pData, 0x00000000, 0x0000, 0x0000, 0x00000000, 0x00000000,
                * typelib_static_type_getByTypeClass( typelib_TypeClass_INTERFACE ),
                1,
                pMembers );

            typelib_typedescription_register( (typelib_TypeDescription**)&pTD );
            typelib_typedescriptionreference_release( pMembers[0] );

            typelib_InterfaceMethodTypeDescription * pMethod = 0;
            typelib_Parameter_Init aParameters[1];
            OUString sParamName0( RTL_CONSTASCII_USTRINGPARAM("Name") );
            OUString sParamType0( RTL_CONSTASCII_USTRINGPARAM("string") );
            aParameters[0].pParamName = sParamName0.pData;
            aParameters[0].eTypeClass = typelib_TypeClass_STRING;
            aParameters[0].pTypeName = sParamType0.pData;
            aParameters[0].bIn = sal_True;
            aParameters[0].bOut = sal_False;
            rtl_uString * pExceptions[1];
            OUString sExceptionName0(
                RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.RuntimeException") );
            pExceptions[0] = sExceptionName0.pData;
            OUString sReturnType0( RTL_CONSTASCII_USTRINGPARAM("any") );
            typelib_typedescription_newInterfaceMethod(
                &pMethod,
                3, sal_False,
                sMethodName0.pData,
                typelib_TypeClass_ANY, sReturnType0.pData,
                1, aParameters, 1, pExceptions );
            typelib_typedescription_register( (typelib_TypeDescription**)&pMethod );
            typelib_typedescription_release( (typelib_TypeDescription*)pMethod );
            // another static ref:
            ++reinterpret_cast< typelib_TypeDescription * >( pTD )->
                nStaticRefCount;
            s_type_XCurrentContext = pTD;
        }
    }
    return s_type_XCurrentContext;
}

//##################################################################################################

//==================================================================================================
class ThreadKey
{
    sal_Bool     _bInit;
    oslThreadKey _hThreadKey;
    oslThreadKeyCallbackFunction _pCallback;

public:
    inline oslThreadKey getThreadKey() SAL_THROW(());

    inline ThreadKey( oslThreadKeyCallbackFunction pCallback ) SAL_THROW(());
    inline ~ThreadKey() SAL_THROW(());
};
//__________________________________________________________________________________________________
inline ThreadKey::ThreadKey( oslThreadKeyCallbackFunction pCallback ) SAL_THROW(())
    : _bInit( sal_False )
    , _pCallback( pCallback )
{
}
//__________________________________________________________________________________________________
inline ThreadKey::~ThreadKey() SAL_THROW(())
{
    if (_bInit)
    {
        ::osl_destroyThreadKey( _hThreadKey );
    }
}
//__________________________________________________________________________________________________
inline oslThreadKey ThreadKey::getThreadKey() SAL_THROW(())
{
    if (! _bInit)
    {
        MutexGuard aGuard( Mutex::getGlobalMutex() );
        if (! _bInit)
        {
            _hThreadKey = ::osl_createThreadKey( _pCallback );
            _bInit = sal_True;
        }
    }
    return _hThreadKey;
}

//==================================================================================================
extern "C" void SAL_CALL delete_IdContainer( void * p )
{
    if (p)
    {
        IdContainer * pId = reinterpret_cast< IdContainer * >( p );
        if (pId->pCurrentContext)
        {
            (*pId->pCurrentContextEnv->releaseInterface)(
                pId->pCurrentContextEnv, pId->pCurrentContext );
            (*((uno_Environment *)pId->pCurrentContextEnv)->release)(
                (uno_Environment *)pId->pCurrentContextEnv );
        }
        if (pId->bInit)
        {
            ::rtl_byte_sequence_release( pId->pLocalThreadId );
            ::rtl_byte_sequence_release( pId->pCurrentId );
        }
        delete pId;
    }
}
//==================================================================================================
IdContainer * getIdContainer() SAL_THROW(())
{
    static ThreadKey s_key( delete_IdContainer );
    oslThreadKey aKey = s_key.getThreadKey();

    IdContainer * pId = reinterpret_cast< IdContainer * >( ::osl_getThreadKeyData( aKey ) );
    if (! pId)
    {
        pId = new IdContainer();
        pId->pCurrentContext = 0;
        pId->pCurrentContextEnv = 0;
        pId->bInit = sal_False;
        ::osl_setThreadKeyData( aKey, pId );
    }
    return pId;
}

}

//##################################################################################################
extern "C" CPPU_DLLPUBLIC sal_Bool SAL_CALL uno_setCurrentContext(
    void * pCurrentContext,
    rtl_uString * pEnvTypeName, void * pEnvContext )
    SAL_THROW_EXTERN_C()
{
    IdContainer * pId = getIdContainer();
    OSL_ASSERT( pId );

    // free old one
    if (pId->pCurrentContext)
    {
        (*pId->pCurrentContextEnv->releaseInterface)(
            pId->pCurrentContextEnv, pId->pCurrentContext );
        (*((uno_Environment *)pId->pCurrentContextEnv)->release)(
            (uno_Environment *)pId->pCurrentContextEnv );
        pId->pCurrentContextEnv = 0;

        pId->pCurrentContext = 0;
    }

    if (pCurrentContext)
    {
        uno_Environment * pEnv = 0;
        ::uno_getEnvironment( &pEnv, pEnvTypeName, pEnvContext );
        OSL_ASSERT( pEnv && pEnv->pExtEnv );
        if (pEnv)
        {
            if (pEnv->pExtEnv)
            {
                pId->pCurrentContextEnv = pEnv->pExtEnv;
                (*pId->pCurrentContextEnv->acquireInterface)(
                    pId->pCurrentContextEnv, pCurrentContext );
                pId->pCurrentContext = pCurrentContext;
            }
            else
            {
                (*pEnv->release)( pEnv );
                return sal_False;
            }
        }
        else
        {
            return sal_False;
        }
    }
    return sal_True;
}
//##################################################################################################
extern "C" CPPU_DLLPUBLIC sal_Bool SAL_CALL uno_getCurrentContext(
    void ** ppCurrentContext, rtl_uString * pEnvTypeName, void * pEnvContext )
    SAL_THROW_EXTERN_C()
{
    IdContainer * pId = getIdContainer();
    OSL_ASSERT( pId );

    Environment target_env;

    // release inout parameter
    if (*ppCurrentContext)
    {
        target_env = Environment(rtl::OUString(pEnvTypeName), pEnvContext);
        OSL_ASSERT( target_env.is() );
        if (! target_env.is())
            return sal_False;
        uno_ExtEnvironment * pEnv = target_env.get()->pExtEnv;
        OSL_ASSERT( 0 != pEnv );
        if (0 == pEnv)
            return sal_False;
        (*pEnv->releaseInterface)( pEnv, *ppCurrentContext );

        *ppCurrentContext = 0;
    }

    // case: null-ref
    if (0 == pId->pCurrentContext)
        return sal_True;

    if (! target_env.is())
    {
        target_env = Environment(rtl::OUString(pEnvTypeName), pEnvContext);
        OSL_ASSERT( target_env.is() );
        if (! target_env.is())
            return sal_False;
    }

    Mapping mapping((uno_Environment *) pId->pCurrentContextEnv, target_env.get());
    OSL_ASSERT( mapping.is() );
    if (! mapping.is())
        return sal_False;

    mapping.mapInterface(ppCurrentContext, pId->pCurrentContext, ::cppu::get_type_XCurrentContext() );

    return sal_True;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>