<commit_before>/// @file   basicRangedAttack.cpp
/// @brief  Contais the implementation of the class for the basic ranged attacks.
/// @author Enrico Fraccaroli
/// @date   Jul 14 2016
/// @copyright
/// Copyright (c) 2016 Enrico Fraccaroli <enrico.fraccaroli@gmail.com>
/// Permission to use, copy, modify, and distribute this software for any
/// purpose with or without fee is hereby granted, provided that the above
/// copyright notice and this permission notice appear in all copies.
///
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
/// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
/// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
/// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
/// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
/// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
/// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include "basicRangedAttack.hpp"
#include "rangedWeaponModel.hpp"
#include "rangedWeaponItem.hpp"
#include "formatter.hpp"
#include "room.hpp"

BasicRangedAttack::BasicRangedAttack(Character * _actor) :
    CombatAction(_actor)
{
    Logger::log(LogLevel::Debug, "Created BasicRangedAttack.");
}

BasicRangedAttack::~BasicRangedAttack()
{
    Logger::log(LogLevel::Debug, "Deleted BasicRangedAttack.");
}

bool BasicRangedAttack::check(std::string & error) const
{
    if (!CombatAction::check(error))
    {
        return false;
    }
    return true;
}

ActionType BasicRangedAttack::getType() const
{
    return ActionType::Combat;
}

std::string BasicRangedAttack::getDescription() const
{
    return "fighting";
}

std::string BasicRangedAttack::stop()
{
    return "You stop fighting.";
}

ActionStatus BasicRangedAttack::perform()
{
    // Check if the cooldown is ended.
    if (!this->checkElapsed())
    {
        return ActionStatus::Running;
    }
    std::string error;
    if (!this->check(error))
    {
        actor->sendMsg(error + "\n\n");
        return ActionStatus::Finished;
    }
    // Iterate trough all the ranged weapons.
    auto activeWeapons = actor->getActiveRangedWeapons();
    bool dualWielding = (activeWeapons.size() > 1);
    bool canAttackTarget = false;
    for (auto iterator : activeWeapons)
    {
        Character * enemy = actor->aimedCharacter;
        // Check if the target is at range of the weapon.
        if (!actor->isAtRange(enemy, iterator->getRange()))
        {
            // If the aimed character is not at range, switch to a closer target.
            enemy = actor->getNextOpponentAtRange(iterator->getRange());
            if (enemy == nullptr)
            {
                actor->sendMsg("%s is not at range for %s.\n", actor->getNameCapital(), iterator->getName(true));
                continue;
            }
        }
        canAttackTarget = true;
        this->performAttack(enemy, iterator, dualWielding);
    }
    if ((actor->aimedCharacter == nullptr) && actor->aggressionList.empty())
    {
        actor->sendMsg(this->stop() + "\n\n");
        return ActionStatus::Finished;
    }
    if (!canAttackTarget)
    {
        actor->sendMsg(this->stop() + "\n\n");
        return ActionStatus::Finished;
    }
    // By default set the next combat action to basic attack.
    if (!actor->setNextCombatAction(CombatActionType::BasicRangedAttack))
    {
        actor->sendMsg(this->stop() + "\n\n");
        return ActionStatus::Finished;
    }
    return ActionStatus::Running;
}

CombatActionType BasicRangedAttack::getCombatActionType() const
{
    return CombatActionType::BasicRangedAttack;
}

unsigned int BasicRangedAttack::getConsumedStamina(Character * character, RangedWeaponItem * weapon)
{
    // BASE     [+1.0]
    // STRENGTH [-0.0 to -2.80]
    // WEIGHT   [+1.6 to +2.51]
    // CARRIED  [+0.0 to +2.48]
    // WEAPON   [+0.0 to +1.60]
    if (weapon->model->toRangedWeapon()->rangedWeaponType == RangedWeaponType::Thrown)
    {
        return static_cast<unsigned int>(1.0
                                         - character->getAbilityLog(Ability::Strength, 0.0, 1.0)
                                         + SafeLog10(character->weight)
                                         + SafeLog10(character->getCarryingWeight())
                                         + SafeLog10(weapon->getWeight(true)));
    }
    return 0;
}

void BasicRangedAttack::performAttack(Character * target,
                                      RangedWeaponItem * weapon,
                                      const bool dualWielding)
{
    // Get the required stamina.
    auto consumedStamina = this->getConsumedStamina(actor, weapon);
    // Check if the actor has enough stamina to execute the action.
    if (consumedStamina > actor->getStamina())
    {
        actor->sendMsg("You are too tired to attack with %s.\n", weapon->getName(true));
        return;
    }
    // Natural roll for the attack.
    auto attack = TRandInteger<unsigned int>(1, 20);
    // Check if:
    //  1. The number of active weapons is more than 1, then we have to apply a penality to the attack roll.
    //  2. The value is NOT a natural 20 (hit).
    if (dualWielding && (attack != 20))
    {
        // Evaluate the penalty to the attack roll.
        unsigned int penalty = 0;
        // On the RIGHT hand the penality is 6.
        // On the LEFT  hand the penality is 10.
        if (weapon->currentSlot == EquipmentSlot::RightHand) penalty = 6;
        if (weapon->currentSlot == EquipmentSlot::LeftHand) penalty = 10;
        // Safely apply the penality.
        attack = (attack < penalty) ? 0 : (attack - penalty);
    }
    // Natural roll for the damage.
    //unsigned int damage = weapon->rollDamage();
    // Evaluate the armor class of the aimed character.
    auto armorClass = actor->aimedCharacter->getArmorClass();
    // Check if:
    //  1. The attack roll is lesser than the armor class of the opponent.
    //  2. The attack roll is not a natural 20.
    if ((attack < armorClass) && (attack != 20))
    {
        this->handleMiss(target, weapon);
        // Consume half the stamina.
        actor->remStamina(consumedStamina / 2, true);
    }
    else
    {
        this->handleHit(target, weapon);
        // Consume the stamina.
        actor->remStamina(consumedStamina, true);
        // Natural roll for the damage.
        auto damage = weapon->rollDamage();
        // If the character has rolled a natural 20, then multiply the damage by two.
        if (attack == 20)
        {
            damage *= 2;
        }
        if (!target->remHealth(damage))
        {
            // Notify the others.
            target->room->sendToAll("%s%s screams in pain and then die!%s\n", {target},
                                    Formatter::red(), target->getNameCapital(), Formatter::reset());
            // The target has received the damage and now it is dead.
            target->kill();
        }
    }
}

void BasicRangedAttack::handleHit(Character * target, RangedWeaponItem * weapon)
{
    // The enemy has received the damage but it is still alive.
    actor->sendMsg("You hit %s with %s.\n\n", target->getName(), weapon->getName(true));
    // Notify the enemy.
    if (target->aimedCharacter == actor)
    {
        target->sendMsg("%s fires a projectile which hits you.\n\n", actor->getNameCapital());
    }
    else
    {
        target->sendMsg("Someone fires a projectile that hits you.\n\n");
    }
    // Notify the others.
    actor->room->funcSendToAll("%s fires and hits %s with %s.\n",
                               [&](Character * character)
                               {
                                   if (character == nullptr) return false;
                                   if (character == actor) return false;
                                   if (character->aimedCharacter == nullptr) return false;
                                   return character->aimedCharacter == target;
                               },
                               actor->getNameCapital(),
                               target->getName(),
                               weapon->getName(true));
    actor->room->funcSendToAll("%s fires at someone or something with %s.\n",
                               [&](Character * character)
                               {
                                   if (character == nullptr) return false;
                                   if (character == actor) return false;
                                   if (character->aimedCharacter == nullptr) return true;
                                   return character->aimedCharacter != target;
                               },
                               actor->getNameCapital(),
                               weapon->getName(true));
    target->room->funcSendToAll("%s fires a projectile which hits %s.\n",
                                [&](Character * character)
                                {
                                    if (character == nullptr) return false;
                                    if (character == target) return false;
                                    if (character->aimedCharacter == nullptr) return false;
                                    return character->aimedCharacter == actor;
                                },
                                actor->getNameCapital(),
                                target->getName(),
                                weapon->getName(true));
    target->room->funcSendToAll("Someone fires a projectile which hits %s.\n",
                                [&](Character * character)
                                {
                                    if (character == nullptr) return false;
                                    if (character == target) return false;
                                    if (character->aimedCharacter == nullptr) return true;
                                    return character->aimedCharacter != actor;
                                },
                                target->getName());
}

void BasicRangedAttack::handleMiss(Character * target, RangedWeaponItem * weapon)
{
    // Notify the actor.
    actor->sendMsg("You fire and miss %s with %s.\n\n", target->getName(), weapon->getName(true));
    // Notify the enemy.
    if (target->aimedCharacter == actor)
    {
        target->sendMsg("%s fires an misses you.\n\n", actor->getName());
    }
    else
    {
        target->sendMsg("Someone fired at you, but missed.\n\n");
    }
    // Notify the others.
    actor->room->funcSendToAll("%s fires and misses %s with %s.\n",
                               [&](Character * character)
                               {
                                   if (character == nullptr) return false;
                                   if (character == actor) return false;
                                   if (character->aimedCharacter == nullptr) return false;
                                   return character->aimedCharacter == target;
                               },
                               actor->getNameCapital(),
                               target->getName(),
                               weapon->getName(true));
    actor->room->funcSendToAll("%s fires at someone or something with %s.\n",
                               [&](Character * character)
                               {
                                   if (character == nullptr) return false;
                                   if (character == actor) return false;
                                   if (character->aimedCharacter == nullptr) return true;
                                   return character->aimedCharacter != target;
                               },
                               actor->getNameCapital(),
                               weapon->getName(true));
    target->room->funcSendToAll("%s fires a projectile which whizzes nearby %s.\n",
                                [&](Character * character)
                                {
                                    if (character == nullptr) return false;
                                    if (character == target) return false;
                                    if (character->aimedCharacter == nullptr) return false;
                                    return character->aimedCharacter == actor;
                                },
                                actor->getNameCapital(),
                                target->getName(),
                                weapon->getName(true));
    target->room->funcSendToAll("Something whizzes nearby %s.\n",
                                [&](Character * character)
                                {
                                    if (character == nullptr) return false;
                                    if (character == target) return false;
                                    if (character->aimedCharacter == nullptr) return true;
                                    return character->aimedCharacter != actor;
                                },
                                target->getName());
}
<commit_msg>Add missing cases in ranged combat messages<commit_after>/// @file   basicRangedAttack.cpp
/// @brief  Contais the implementation of the class for the basic ranged attacks.
/// @author Enrico Fraccaroli
/// @date   Jul 14 2016
/// @copyright
/// Copyright (c) 2016 Enrico Fraccaroli <enrico.fraccaroli@gmail.com>
/// Permission to use, copy, modify, and distribute this software for any
/// purpose with or without fee is hereby granted, provided that the above
/// copyright notice and this permission notice appear in all copies.
///
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
/// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
/// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
/// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
/// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
/// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
/// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include "basicRangedAttack.hpp"
#include "rangedWeaponModel.hpp"
#include "rangedWeaponItem.hpp"
#include "formatter.hpp"
#include "room.hpp"

BasicRangedAttack::BasicRangedAttack(Character * _actor) :
    CombatAction(_actor)
{
    Logger::log(LogLevel::Debug, "Created BasicRangedAttack.");
}

BasicRangedAttack::~BasicRangedAttack()
{
    Logger::log(LogLevel::Debug, "Deleted BasicRangedAttack.");
}

bool BasicRangedAttack::check(std::string & error) const
{
    if (!CombatAction::check(error))
    {
        return false;
    }
    return true;
}

ActionType BasicRangedAttack::getType() const
{
    return ActionType::Combat;
}

std::string BasicRangedAttack::getDescription() const
{
    return "fighting";
}

std::string BasicRangedAttack::stop()
{
    return "You stop fighting.";
}

ActionStatus BasicRangedAttack::perform()
{
    // Check if the cooldown is ended.
    if (!this->checkElapsed())
    {
        return ActionStatus::Running;
    }
    std::string error;
    if (!this->check(error))
    {
        actor->sendMsg(error + "\n\n");
        return ActionStatus::Finished;
    }
    // Iterate trough all the ranged weapons.
    auto activeWeapons = actor->getActiveRangedWeapons();
    bool dualWielding = (activeWeapons.size() > 1);
    bool canAttackTarget = false;
    for (auto iterator : activeWeapons)
    {
        Character * enemy = actor->aimedCharacter;
        // Check if the target is at range of the weapon.
        if (!actor->isAtRange(enemy, iterator->getRange()))
        {
            // If the aimed character is not at range, switch to a closer target.
            enemy = actor->getNextOpponentAtRange(iterator->getRange());
            if (enemy == nullptr)
            {
                actor->sendMsg("%s is not at range for %s.\n", actor->getNameCapital(), iterator->getName(true));
                continue;
            }
        }
        canAttackTarget = true;
        this->performAttack(enemy, iterator, dualWielding);
    }
    if ((actor->aimedCharacter == nullptr) && actor->aggressionList.empty())
    {
        actor->sendMsg(this->stop() + "\n\n");
        return ActionStatus::Finished;
    }
    if (!canAttackTarget)
    {
        actor->sendMsg(this->stop() + "\n\n");
        return ActionStatus::Finished;
    }
    // By default set the next combat action to basic attack.
    if (!actor->setNextCombatAction(CombatActionType::BasicRangedAttack))
    {
        actor->sendMsg(this->stop() + "\n\n");
        return ActionStatus::Finished;
    }
    return ActionStatus::Running;
}

CombatActionType BasicRangedAttack::getCombatActionType() const
{
    return CombatActionType::BasicRangedAttack;
}

unsigned int BasicRangedAttack::getConsumedStamina(Character * character, RangedWeaponItem * weapon)
{
    // BASE     [+1.0]
    // STRENGTH [-0.0 to -2.80]
    // WEIGHT   [+1.6 to +2.51]
    // CARRIED  [+0.0 to +2.48]
    // WEAPON   [+0.0 to +1.60]
    if (weapon->model->toRangedWeapon()->rangedWeaponType == RangedWeaponType::Thrown)
    {
        return static_cast<unsigned int>(1.0
                                         - character->getAbilityLog(Ability::Strength, 0.0, 1.0)
                                         + SafeLog10(character->weight)
                                         + SafeLog10(character->getCarryingWeight())
                                         + SafeLog10(weapon->getWeight(true)));
    }
    return 0;
}

void BasicRangedAttack::performAttack(Character * target,
                                      RangedWeaponItem * weapon,
                                      const bool dualWielding)
{
    // Get the required stamina.
    auto consumedStamina = this->getConsumedStamina(actor, weapon);
    // Check if the actor has enough stamina to execute the action.
    if (consumedStamina > actor->getStamina())
    {
        actor->sendMsg("You are too tired to attack with %s.\n", weapon->getName(true));
        return;
    }
    // Natural roll for the attack.
    auto attack = TRandInteger<unsigned int>(1, 20);
    // Check if:
    //  1. The number of active weapons is more than 1, then we have to apply a penality to the attack roll.
    //  2. The value is NOT a natural 20 (hit).
    if (dualWielding && (attack != 20))
    {
        // Evaluate the penalty to the attack roll.
        unsigned int penalty = 0;
        // On the RIGHT hand the penality is 6.
        // On the LEFT  hand the penality is 10.
        if (weapon->currentSlot == EquipmentSlot::RightHand) penalty = 6;
        if (weapon->currentSlot == EquipmentSlot::LeftHand) penalty = 10;
        // Safely apply the penality.
        attack = (attack < penalty) ? 0 : (attack - penalty);
    }
    // Natural roll for the damage.
    //unsigned int damage = weapon->rollDamage();
    // Evaluate the armor class of the aimed character.
    auto armorClass = actor->aimedCharacter->getArmorClass();
    // Check if:
    //  1. The attack roll is lesser than the armor class of the opponent.
    //  2. The attack roll is not a natural 20.
    if ((attack < armorClass) && (attack != 20))
    {
        this->handleMiss(target, weapon);
        // Consume half the stamina.
        actor->remStamina(consumedStamina / 2, true);
    }
    else
    {
        this->handleHit(target, weapon);
        // Consume the stamina.
        actor->remStamina(consumedStamina, true);
        // Natural roll for the damage.
        auto damage = weapon->rollDamage();
        // If the character has rolled a natural 20, then multiply the damage by two.
        if (attack == 20)
        {
            damage *= 2;
        }
        if (!target->remHealth(damage))
        {
            // Notify the others.
            target->room->sendToAll("%s%s screams in pain and then die!%s\n", {target},
                                    Formatter::red(), target->getNameCapital(), Formatter::reset());
            // The target has received the damage and now it is dead.
            target->kill();
        }
    }
}

void BasicRangedAttack::handleHit(Character * target, RangedWeaponItem * weapon)
{
    // The enemy has received the damage but it is still alive.
    actor->sendMsg("You hit %s with %s.\n\n", target->getName(), weapon->getName(true));
    // Notify the enemy.
    if (target->aimedCharacter == actor)
    {
        target->sendMsg("%s fires a projectile which hits you.\n\n", actor->getNameCapital());
    }
    else
    {
        target->sendMsg("Someone fires a projectile that hits you.\n\n");
    }
    // Notify the other characters.
    if (actor->room == target->room)
    {
        actor->room->funcSendToAll("%s fires and hits %s with %s.\n",
                                   [&](Character * character)
                                   {
                                       return !((character == actor) || (character == target));
                                   },
                                   actor->getNameCapital(),
                                   target->getName(),
                                   weapon->getName(true));
    }
    else
    {
        actor->room->funcSendToAll("%s fires and hits %s with %s.\n",
                                   [&](Character * character)
                                   {
                                       if ((character == actor) || (character == target)) return false;
                                       if (character->charactersInSight.containsCharacter(target)) return true;
                                       return character->aimedCharacter == target;
                                   },
                                   actor->getNameCapital(),
                                   target->getName(),
                                   weapon->getName(true));
        actor->room->funcSendToAll("%s fires at someone or something with %s.\n",
                                   [&](Character * character)
                                   {
                                       if ((character == actor) || (character == target)) return false;
                                       if (character->charactersInSight.containsCharacter(target)) return false;
                                       return character->aimedCharacter != target;
                                   },
                                   actor->getNameCapital(),
                                   weapon->getName(true));
        target->room->funcSendToAll("%s fires a projectile which hits %s.\n",
                                    [&](Character * character)
                                    {
                                        if ((character == actor) || (character == target)) return false;
                                        if (character->charactersInSight.containsCharacter(actor)) return true;
                                        return character->aimedCharacter == actor;
                                    },
                                    actor->getNameCapital(),
                                    target->getName(),
                                    weapon->getName(true));
        target->room->funcSendToAll("Someone fires a projectile which hits %s.\n",
                                    [&](Character * character)
                                    {
                                        if ((character == actor) || (character == target)) return false;
                                        if (character->charactersInSight.containsCharacter(actor)) return false;
                                        return character->aimedCharacter != actor;
                                    },
                                    target->getName());
    }
}

void BasicRangedAttack::handleMiss(Character * target, RangedWeaponItem * weapon)
{
    // Notify the actor.
    actor->sendMsg("You fire and miss %s with %s.\n\n", target->getName(), weapon->getName(true));
    // Notify the enemy.
    if (target->aimedCharacter == actor)
    {
        target->sendMsg("%s fires an misses you.\n\n", actor->getName());
    }
    else
    {
        target->sendMsg("Someone fired at you, but missed.\n\n");
    }
    // Notify the other characters.
    if (actor->room == target->room)
    {
        actor->room->funcSendToAll("%s fires and misses %s with %s.\n",
                                   [&](Character * character)
                                   {
                                       return !((character == actor) || (character == target));
                                   },
                                   actor->getNameCapital(),
                                   target->getName(),
                                   weapon->getName(true));
    }
    else
    {
        actor->room->funcSendToAll("%s fires and misses %s with %s.\n",
                                   [&](Character * character)
                                   {
                                       if ((character == actor) || (character == target)) return false;
                                       if (character->charactersInSight.containsCharacter(target)) return true;
                                       return character->aimedCharacter == target;
                                   },
                                   actor->getNameCapital(),
                                   target->getName(),
                                   weapon->getName(true));
        actor->room->funcSendToAll("%s fires at someone or something with %s.\n",
                                   [&](Character * character)
                                   {
                                       if ((character == actor) || (character == target)) return false;
                                       if (character->charactersInSight.containsCharacter(target)) return false;
                                       return character->aimedCharacter != target;
                                   },
                                   actor->getNameCapital(),
                                   weapon->getName(true));
        target->room->funcSendToAll("%s fires a projectile which whizzes nearby %s.\n",
                                    [&](Character * character)
                                    {
                                        if ((character == actor) || (character == target)) return false;
                                        if (character->charactersInSight.containsCharacter(actor)) return true;
                                        return character->aimedCharacter == actor;
                                    },
                                    actor->getNameCapital(),
                                    target->getName(),
                                    weapon->getName(true));
        target->room->funcSendToAll("Something whizzes nearby %s.\n",
                                    [&](Character * character)
                                    {
                                        if ((character == actor) || (character == target)) return false;
                                        if (character->charactersInSight.containsCharacter(actor)) return false;
                                        return character->aimedCharacter != actor;
                                    },
                                    target->getName());
    }
}
<|endoftext|>


<commit_before>#include "server_functions.h"
#include <string.h>

#include <iostream>
#include <sstream>

#include <netinet/in.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <vector>
#include <algorithm>
#include <list>
#include <map>

#include <netdb.h>
#include <stdlib.h>

#include "segment.h"
#include "message.h"
#include "register_success_message.h"
#include "register_failure_message.h"
#include "register_request_message.h"
#include "loc_success_message.h"
#include "loc_failure_message.h"
#include "loc_request_message.h"

#include "rpc.h"
#include "constants.h"
#include "helper_function.h"
#include "message_types.h"

using namespace std;

//TODO:
//MANAGE CLIENT CONNECTION
//MANAGE SERVER CONNECTION
//DATABASE
//ROUND ROBIN

static map<procedure_signature, list<server_info *> * > proc_loc_dict;
static list<server_function_info *> roundRobinList;

/*
TODO:
ADD FUNCTION TO MAP
ADD FUNCTION TO ROUND ROBIN
IF FUNCTION EXISTS IN ROUND ROBIN DELETE OLD REPLACE WITH NEW (where)
*/
void registration_request_handler(RegisterRequestMessage * message, int sock){
	const char * name = message->getName().c_str();
  int * argTypes = message->getArgTypes();
  string server_identifier = message->getServerIdentifier();
  int port = message->getPort();

  procedure_signature * key = new procedure_signature(name, argTypes);

  //server_info * new_msg_loc = new server_info(server_identifier, port, sock);

  int status = 0;

  //if no key dosnt exist in map
	if (proc_loc_dict.find(key) == proc_loc_dict.end()) {
    //Adding to the map

    //int *memArgTypes = copyArgTypes(argTypes);
    //key = procedure_signature(name, memArgTypes);

    proc_loc_dict[key] = new list<server_info *>();
    server_info * entry = new server_info(server_identifier, port, sock);

    //Adding to roundRobinList
    server_function_info * info = new server_function_info(entry, key);
    roundRobinList.push_back(info);

  }else{

    bool sameLoc = false;
    list<server_info *> *hostList = proc_loc_dict.find[key];

    for (list<server_info *>::iterator it = hostList->begin(); it != hostList->end(); it++) {
      // IF THEY ARE AT THE SAME PLACE, THEY SHOULD HAVE TEH SAME SOCKET
      if((*it)->socket == sock){
        //The same procedure signature already exists on the same location
        //TODO: Move to end of round robin or something
        sameLoc = true;
      }

    }
    //Same procedure signature, different location
  	if(!sameLoc){
       hostList.push_back(new_msg_loc);
    }
  }

  RegisterSuccessMessage * success_message = new RegisterSuccessMessage(status);
  success_message->send(sock);
}

/*
TODO:
USE ROUND ROBIN TO ACCESS THE CORRECT SERVER/FUNCTION FOR THE CLIENT
*/
int location_request_handler(LocRequestMessage * message, int sock){

  bool exist = false;
	for (list<server_function_info *>::iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){

    //If the name are the same
    if((*it)->ps->name == message->getName() && compareArr((*it)->ps->argTypes, message->getArgTypes() )){

      exist = true;

      LocSuccessMessage * success_message = new LocSuccessMessage((*it)->si->server_identifier, (*it)->si->port);

      success_message->send(sock);

      //When we have identified the correct procedure_signature use round robin and move that service to the end
      roundRobinList.splice(roundRobinList.end(), roundRobinList, it);

      break;
 		}
	}

  if(!exist){
    int reasoncode = 0;
    LocFailureMessage * failure_message = new LocFailureMessage(reasoncode);
    failure_message->send(sock);
  }

	return 0; //LOC_FAILURE
}

int request_handler(Segment * segment, int sock){
  int retval = 0;
  if(segment->getType() == MSG_TYPE_REGISTER_REQUEST){ //'LOC_REQUEST'
    Message * cast1 = segment->getMessage();
    RegistrationRequestMessage * rrm = dynamic_cast<LocRequestMessage*>(cast1);
    registration_request_handler(rrm, sock);

  }else if (segment->getType() == MSG_TYPE_LOC_REQUEST){ //'REGISTER'
    Message * cast2 = segment->getMessage();
    LocRequestMessage * lqm = dynamic_cast<LocRequestMessage*>(cast2);
    retval = location_request_handler(lqm, sock);
  }

	return retval;
}

// Returns the binder address
string getBinderAddress() {
   char hostname[MAXHOSTNAMELEN + 1] = {'\0'};
   gethostname(hostname, sizeof(hostname));
   return string(hostname);
}

// Returns the binder port
int getBinderPort(int welcomeSocket) {
   struct sockaddr_in binderAddress;
   socklen_t binderAddressLength = sizeof(binderAddress);

   int result = getsockname(welcomeSocket, (struct sockaddr*) &binderAddress,
      &binderAddressLength);
   if (result < 0) {
      exit(-1);
   } // if

   return ntohs(binderAddress.sin_port);
}

//TODO:
//Create helper functions that can be used for rpcServer.cc
int main(){

  vector<int> myConnections;
  vector<int> myToRemove;

  int status;
  struct addrinfo hints;
  struct addrinfo* servinfo;
  struct addrinfo* p;

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  status = getaddrinfo(NULL, "0", &hints, &servinfo);

  if (status != 0) {
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
    return 0;
  }

  p = servinfo;
  int sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);

  status = bind(sock, servinfo->ai_addr, servinfo->ai_addrlen);
  status = listen(sock, 5);

  cout << "BINDER_ADDRESS " << getBinderAddress() << endl;
  cout << "BINDER_PORT " << getBinderPort(sock) << endl;

  fd_set readfds;
  int n;
  struct sockaddr_storage their_addr;

  while(true){
    //CONNECTIONS VECTOR
    FD_ZERO(&readfds);
    FD_SET(sock, &readfds);

    n = sock;

    for (vector<int>::iterator it = myConnections.begin();it != myConnections.end(); ++it) {
      int connection = *it;
      FD_SET(connection, &readfds);
       if (connection > n){
        n = connection;
      }
    }

    n = n+1;

    status = select(n, &readfds, NULL, NULL, NULL);

    if (status == -1) {
      cerr << "ERROR: select failed." << endl;
    } else {

      if (FD_ISSET(sock, &readfds)) {
        socklen_t addr_size = sizeof their_addr;
        int new_sock = accept(sock, (struct sockaddr*)&their_addr, &addr_size);

        if (new_sock < 0) {
          cerr << "ERROR: while accepting connection" << endl;
          close(new_sock);
          continue;
        }

        myConnections.push_back(new_sock);

      } else {

        for (vector<int>::iterator it = myConnections.begin(); it != myConnections.end(); ++it) {
          int tempConnection = *it;
          if (FD_ISSET(tempConnection, &readfds)) {

            Segment * segment = 0;
            status = Segment::receive(sock, segment);

            if (status < 0) {
                RegisterFailureMessage * failure_message = new RegisterFailureMessage(status);
                failure_message->send(sock);
                return errorMsg;
            }

            if (status == 0) {
              // client has closed the connection
              myToRemove.push_back(sock);
              return errorMsg;
            }

            request_handler(segment, sock);
          }
        }
      }

      for (vector<int>::iterator it = myToRemove.begin(); it != myToRemove.end(); ++it) {
        myConnections.erase(remove(myConnections.begin(), myConnections.end(), *it), myConnections.end());
        close(*it);
      }
      myToRemove.clear();
    }
  }

  freeaddrinfo(servinfo);
}
<commit_msg>changes<commit_after>#include "server_functions.h"
#include <string.h>

#include <iostream>
#include <sstream>

#include <netinet/in.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <vector>
#include <algorithm>
#include <list>
#include <map>

#include <netdb.h>
#include <stdlib.h>

#include "segment.h"
#include "message.h"
#include "register_success_message.h"
#include "register_failure_message.h"
#include "register_request_message.h"
#include "loc_success_message.h"
#include "loc_failure_message.h"
#include "loc_request_message.h"

#include "rpc.h"
#include "constants.h"
#include "helper_function.h"
#include "message_types.h"

using namespace std;

//TODO:
//MANAGE CLIENT CONNECTION
//MANAGE SERVER CONNECTION
//DATABASE
//ROUND ROBIN

static map<procedure_signature, list<server_info *> * > proc_loc_dict;
static list<server_function_info *> roundRobinList;

/*
TODO:
ADD FUNCTION TO MAP
ADD FUNCTION TO ROUND ROBIN
IF FUNCTION EXISTS IN ROUND ROBIN DELETE OLD REPLACE WITH NEW (where)
*/
void registration_request_handler(RegisterRequestMessage * message, int sock){
	const char * name = message->getName().c_str();
  int * argTypes = message->getArgTypes();
  string server_identifier = message->getServerIdentifier();
  int port = message->getPort();

  procedure_signature * key = new procedure_signature(name, argTypes);

  int status = 0;

  //if no key dosnt exist in map
	if (proc_loc_dict.find(key) == proc_loc_dict.end()) {
    //Adding to the map

    //int *memArgTypes = copyArgTypes(argTypes);
    //key = procedure_signature(name, memArgTypes);

    proc_loc_dict[key] = new list<server_info *>();
    server_info * entry = new server_info(server_identifier, port, sock);

    //Adding to roundRobinList
    server_function_info * info = new server_function_info(entry, key);
    roundRobinList.push_back(info);

  }else{

    bool sameLoc = false;
    list<server_info *> *hostList = proc_loc_dict.find[key];

    for (list<server_info *>::iterator it = hostList->begin(); it != hostList->end(); it++) {
      // IF THEY ARE AT THE SAME PLACE, THEY SHOULD HAVE TEH SAME SOCKET
      if((*it)->socket == sock){
        //The same procedure signature already exists on the same location
        //TODO: Move to end of round robin or something
        sameLoc = true;
      }

    }
    //Same procedure signature, different location
  	if(!sameLoc){
       server_info * new_msg_loc = new server_info(server_identifier, port, sock);
       hostList.push_back(new_msg_loc);
    }
  }

  RegisterSuccessMessage * success_message = new RegisterSuccessMessage(status);
  success_message->send(sock);
}

/*
TODO:
USE ROUND ROBIN TO ACCESS THE CORRECT SERVER/FUNCTION FOR THE CLIENT
*/
int location_request_handler(LocRequestMessage * message, int sock){

  bool exist = false;
	for (list<server_function_info *>::iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){

    //If the name are the same
    if((*it)->ps->name == message->getName() && compareArr((*it)->ps->argTypes, message->getArgTypes() )){

      exist = true;

      LocSuccessMessage * success_message = new LocSuccessMessage((*it)->si->server_identifier, (*it)->si->port);

      success_message->send(sock);

      //When we have identified the correct procedure_signature use round robin and move that service to the end
      roundRobinList.splice(roundRobinList.end(), roundRobinList, it);

      break;
 		}
	}

  if(!exist){
    int reasoncode = 0;
    LocFailureMessage * failure_message = new LocFailureMessage(reasoncode);
    failure_message->send(sock);
  }

	return 0; //LOC_FAILURE
}

int request_handler(Segment * segment, int sock){
  int retval = 0;
  if(segment->getType() == MSG_TYPE_REGISTER_REQUEST){ //'LOC_REQUEST'
    Message * cast1 = segment->getMessage();
    RegisterRequestMessage * rrm = dynamic_cast<RegisterRequestMessage*>(cast1);
    registration_request_handler(rrm, sock);

  }else if (segment->getType() == MSG_TYPE_LOC_REQUEST){ //'REGISTER'
    Message * cast2 = segment->getMessage();
    LocRequestMessage * lqm = dynamic_cast<LocRequestMessage*>(cast2);
    retval = location_request_handler(lqm, sock);
  }

	return retval;
}

// Returns the binder address
string getBinderAddress() {
   char hostname[MAXHOSTNAMELEN + 1] = {'\0'};
   gethostname(hostname, sizeof(hostname));
   return string(hostname);
}

// Returns the binder port
int getBinderPort(int welcomeSocket) {
   struct sockaddr_in binderAddress;
   socklen_t binderAddressLength = sizeof(binderAddress);

   int result = getsockname(welcomeSocket, (struct sockaddr*) &binderAddress,
      &binderAddressLength);
   if (result < 0) {
      exit(-1);
   } // if

   return ntohs(binderAddress.sin_port);
}

//TODO:
//Create helper functions that can be used for rpcServer.cc
int main(){

  vector<int> myConnections;
  vector<int> myToRemove;

  int status;
  struct addrinfo hints;
  struct addrinfo* servinfo;
  struct addrinfo* p;

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  status = getaddrinfo(NULL, "0", &hints, &servinfo);

  if (status != 0) {
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
    return 0;
  }

  p = servinfo;
  int sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);

  status = bind(sock, servinfo->ai_addr, servinfo->ai_addrlen);
  status = listen(sock, 5);

  cout << "BINDER_ADDRESS " << getBinderAddress() << endl;
  cout << "BINDER_PORT " << getBinderPort(sock) << endl;

  fd_set readfds;
  int n;
  struct sockaddr_storage their_addr;

  while(true){
    //CONNECTIONS VECTOR
    FD_ZERO(&readfds);
    FD_SET(sock, &readfds);

    n = sock;

    for (vector<int>::iterator it = myConnections.begin();it != myConnections.end(); ++it) {
      int connection = *it;
      FD_SET(connection, &readfds);
       if (connection > n){
        n = connection;
      }
    }

    n = n+1;

    status = select(n, &readfds, NULL, NULL, NULL);

    if (status == -1) {
      cerr << "ERROR: select failed." << endl;
    } else {

      if (FD_ISSET(sock, &readfds)) {
        socklen_t addr_size = sizeof their_addr;
        int new_sock = accept(sock, (struct sockaddr*)&their_addr, &addr_size);

        if (new_sock < 0) {
          cerr << "ERROR: while accepting connection" << endl;
          close(new_sock);
          continue;
        }

        myConnections.push_back(new_sock);

      } else {

        for (vector<int>::iterator it = myConnections.begin(); it != myConnections.end(); ++it) {
          int tempConnection = *it;
          if (FD_ISSET(tempConnection, &readfds)) {

            Segment * segment = 0;
            status = Segment::receive(sock, segment);

            if (status < 0) {
                RegisterFailureMessage * failure_message = new RegisterFailureMessage(status);
                failure_message->send(sock);
                return status;
            }

            if (status == 0) {
              // client has closed the connection
              myToRemove.push_back(sock);
              return status;
            }

            request_handler(segment, sock);
          }
        }
      }

      for (vector<int>::iterator it = myToRemove.begin(); it != myToRemove.end(); ++it) {
        myConnections.erase(remove(myConnections.begin(), myConnections.end(), *it), myConnections.end());
        close(*it);
      }
      myToRemove.clear();
    }
  }

  freeaddrinfo(servinfo);
}
<|endoftext|>


<commit_before>#include <boost/python.hpp>
#include "MIDIout.hh"

namespace bp = boost::python;

BOOST_PYTHON_MODULE(MIDIout)
{
	bp::class_<MIDIout>(
		"MIDIout",
	       	bp::init<std::string, std::string>())
	.def("noteon", &MIDIout::noteon)
	.def("noteoff", &MIDIout::noteoff)
	.def("controller", &MIDIout::controller)
	.def("pgmchange", &MIDIout::pgmchange)
	.def("sysex", &MIDIout::sysex)
    ;
}

<commit_msg>sysex in python doesn't work, the vector needs wrapping<commit_after>#include <boost/python.hpp>
#include "MIDIout.hh"

namespace bp = boost::python;

BOOST_PYTHON_MODULE(MIDIout)
{
	bp::class_<MIDIout>(
		"MIDIout",
	       	bp::init<std::string, std::string>())
	.def("noteon", &MIDIout::noteon)
	.def("noteoff", &MIDIout::noteoff)
	.def("controller", &MIDIout::controller)
	.def("pgmchange", &MIDIout::pgmchange)
//	.def("sysex", &MIDIout::sysex)
    ;
}

<|endoftext|>


<commit_before>/* This software is distributed under the MIT license (see LICENSE file in the
* root directory)
 *
 * Copyright (c) 2013 Fernando J. Iglesias Garcia
 */

#include "filter.h"
#include <algorithm>
#include <cstdlib>
#include <cassert>

namespace parfil {

extern double WORLD_SIZE;

const double STEERING_NOISE = 0.1;
const double DISTANCE_NOISE = 5.0;
const double BEARING_NOISE  = 0.1;

// Constructor from the number of particles.
Filter::Filter(int num_particles) {
  assert(num_particles>0);

  // Particle pose allocation and initialization.

  m_particles.reserve(num_particles);

  for (int i=0; i<num_particles; ++i) {
    Robot particle = Robot();
    particle.SetNoise(STEERING_NOISE,DISTANCE_NOISE,BEARING_NOISE);
    m_particles.push_back(particle);
  }

  // Particle weights allocation.
  m_weights.resize(num_particles);
}

// Destructor.
Filter::~Filter() {
}

// Extract position from particle set.
void Filter::GetPose(double& x, double& y, double& heading) const {
  x = 0;
  y = 0;
  heading = 0.0;

  for (unsigned int i=0; i<m_particles.size(); ++i) {
    x += m_particles[i].x();
    y += m_particles[i].y();
    // Normalize around the first particle.
    heading += fmod(m_particles[i].heading()-m_particles[0].heading()+M_PI, 2.0*M_PI) +
                m_particles[0].heading() - M_PI;
  }

  // Normalize using the number of particles.
  x /= m_particles.size();
  y /= m_particles.size();
  heading /= m_particles.size();
}

// Run particle filter.
void Filter::Run(const std::vector<Motion>& motions, const std::vector<Measurement>& measurements) {
  assert(motions.size()==measurements.size());

  for (unsigned int t = 0; t<motions.size(); ++t) {
    Filter::Predict(motions[t]);
    Filter::MeasurementUpdate(measurements[t]);
    Filter::Resample();
  }
}

void Filter::Predict(const Motion& motion) {
  for (unsigned int i=0; i<m_particles.size(); ++i)
    m_particles[i].Move(motion);
}

void Filter::MeasurementUpdate(const Measurement& measurement) {
  for (unsigned int i=0; i<m_particles.size(); ++i)
    m_weights[i] = m_particles[i].ComputeMeasurementProbability(measurement);
}

// Circular resampling.
void Filter::Resample() {
  int index = int(1.0*std::rand()/RAND_MAX*m_particles.size());
  double beta = 0.0;
  double max_weight = *std::max_element(m_weights.begin(),m_weights.end());
  std::vector<Robot> new_particles;
  new_particles.reserve(m_particles.size());

  for (unsigned int i=0; i<m_weights.size(); ++i) {
    beta += 1.0*std::rand()/RAND_MAX*2*max_weight;

    while (beta > m_weights[index]) {
      beta -= m_weights[index];
      index = (index+1)%m_particles.size();
    }

    new_particles.push_back(m_particles[index]);
  }

  m_particles = new_particles;
}

} // namespace parfil
<commit_msg>Remove unnecesary namespace access in filter.<commit_after>/* This software is distributed under the MIT license (see LICENSE file in the
* root directory)
 *
 * Copyright (c) 2013 Fernando J. Iglesias Garcia
 */

#include "filter.h"
#include <algorithm>
#include <cstdlib>
#include <cassert>

namespace parfil {

extern double WORLD_SIZE;

const double STEERING_NOISE = 0.1;
const double DISTANCE_NOISE = 5.0;
const double BEARING_NOISE  = 0.1;

// Constructor from the number of particles.
Filter::Filter(int num_particles) {
  assert(num_particles>0);

  // Particle pose allocation and initialization.

  m_particles.reserve(num_particles);

  for (int i=0; i<num_particles; ++i) {
    Robot particle = Robot();
    particle.SetNoise(STEERING_NOISE,DISTANCE_NOISE,BEARING_NOISE);
    m_particles.push_back(particle);
  }

  // Particle weights allocation.
  m_weights.resize(num_particles);
}

// Destructor.
Filter::~Filter() {
}

// Extract position from particle set.
void Filter::GetPose(double& x, double& y, double& heading) const {
  x = 0;
  y = 0;
  heading = 0.0;

  for (unsigned int i=0; i<m_particles.size(); ++i) {
    x += m_particles[i].x();
    y += m_particles[i].y();
    // Normalize around the first particle.
    heading += fmod(m_particles[i].heading()-m_particles[0].heading()+M_PI, 2.0*M_PI) +
                m_particles[0].heading() - M_PI;
  }

  // Normalize using the number of particles.
  x /= m_particles.size();
  y /= m_particles.size();
  heading /= m_particles.size();
}

// Run particle filter.
void Filter::Run(const std::vector<Motion>& motions, const std::vector<Measurement>& measurements) {
  assert(motions.size()==measurements.size());

  for (unsigned int t = 0; t<motions.size(); ++t) {
    Predict(motions[t]);
    MeasurementUpdate(measurements[t]);
    Resample();
  }
}

void Filter::Predict(const Motion& motion) {
  for (unsigned int i=0; i<m_particles.size(); ++i)
    m_particles[i].Move(motion);
}

void Filter::MeasurementUpdate(const Measurement& measurement) {
  for (unsigned int i=0; i<m_particles.size(); ++i)
    m_weights[i] = m_particles[i].ComputeMeasurementProbability(measurement);
}

// Circular resampling.
void Filter::Resample() {
  int index = int(1.0*std::rand()/RAND_MAX*m_particles.size());
  double beta = 0.0;
  double max_weight = *std::max_element(m_weights.begin(),m_weights.end());
  std::vector<Robot> new_particles;
  new_particles.reserve(m_particles.size());

  for (unsigned int i=0; i<m_weights.size(); ++i) {
    beta += 1.0*std::rand()/RAND_MAX*2*max_weight;

    while (beta > m_weights[index]) {
      beta -= m_weights[index];
      index = (index+1)%m_particles.size();
    }

    new_particles.push_back(m_particles[index]);
  }

  m_particles = new_particles;
}

} // namespace parfil
<|endoftext|>


<commit_before>//
// Created by Lucas on 10/15/2016.
//

#include "first.h"

FirstSet *first(GramaticalRule *gramaticalrule)
{
    FirstSet *head = (FirstSet*) malloc(sizeof(FirstSet));
    int mudou = 0;

    do
    {
        GramaticalRule *currentrule = gramaticalrule;
        while (currentrule != NULL)
        {
            char key = currentrule->key;
            FirstSet *currentfirstset = seekkey(head,key);
            if (currentfirstset == NUlL)
            {
                currentfirstset = (FirstSet*) malloc(sizeof(FirstSet));
                currentfirstset->key = key;
                currentfirstset->set = (char*) malloc(500);
            }

            for (int i = 0; i < strlen(currentrule->rule); i++)
            {
                char crule = currentrule->rule[i];
                if (islower(crule))
                    addfirst();

            }

            currentrule = currentrule->next;
        }

    } while (mudou);

}

FirstSet *seekkey(FirstSet *firstset, char key)
{
    FirstSet *current = firstset;
    while (current != NULL)
    {
        if (current->key == key)
            return current;

        current = current->next;
    }

    return NULL;
}
<commit_msg>Iniciando implementação algoritmo First<commit_after>//
// Created by Lucas on 10/15/2016.
//

#include "first.h"

FirstSet *first(GramaticalRule *gramaticalrule)
{
    FirstSet *head = (FirstSet*) malloc(sizeof(FirstSet));
    int mudou = 0;

    do
    {
        GramaticalRule *currentrule = gramaticalrule;
        while (currentrule != NULL)
        {
            char key = currentrule->key;
            FirstSet *currentfirstset = seekkey(head,key);
            if (currentfirstset == NUlL)
            {
                currentfirstset = (FirstSet*) malloc(sizeof(FirstSet));
                currentfirstset->key = key;
                currentfirstset->set = (char*) malloc(500);
            }

            for (int i = 0; i < strlen(currentrule->rule); i++)
            {
                char crule = currentrule->rule[i];
                if (islower(crule))
                {
                    strncat(currentfirstset->set, crule, 1);
                } else {

                }

            }

            currentrule = currentrule->next;
        }

    } while (mudou);

}

FirstSet *seekkey(FirstSet *firstset, char key)
{
    FirstSet *current = firstset;
    while (current != NULL)
    {
        if (current->key == key)
            return current;

        current = current->next;
    }

    return NULL;
}
<|endoftext|>


<commit_before>/**
 * Appcelerator Kroll - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2009 Appcelerator, Inc. All Rights Reserved.
 */

#include "utils.h"
#include <cstdlib>

#ifdef OS_WIN32
#include <windows.h>
#elif OS_OSX
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#else
extern char** environ;
#endif

namespace UTILS_NS
{
	bool EnvironmentUtils::Has(std::string name)
	{
#ifdef OS_WIN32
		DWORD len = GetEnvironmentVariableA(name.c_str(), 0, 0);
		return len > 0;
#else
		return getenv(name.c_str()) != 0;
#endif
	}

	std::string EnvironmentUtils::Get(std::string name)
	{
#ifdef OS_WIN32
		int MAX_LENGTH = 1024;
		char* buffer = new char[MAX_LENGTH];
		DWORD len = GetEnvironmentVariableA(name.c_str(), buffer, MAX_LENGTH - 1);
		if(len > 0)
		{
			std::string result(buffer);
			delete [] buffer;
			return result;
		}
		else
		{
			delete [] buffer;
			return std::string();
		}
#else
		const char* val = getenv(name.c_str());
		if (val)
			return std::string(val);
		else
			return std::string();
#endif
	}

	void EnvironmentUtils::Set(std::string name, std::string value)
	{
#ifdef OS_WIN32
		if (SetEnvironmentVariableA(name.c_str(), value.c_str()) == 0)
		{
			throw std::string("Cannot set environment variable: ") + name;
		}
#else
		if (setenv(name.c_str(), value.c_str(), 1))
		{
			throw std::string("Cannot set environment variable: ") + name;
		}
#endif
	}

	void EnvironmentUtils::Unset(std::string name)
	{
#ifdef OS_WIN32
		SetEnvironmentVariableA(name.c_str(), NULL);
#else
		unsetenv(name.c_str());
#endif
	}

	std::map<std::string, std::string> EnvironmentUtils::GetEnvironment()
	{
		std::map<std::string, std::string> environment;
#ifdef OS_WIN32
		LPTCH env = GetEnvironmentStrings();
		while (env[0] != '\0')
		{
			std::string entry = env;
			std::string key = entry.substr(0, entry.find("="));
			std::string val = entry.substr(entry.find("=")+1);
			environment[key] = val;
			env += entry.size() + 1;
		}
#else
		char** current = environ;
		while (current)
		{
			std::string entry = *current;
			std::string key = entry.substr(0, entry.find("="));
			std::string val = entry.substr(entry.find("=")+1);
			environment[key] = val;
			current++;
		}
#endif
		return environment;
	}
}
<commit_msg>fix for build error in win32<commit_after>/**
 * Appcelerator Kroll - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2009 Appcelerator, Inc. All Rights Reserved.
 */

#include "utils.h"
#include <cstdlib>

#ifdef OS_WIN32
#include <windows.h>
#elif OS_OSX
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#else
extern char** environ;
#endif

namespace UTILS_NS
{
	bool EnvironmentUtils::Has(std::string name)
	{
#ifdef OS_WIN32
		DWORD len = GetEnvironmentVariableA(name.c_str(), 0, 0);
		return len > 0;
#else
		return getenv(name.c_str()) != 0;
#endif
	}

	std::string EnvironmentUtils::Get(std::string name)
	{
#ifdef OS_WIN32
		int MAX_LENGTH = 1024;
		char* buffer = new char[MAX_LENGTH];
		DWORD len = GetEnvironmentVariableA(name.c_str(), buffer, MAX_LENGTH - 1);
		if(len > 0)
		{
			std::string result(buffer);
			delete [] buffer;
			return result;
		}
		else
		{
			delete [] buffer;
			return std::string();
		}
#else
		const char* val = getenv(name.c_str());
		if (val)
			return std::string(val);
		else
			return std::string();
#endif
	}

	void EnvironmentUtils::Set(std::string name, std::string value)
	{
#ifdef OS_WIN32
		if (SetEnvironmentVariableA(name.c_str(), value.c_str()) == 0)
		{
			throw std::string("Cannot set environment variable: ") + name;
		}
#else
		if (setenv(name.c_str(), value.c_str(), 1))
		{
			throw std::string("Cannot set environment variable: ") + name;
		}
#endif
	}

	void EnvironmentUtils::Unset(std::string name)
	{
#ifdef OS_WIN32
		SetEnvironmentVariableA(name.c_str(), NULL);
#else
		unsetenv(name.c_str());
#endif
	}

	std::map<std::string, std::string> EnvironmentUtils::GetEnvironment()
	{
		std::map<std::string, std::string> environment;
#ifdef OS_WIN32
		LPTCH env = GetEnvironmentStrings();
		while (env[0] != '\0')
		{
			std::string entry = (char*)env;
			std::string key = entry.substr(0, entry.find("="));
			std::string val = entry.substr(entry.find("=")+1);
			environment[key] = val;
			env += entry.size() + 1;
		}
#else
		char** current = environ;
		while (current)
		{
			std::string entry = *current;
			std::string key = entry.substr(0, entry.find("="));
			std::string val = entry.substr(entry.find("=")+1);
			environment[key] = val;
			current++;
		}
#endif
		return environment;
	}
}
<|endoftext|>


<commit_before>/*******************************
Copyright (C) 2013-2015 gregoire ANGERAND

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 3 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
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, see <http://www.gnu.org/licenses/>.
**********************************/

#include "DeferredCommon.h"
#include "GLContext.h"
#include "VertexArrayFactory.h"

namespace n {
namespace graphics {

const VertexArrayObject<> &getSphere() {
	static VertexArrayObject<> *sphere = 0;
	if(!sphere) {
		sphere = new VertexArrayObject<>(GLContext::getContext()->getVertexArrayFactory()(TriangleBuffer<>::getSphere()));
	}
	return *sphere;
}

const VertexArrayObject<> &getBox() {
	static VertexArrayObject<> *box = 0;
	if(!box) {
		box = new VertexArrayObject<>(GLContext::getContext()->getVertexArrayFactory()(TriangleBuffer<>::getCube()));
	}
	return *box;
}

core::String getBRDFs() {
	return
			"float cook_torrance_D(float NoH, float a2) {"
				"float d = (NoH * a2 - NoH) * NoH + 1.0;"
				"return a2 / (pi * d * d);"
			"}"

			"float cook_torrance_F(float LoH, float F0) {"
				"return saturate(F0 + (1.0 - F0) * pow(1.0 - LoH, 5.0));"
			"}"

			"float cook_torrance_vis(float NoL, float NoV, float a2) {"
				"float G1V = NoV + sqrt((NoV - NoV * a2) * NoV + a2);"
				"float G1L = NoL + sqrt((NoL - NoL * a2) * NoL + a2);"
				"return 1.0 / (G1L * G1V);"
			"}"

			"float brdf_cook_torrance(vec3 L, vec3 V, vec3 N, vec4 M) {"
				"vec3 H = normalize(L + V);"

				"float NoL = saturate(dot(N, L));"
				"float NoV = saturate(dot(N, V));"
				"float LoH = saturate(dot(L, H));"
				"float NoH = saturate(dot(N, H));"

				"float roughness = M.x + epsilon;"
				"float a = sqr(roughness);"
				"float a2 = sqr(a);"

				"float D = cook_torrance_D(NoH, a2);"

				"float F = cook_torrance_F(LoH, M.z);"

				"return F * D * cook_torrance_vis(NoL, NoV, a);"
			"}"

			"float brdf_lambert(vec3 L, vec3 V, vec3 N, vec4 M) {"
				"return 1.0 / pi;"
			"}";

}

}
}
<commit_msg>More brdf tweaks.<commit_after>/*******************************
Copyright (C) 2013-2015 gregoire ANGERAND

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 3 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
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, see <http://www.gnu.org/licenses/>.
**********************************/

#include "DeferredCommon.h"
#include "GLContext.h"
#include "VertexArrayFactory.h"

namespace n {
namespace graphics {

const VertexArrayObject<> &getSphere() {
	static VertexArrayObject<> *sphere = 0;
	if(!sphere) {
		sphere = new VertexArrayObject<>(GLContext::getContext()->getVertexArrayFactory()(TriangleBuffer<>::getSphere()));
	}
	return *sphere;
}

const VertexArrayObject<> &getBox() {
	static VertexArrayObject<> *box = 0;
	if(!box) {
		box = new VertexArrayObject<>(GLContext::getContext()->getVertexArrayFactory()(TriangleBuffer<>::getCube()));
	}
	return *box;
}

core::String getBRDFs() {
	return
			// [Walter et al. 2007, "Microfacet models for refraction through rough surfaces"]
			"float D_GGX(float NoH, float a2) {"
				"float d = (NoH * a2 - NoH) * NoH + 1.0;"
				"return a2 / (pi * d * d);"
			"}"

			// [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"]
			"float F_Schlick(float LoH, float F0) {"
				"return F0 + (1.0 - F0) * pow(1.0 - LoH, 5.0);"
			"}"

			"vec3 F_Schlick(float LoH, vec3 F0) {"
				"return F0 + (1.0 - F0) * pow(1.0 - LoH, 5.0);"
			"}"

			"float V_Schlick(float NoL, float NoV, float a) {"
				"float k = a * 0.5;"
				"float GV = NoV * (1.0 - k) + k;"
				"float GL = NoL * (1.0 - k) + k;"
				"return 0.25 / (GL * GV);"
			"}"

			"float brdf_cook_torrance(vec3 L, vec3 V, vec3 N, vec4 M) {"
				"vec3 H = normalize(L + V);"

				"float NoL = saturate(dot(N, L));"
				"float NoV = saturate(dot(N, V));"
				"float LoH = saturate(dot(L, H));"
				"float NoH = saturate(dot(N, H));"

				"float roughness = saturate(M.x + epsilon);"
				"float a = sqr(roughness);"
				"float a2 = sqr(a);"

				"return F_Schlick(LoH, M.z) * D_GGX(NoH, a) * V_Schlick(NoL, NoV, a);"
			"}"

			"float brdf_lambert(vec3 L, vec3 V, vec3 N, vec4 M) {"
				"return 1.0 / pi;"
			"}";

}

}
}
<|endoftext|>


<commit_before>/*****************************************************************************
   Copyright 2004 Steve Ménard

   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

   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.

 *****************************************************************************/
#include "jpype.h"
#include "jp_platform.h"

JPPlatformAdapter::~JPPlatformAdapter()
{
}

#ifdef WIN32
#include <windows.h>

/**
 * Windows-specific platform adapter
 */
class Win32PlatformAdapter : public JPPlatformAdapter
{
private:
	HINSTANCE jvmLibrary;

	std::string formatMessage(DWORD msgCode)
	{
		LPVOID lpMsgBuf;

		FormatMessage(
				FORMAT_MESSAGE_ALLOCATE_BUFFER |
				FORMAT_MESSAGE_FROM_SYSTEM,
				NULL,
				msgCode,
				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
				(LPTSTR) & lpMsgBuf,
				0, NULL );

		std::string res((LPTSTR) lpMsgBuf);

		LocalFree(lpMsgBuf);

		return res;
	}

public:

	virtual void loadLibrary(const char* path) override
	{
		JP_TRACE_IN("Win32PlatformAdapter::loadLibrary");
		jvmLibrary = LoadLibrary(path);
		if (jvmLibrary == NULL)
		{
			JP_RAISE_OS_ERROR_WINDOWS( GetLastError(), path);
		}
		JP_TRACE_OUT;
	}

	virtual void unloadLibrary() override
	{
		// on success return code is nonzero, TODO: handle error?
		FreeLibrary(jvmLibrary);
	}

	virtual void* getSymbol(const char* name) override
	{
		void* res = (void*) GetProcAddress(jvmLibrary, name);
		if (res == NULL)
		{
			std::stringstream msg;
			msg << "Unable to load symbol [" << name << "], error = " << formatMessage(GetLastError());
			JP_RAISE(PyExc_RuntimeError,  msg.str().c_str());
		}
		return res;
	}
} ;

#define  PLATFORM_ADAPTER Win32PlatformAdapter
#else

#if defined(_HPUX) && !defined(_IA64)
#include <dl.h>
#else
#include <dlfcn.h>
#endif // HPUX
#include <errno.h>

// The code in this modules is mostly excluded from coverage as it is only
// possible to execute during a fatal error.
class LinuxPlatformAdapter : public JPPlatformAdapter
{
private:
	void* jvmLibrary;

public:

	virtual void loadLibrary(const char* path) override
	{
		JP_TRACE_IN("LinuxPlatformAdapter::loadLibrary");
#if defined(_HPUX) && !defined(_IA64)
		JP_TRACE("shl_load", path);
		jvmLibrary = shl_load(path, BIND_DEFERRED | BIND_VERBOSE, 0L);
#else
		JP_TRACE("dlopen", path);
		jvmLibrary = dlopen(path, RTLD_LAZY | RTLD_GLOBAL);
#endif // HPUX
                // GCOVR_EXCL_START
		if (jvmLibrary == NULL)
		{
			JP_TRACE("null library");
                        JP_TRACE("errno", errno);
                        if (errno == ENOEXEC)
                        {
                            JP_TRACE("dignostics", dlerror());
                        }
			JP_RAISE_OS_ERROR_UNIX( errno, path);
		}
                // GCOVR_EXCL_STOP
		JP_TRACE_OUT;
	}

	virtual void unloadLibrary() override
	{
		JP_TRACE_IN("LinuxPlatformAdapter::unloadLibrary");
		int r = dlclose(jvmLibrary);
                // GCOVR_EXCL_START
		if (r != 0) // error
		{
			cerr << dlerror() << endl;
		}
                // GCOVR_EXCL_STOP
		JP_TRACE_OUT;
	}

	virtual void* getSymbol(const char* name) override
	{
		JP_TRACE_IN("LinuxPlatformAdapter::getSymbol");
                JP_TRACE("Load", name):
		void* res = dlsym(jvmLibrary, name);
                JP_TRACE("Res", res);
		// GCOVR_EXCL_START
		if (res == NULL)
		{
                        JP_TRACE("errno", errno);
			std::stringstream msg;
			msg << "Unable to load symbol [" << name << "], error = " << dlerror();
			JP_RAISE(PyExc_RuntimeError,  msg.str().c_str());
		}
		// GCOVR_EXCL_STOP
		return res;
		JP_TRACE_OUT;
	}
} ;

#define  PLATFORM_ADAPTER LinuxPlatformAdapter
#endif

namespace
{
PLATFORM_ADAPTER adapter;
}

JPPlatformAdapter* JPPlatformAdapter::getAdapter()
{
	return &adapter;
}
<commit_msg>More diag<commit_after>/*****************************************************************************
   Copyright 2004 Steve Ménard

   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

   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.

 *****************************************************************************/
#include "jpype.h"
#include "jp_platform.h"

JPPlatformAdapter::~JPPlatformAdapter()
{
}

#ifdef WIN32
#include <windows.h>

/**
 * Windows-specific platform adapter
 */
class Win32PlatformAdapter : public JPPlatformAdapter
{
private:
	HINSTANCE jvmLibrary;

	std::string formatMessage(DWORD msgCode)
	{
		LPVOID lpMsgBuf;

		FormatMessage(
				FORMAT_MESSAGE_ALLOCATE_BUFFER |
				FORMAT_MESSAGE_FROM_SYSTEM,
				NULL,
				msgCode,
				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
				(LPTSTR) & lpMsgBuf,
				0, NULL );

		std::string res((LPTSTR) lpMsgBuf);

		LocalFree(lpMsgBuf);

		return res;
	}

public:

	virtual void loadLibrary(const char* path) override
	{
		JP_TRACE_IN("Win32PlatformAdapter::loadLibrary");
		jvmLibrary = LoadLibrary(path);
		if (jvmLibrary == NULL)
		{
			JP_RAISE_OS_ERROR_WINDOWS( GetLastError(), path);
		}
		JP_TRACE_OUT;
	}

	virtual void unloadLibrary() override
	{
		// on success return code is nonzero, TODO: handle error?
		FreeLibrary(jvmLibrary);
	}

	virtual void* getSymbol(const char* name) override
	{
		void* res = (void*) GetProcAddress(jvmLibrary, name);
		if (res == NULL)
		{
			std::stringstream msg;
			msg << "Unable to load symbol [" << name << "], error = " << formatMessage(GetLastError());
			JP_RAISE(PyExc_RuntimeError,  msg.str().c_str());
		}
		return res;
	}
} ;

#define  PLATFORM_ADAPTER Win32PlatformAdapter
#else

#if defined(_HPUX) && !defined(_IA64)
#include <dl.h>
#else
#include <dlfcn.h>
#endif // HPUX
#include <errno.h>

// The code in this modules is mostly excluded from coverage as it is only
// possible to execute during a fatal error.
class LinuxPlatformAdapter : public JPPlatformAdapter
{
private:
	void* jvmLibrary;

public:

	virtual void loadLibrary(const char* path) override
	{
		JP_TRACE_IN("LinuxPlatformAdapter::loadLibrary");
#if defined(_HPUX) && !defined(_IA64)
		JP_TRACE("shl_load", path);
		jvmLibrary = shl_load(path, BIND_DEFERRED | BIND_VERBOSE, 0L);
#else
		JP_TRACE("dlopen", path);
		jvmLibrary = dlopen(path, RTLD_LAZY | RTLD_GLOBAL);
#endif // HPUX
                // GCOVR_EXCL_START
		if (jvmLibrary == NULL)
		{
			JP_TRACE("null library");
                        JP_TRACE("errno", errno);
                        if (errno == ENOEXEC)
                        {
                            JP_TRACE("dignostics", dlerror());
                        }
			JP_RAISE_OS_ERROR_UNIX( errno, path);
		}
                // GCOVR_EXCL_STOP
		JP_TRACE_OUT;
	}

	virtual void unloadLibrary() override
	{
		JP_TRACE_IN("LinuxPlatformAdapter::unloadLibrary");
		int r = dlclose(jvmLibrary);
                // GCOVR_EXCL_START
		if (r != 0) // error
		{
			cerr << dlerror() << endl;
		}
                // GCOVR_EXCL_STOP
		JP_TRACE_OUT;
	}

	virtual void* getSymbol(const char* name) override
	{
		JP_TRACE_IN("LinuxPlatformAdapter::getSymbol");
                JP_TRACE("Load", name);
		void* res = dlsym(jvmLibrary, name);
                JP_TRACE("Res", res);
		// GCOVR_EXCL_START
		if (res == NULL)
		{
                        JP_TRACE("errno", errno);
			std::stringstream msg;
			msg << "Unable to load symbol [" << name << "], error = " << dlerror();
			JP_RAISE(PyExc_RuntimeError,  msg.str().c_str());
		}
		// GCOVR_EXCL_STOP
		return res;
		JP_TRACE_OUT;
	}
} ;

#define  PLATFORM_ADAPTER LinuxPlatformAdapter
#endif

namespace
{
PLATFORM_ADAPTER adapter;
}

JPPlatformAdapter* JPPlatformAdapter::getAdapter()
{
	return &adapter;
}
<|endoftext|>


<commit_before>#pragma once

#include "gc.hh"
#include "percpu.hh"

// name spaces
// XXX maybe use open hash table, no chain, better cache locality

#if SPINLOCK_DEBUG
#define NHASH 10
#else
#define NHASH 257
#endif

template<class K, class V>
class xelem : public rcu_freed {
 public:
  V val;
  K key;

  std::atomic<int> next_lock;
  std::atomic<xelem<K, V>*> next;

  int percore_c;
  std::atomic<xelem<K, V>*> percore_next;
  std::atomic<xelem<K, V>*>* percore_pprev;

  xelem(const K &k, const V &v)
    : rcu_freed("xelem"), val(v), key(k),
      next_lock(0), next(0),
      percore_next(0), percore_pprev(0) {}
  virtual void do_gc() {
    delete this;
  }

  NEW_DELETE_OPS(xelem)
};

// XXX maybe not cache align, because it takes too much space
template<class K, class V>
struct xbucket {
  std::atomic<xelem<K, V>*> volatile chain;
} ; // __attribute__((aligned (CACHELINE)));

template<class K, class V, u64 (*HF)(const K&)>
class xns : public rcu_freed {
 private:
  bool allowdup;
  std::atomic<u64> nextkey;
  xbucket<K, V> table[NHASH];
  std::atomic<xelem<K, V>*> percore[NCPU];
  spinlock percore_lock[NCPU];

 public:
  xns(bool dup) : rcu_freed("xns") {
    allowdup = dup;
    nextkey = 1;
    for (int i = 0; i < NHASH; i++)
      table[i].chain = 0;
    for (int i = 0; i < NCPU; i++) {
      percore[i] = nullptr;
      percore_lock[i] = spinlock("xns_lock", LOCKSTAT_NS);
    }
  }

  ~xns() {
    for (int i = 0; i < NHASH; i++)
      if (table[i].chain)
        panic("~xns: not empty");
  }

  virtual void do_gc() {
    delete this;
  }

  u64 allockey() {
    return nextkey++;
  }

  u64 h(const K &key) {
    return HF(key) % NHASH;
  }

  int insert(const K &key, const V &val) {
    auto e = new xelem<K, V>(key, val);
    if (!e)
      return -1;

    u64 i = h(key);
    scoped_gc_epoch gc;

    for (;;) {
      auto root = table[i].chain;
      if (!allowdup) {
        for (auto x = root.load(); x; x = x->next) {
          if (x->key == key) {
            gc_delayed(e);
            return -1;
          }
        }
      }

      e->next = root.load();
      if (cmpxch(&table[i].chain, e->next.load(), e)) {
        int c = myid();
        acquire(&percore_lock[c]);
        e->percore_c = c;
        e->percore_next = percore[c].load();
        if (percore[c])
          percore[c].load()->percore_pprev = &e->percore_next;
        e->percore_pprev = &percore[c];
        percore[c] = e;
        release(&percore_lock[c]);
        return 0;
      }
    }
  }

  V lookup(const K &key) {
    u64 i = h(key);

    scoped_gc_epoch gc;
    auto e = table[i].chain.load();

    while (e) {
      if (e->key == key)
        return e->val;
      e = e->next;
    }

    return 0;
  }

  bool remove(const K &key, const V *vp = 0) {
    u64 i = h(key);
    scoped_gc_epoch gc;

    for (;;) {
      std::atomic<int> fakelock(0);
      std::atomic<int> *pelock = &fakelock;
      auto pe = &table[i].chain;

      for (;;) {
        auto e = pe->load();
        if (!e)
          return false;

        if (e->key == key && (!vp || e->val == *vp)) {
          if (!cmpxch(&e->next_lock, 0, 1))
            break;
          if (!cmpxch(pelock, 0, 1)) {
            e->next_lock = 0;
            break;
          }

          if (!cmpxch(pe, e, e->next.load())) {
            *pelock = 0;
            e->next_lock = 0;
            break;
          }

          int c = e->percore_c;
          acquire(&percore_lock[c]);
          *e->percore_pprev = e->percore_next.load();
          if (e->percore_next)
            e->percore_next.load()->percore_pprev = e->percore_pprev;
          release(&percore_lock[c]);

          *pelock = 0;
          gc_delayed(e);
          return true;
        }

        pe = &e->next;
        pelock = &e->next_lock;
      }
    }
  }

  template<class CB>
  void enumerate(CB cb) {
    scoped_gc_epoch gc;
    int cpuoffset = myid();
    for (int i = 0; i < NCPU; i++) {
      auto e = percore[(i + cpuoffset) % NCPU].load();
      while (e) {
        if (cb(e->key, e->val))
          return;
        e = e->percore_next;
      }
    }
  }

  template<class CB>
  void enumerate_key(const K &key, CB cb) {
    scoped_gc_epoch gc;
    u64 i = h(key);
    auto e = table[i].chain;
    while (e) {
      if (e->key == key && cb(e->key, e->val))
        return;
      e = e->next;
    }
  }

  class iterator {
  private:
    xns<K, V, HF> *ns_;
    xelem<K, V> *chain_;
    int ndx_;

  public:
    iterator(xns<K, V, HF> *ns) {
      if (ns_)
        gc_begin_epoch();
      ns_ = ns;
      ndx_ = 0;
      chain_ = ns->table[ndx_++].chain;
      for (; chain_ == 0 && ndx_ < NHASH; ndx_++)
        chain_ = ns_->table[ndx_].chain;
    }

    iterator() {
      ns_ = 0;
      ndx_ = NHASH;
      chain_ = 0;
    }

    ~iterator() {
      if (ns_)
        gc_end_epoch();
    }

    bool operator!=(const iterator &other) const {
      return other.chain_ != this->chain_;
    }

    iterator& operator ++() {
      for (chain_ = chain_->next; chain_ == 0 && ndx_ < NHASH; ndx_++)
        chain_ = ns_->table[ndx_].chain;
      return *this;
    }

    V& operator *() {
      return chain_->val;
    }
  };

  iterator begin() {
    return iterator(this);
  }

  iterator end() {
    return iterator();
  }

  NEW_DELETE_OPS(xns)
};

template<class K, class V, u64 (*HF)(const K&)>
static inline
typename xns<K, V, HF>::iterator
begin(xns<K, V, HF> *&ns)
{
  return ns->begin();
}

template<class K, class V, u64 (*HF)(const K&)>
static inline
typename xns<K, V, HF>::iterator
end(xns<K, V, HF> *&ns)
{
  return ns->end();
}
<commit_msg>ns tweaks for clang compatibility<commit_after>#pragma once

#include "gc.hh"
#include "percpu.hh"

// name spaces
// XXX maybe use open hash table, no chain, better cache locality

#if SPINLOCK_DEBUG
#define NHASH 10
#else
#define NHASH 257
#endif

template<class K, class V>
class xelem : public rcu_freed {
 public:
  V val;
  K key;

  std::atomic<int> next_lock;
  std::atomic<xelem<K, V>*> next;

  int percore_c;
  std::atomic<xelem<K, V>*> percore_next;
  std::atomic<xelem<K, V>*>* percore_pprev;

  xelem(const K &k, const V &v)
    : rcu_freed("xelem"), val(v), key(k),
      next_lock(0), next(0),
      percore_next(0), percore_pprev(0) {}
  virtual void do_gc() {
    delete this;
  }

  NEW_DELETE_OPS(xelem)
};

// XXX maybe not cache align, because it takes too much space
template<class K, class V>
struct xbucket {
  std::atomic<xelem<K, V>*> volatile chain;
} ; // __attribute__((aligned (CACHELINE)));

template<class K, class V, u64 (*HF)(const K&)>
class xns : public rcu_freed {
 private:
  bool allowdup;
  std::atomic<u64> nextkey;
  xbucket<K, V> table[NHASH];
  std::atomic<xelem<K, V>*> percore[NCPU];
  spinlock percore_lock[NCPU];

 public:
  xns(bool dup) : rcu_freed("xns") {
    allowdup = dup;
    nextkey = 1;
    for (int i = 0; i < NHASH; i++)
      table[i].chain = 0;
    for (int i = 0; i < NCPU; i++) {
      percore[i] = nullptr;
      percore_lock[i] = spinlock("xns_lock", LOCKSTAT_NS);
    }
  }

  ~xns() {
    for (int i = 0; i < NHASH; i++)
      if (table[i].chain)
        panic("~xns: not empty");
  }

  virtual void do_gc() {
    delete this;
  }

  u64 allockey() {
    return nextkey++;
  }

  u64 h(const K &key) {
    return HF(key) % NHASH;
  }

  int insert(const K &key, const V &val) {
    auto e = new xelem<K, V>(key, val);
    if (!e)
      return -1;

    u64 i = h(key);
    scoped_gc_epoch gc;

    for (;;) {
      auto root = table[i].chain;
      if (!allowdup) {
        for (auto x = root.load(); x; x = x->next) {
          if (x->key == key) {
            gc_delayed(e);
            return -1;
          }
        }
      }

      e->next = root.load();
      if (cmpxch(&table[i].chain, e->next.load(), e)) {
        int c = myid();
        acquire(&percore_lock[c]);
        e->percore_c = c;
        e->percore_next = percore[c].load();
        if (percore[c])
          percore[c].load()->percore_pprev = &e->percore_next;
        e->percore_pprev = &percore[c];
        percore[c] = e;
        release(&percore_lock[c]);
        return 0;
      }
    }
  }

  V lookup(const K &key) {
    u64 i = h(key);

    scoped_gc_epoch gc;
    auto e = table[i].chain.load();

    while (e) {
      if (e->key == key)
        return e->val;
      e = e->next;
    }

    return 0;
  }

  bool remove(const K &key, const V *vp = 0) {
    u64 i = h(key);
    scoped_gc_epoch gc;

    for (;;) {
      std::atomic<int> fakelock(0);
      std::atomic<int> *pelock = &fakelock;
      auto pe = &table[i].chain;

      for (;;) {
        auto e = pe->load();
        if (!e)
          return false;

        if (e->key == key && (!vp || e->val == *vp)) {
          if (!cmpxch(&e->next_lock, 0, 1))
            break;
          if (!cmpxch(pelock, 0, 1)) {
            e->next_lock = 0;
            break;
          }

          if (!cmpxch(pe, e, e->next.load())) {
            pelock->store(0);
            e->next_lock = 0;
            break;
          }

          int c = e->percore_c;
          acquire(&percore_lock[c]);
          *e->percore_pprev = e->percore_next.load();
          if (e->percore_next)
            e->percore_next.load()->percore_pprev = e->percore_pprev;
          release(&percore_lock[c]);

          pelock->store(0);
          gc_delayed(e);
          return true;
        }

        pe = &e->next;
        pelock = &e->next_lock;
      }
    }
  }

  template<class CB>
  void enumerate(CB cb) {
    scoped_gc_epoch gc;
    int cpuoffset = myid();
    for (int i = 0; i < NCPU; i++) {
      auto e = percore[(i + cpuoffset) % NCPU].load();
      while (e) {
        if (cb(e->key, e->val))
          return;
        e = e->percore_next;
      }
    }
  }

  template<class CB>
  void enumerate_key(const K &key, CB cb) {
    scoped_gc_epoch gc;
    u64 i = h(key);
    auto e = table[i].chain;
    while (e) {
      if (e->key == key && cb(e->key, e->val))
        return;
      e = e->next;
    }
  }

  class iterator {
  private:
    xns<K, V, HF> *ns_;
    xelem<K, V> *chain_;
    int ndx_;

  public:
    iterator(xns<K, V, HF> *ns) {
      if (ns_)
        gc_begin_epoch();
      ns_ = ns;
      ndx_ = 0;
      chain_ = ns->table[ndx_++].chain;
      for (; chain_ == 0 && ndx_ < NHASH; ndx_++)
        chain_ = ns_->table[ndx_].chain;
    }

    iterator() {
      ns_ = 0;
      ndx_ = NHASH;
      chain_ = 0;
    }

    ~iterator() {
      if (ns_)
        gc_end_epoch();
    }

    bool operator!=(const iterator &other) const {
      return other.chain_ != this->chain_;
    }

    iterator& operator ++() {
      for (chain_ = chain_->next; chain_ == 0 && ndx_ < NHASH; ndx_++)
        chain_ = ns_->table[ndx_].chain;
      return *this;
    }

    V& operator *() {
      return chain_->val;
    }
  };

  iterator begin() {
    return iterator(this);
  }

  iterator end() {
    return iterator();
  }

  NEW_DELETE_OPS(xns)
};

template<class K, class V, u64 (*HF)(const K&)>
static inline
typename xns<K, V, HF>::iterator
begin(xns<K, V, HF> *&ns)
{
  return ns->begin();
}

template<class K, class V, u64 (*HF)(const K&)>
static inline
typename xns<K, V, HF>::iterator
end(xns<K, V, HF> *&ns)
{
  return ns->end();
}
<|endoftext|>


<commit_before>#include "inireader.h"
#include <string>

CIniReader::CIniReader(const char* szFileName)
{
   conf = config_file_new(szFileName);
}

CIniReader::~CIniReader()
{
   if (conf)
      config_file_free(conf);
}

int CIniReader::ReadInteger(const char* szSection, const char* szKey, int iDefaultValue)
{
   std::string key(szSection);
   key += "_";
   key += szKey;
   int res;
   if (config_get_int(conf, key.c_str(), &res))
      return res;
   else
      return iDefaultValue;
}

float CIniReader::ReadFloat(const char* szSection, const char* szKey, float fltDefaultValue)
{
   std::string key(szSection);
   key += "_";
   key += szKey;
   double res;
   if (config_get_double(conf, key.c_str(), &res))
      return (float)res;
   else
      return fltDefaultValue;
}

bool CIniReader::ReadBoolean(const char* szSection, const char* szKey, bool bolDefaultValue)
{
   std::string key(szSection);
   key += "_";
   key += szKey;
   bool res;
   if (config_get_bool(conf, key.c_str(), &res))
      return res;
   else
      return bolDefaultValue;
}

<commit_msg>Fix segfault.<commit_after>#include "inireader.h"
#include <string>

CIniReader::CIniReader(const char* szFileName)
{
   conf = config_file_new(szFileName);
   if (!conf)
      conf = config_file_new(NULL);
}

CIniReader::~CIniReader()
{
   if (conf)
      config_file_free(conf);
}

int CIniReader::ReadInteger(const char* szSection, const char* szKey, int iDefaultValue)
{
   std::string key(szSection);
   key += "_";
   key += szKey;
   int res;
   if (config_get_int(conf, key.c_str(), &res))
      return res;
   else
      return iDefaultValue;
}

float CIniReader::ReadFloat(const char* szSection, const char* szKey, float fltDefaultValue)
{
   std::string key(szSection);
   key += "_";
   key += szKey;
   double res;
   if (config_get_double(conf, key.c_str(), &res))
      return (float)res;
   else
      return fltDefaultValue;
}

bool CIniReader::ReadBoolean(const char* szSection, const char* szKey, bool bolDefaultValue)
{
   std::string key(szSection);
   key += "_";
   key += szKey;
   bool res;
   if (config_get_bool(conf, key.c_str(), &res))
      return res;
   else
      return bolDefaultValue;
}

<|endoftext|>


<commit_before>/*
 * This file is part of Connect4 Game Solver <http://connect4.gamesolver.org>
 * Copyright (C) 2007 Pascal Pons <contact@gamesolver.org>
 *
 * Connect4 Game Solver is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Connect4 Game Solver 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Connect4 Game Solver. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef POSITION_HPP
#define POSITION_HPP

#include <string>

namespace GameSolver { namespace Connect4 {

  /**
   * A class storing a Connect 4 position.
   * Functions are relative to the current player to play.
   * Position containing aligment are not supported by this class.
   */
  class Position {
    public:

      static const int WIDTH = 7;  // width of the board
      static const int HEIGHT = 6; // height of the board
      static_assert(WIDTH < 10, "Board's width must be less than 10");

      /**
       * Indicates whether a column is playable.
       * @param col: 0-based index of column to play
       * @return true if the column is playable, false if the column is already full.
       */
      bool canPlay(int col) const
      {
        return height[col] < HEIGHT;
      }

      /**
       * Plays a playable column.
       * This function should not be called on a non-playable column or a column making an alignment.
       *
       * @param col: 0-based index of a playable column.
       */
      void play(int col)
      {
        board[col][height[col]] = 1 + moves%2;
        height[col]++;
        moves++;
      }

      /*
       * Plays a sequence of successive played columns, mainly used to initilize a board.
       * @param seq: a sequence of digits corresponding to the 1-based index of the column played.
       *
       * @return number of played moves. Processing will stop at first invalid move that can be:
       *           - invalid character (non digit, or digit >= WIDTH)
       *           - playing a colum the is already full
       *           - playing a column that makes an aligment (we only solve non).
       *         Caller can check if the move sequence was valid by comparing the number of
       *         processed moves to the length of the sequence.
       */
      unsigned int play(std::string seq)
      {
        for(unsigned int i = 0; i < seq.size(); i++) {
          int col = seq[i] - '1';
          if(col < 0 || col >= Position::WIDTH || !canPlay(col) || isWinningMove(col)) return i; // invalid move
          play(col);
        }
        return seq.size();
      }

      /**
       * Indicates whether the current player wins by playing a given column.
       * This function should never be called on a non-playable column.
       * @param col: 0-based index of a playable column.
       * @return true if current player makes an alignment by playing the corresponding column col.
       */
      bool isWinningMove(int col) const
      {
        int current_player = 1 + moves%2;
        // check for vertical alignments
        if(height[col] >= 3
            && board[col][height[col]-1] == current_player
            && board[col][height[col]-2] == current_player
            && board[col][height[col]-3] == current_player)
          return true;

        for(int dy = -1; dy <=1; dy++) {    // Iterate on horizontal (dy = 0) or two diagonal directions (dy = -1 or dy = 1).
          int nb = 0;                       // counter of the number of stones of current player surronding the played stone in tested direction.
          for(int dx = -1; dx <=1; dx += 2) // count continuous stones of current player on the left, then right of the played column.
            for(int x = col+dx, y = height[col]+dx*dy; x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT && board[x][y] == current_player; nb++) {
              x += dx;
              y += dx*dy;
            }
          if(nb >= 3) return true; // there is an aligment if at least 3 other stones of the current user
                                   // are surronding the played stone in the tested direction.
        }
        return false;
      }

      /**
       * @return number of moves played from the beginning of the game.
       */
      unsigned int nbMoves() const
      {
        return moves;
      }

      /*
       * Default constructor, build an empty position.
       */
      Position() : board{0}, height{0}, moves{0} {}

    private:
      int board[WIDTH][HEIGHT]; // 0 if cell is empty, 1 for first player and 2 for second player.
      int height[WIDTH];        // number of stones per column
      unsigned int moves;       // number of moves played since the beinning of the game.
  };

}} // end namespaces

#endif
<commit_msg>Part 6: Bitboard<commit_after>/*
 * This file is part of Connect4 Game Solver <http://connect4.gamesolver.org>
 * Copyright (C) 2007 Pascal Pons <contact@gamesolver.org>
 *
 * Connect4 Game Solver is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Connect4 Game Solver 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Connect4 Game Solver. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef POSITION_HPP
#define POSITION_HPP

#include <string>
#include <cstdint>

namespace GameSolver { namespace Connect4 {
  /**
   * A class storing a Connect 4 position.
   * Functions are relative to the current player to play.
   * Position containing aligment are not supported by this class.
   *
   * A binary bitboard representationis used.
   * Each column is encoded on HEIGH+1 bits.
	 *
   * Example of bit order to encode for a 7x6 board
	 * .  .  .  .  .  .  .
	 * 5 12 19 26 33 40 47
	 * 4 11 18 25 32 39 46
	 * 3 10 17 24 31 38 45
	 * 2  9 16 23 30 37 44
	 * 1  8 15 22 29 36 43
	 * 0  7 14 21 28 35 42
	 *
   * Position is stored as
   * - a bitboard "mask" with 1 on any color stones
   * - a bitboard "current_player" with 1 on stones of current player
   *
   * "current_player" bitboard can be transformed into a compact and non ambiguous key
   * by adding an extra bit on top of the last non empty cell of each column.
   * This allow to identify all the empty cells whithout needing "mask" bitboard
   *
	 * current_player "x" = 1, opponent "o" = 0
	 * board     position  mask      key       bottom
	 *           0000000   0000000   0000000   0000000
	 * .......   0000000   0000000   0001000   0000000
	 * ...o...   0000000   0001000   0010000   0000000
	 * ..xx...   0011000   0011000   0011000   0000000
	 * ..ox...   0001000   0011000   0001100   0000000
	 * ..oox..   0000100   0011100   0000110   0000000
	 * ..oxxo.   0001100   0011110   1101101   1111111
	 *
	 * current_player "o" = 1, opponent "x" = 0
	 * board     position  mask      key       bottom
	 *           0000000   0000000   0001000   0000000
	 * ...x...   0000000   0001000   0000000   0000000
	 * ...o...   0001000   0001000   0011000   0000000
	 * ..xx...   0000000   0011000   0000000   0000000
	 * ..ox...   0010000   0011000   0010100   0000000
	 * ..oox..   0011000   0011100   0011010   0000000
	 * ..oxxo.   0010010   0011110   1110011   1111111
	 *
	 * key is an unique representation of a board key = position + mask + bottom
	 * in practice, as bottom is constant, key = position + mask is also a
   * non-ambigous representation of the position.
	 */
  class Position {
    public:

      static const int WIDTH = 7;  // width of the board
      static const int HEIGHT = 6; // height of the board
      static_assert(WIDTH < 10, "Board's width must be less than 10");
      static_assert(WIDTH*(HEIGHT+1) <= 64, "Board does not fit in 64bits bitboard");

      /**
       * Indicates whether a column is playable.
       * @param col: 0-based index of column to play
       * @return true if the column is playable, false if the column is already full.
       */
      bool canPlay(int col) const
      {
        return (mask & top_mask(col)) == 0;
      }

      /**
       * Plays a playable column.
       * This function should not be called on a non-playable column or a column making an alignment.
       *
       * @param col: 0-based index of a playable column.
       */
      void play(int col)
      {
        current_position ^= mask;
        mask |= mask + bottom_mask(col);
        moves++;
      }

      /*
       * Plays a sequence of successive played columns, mainly used to initilize a board.
       * @param seq: a sequence of digits corresponding to the 1-based index of the column played.
       *
       * @return number of played moves. Processing will stop at first invalid move that can be:
       *           - invalid character (non digit, or digit >= WIDTH)
       *           - playing a colum the is already full
       *           - playing a column that makes an aligment (we only solve non).
       *         Caller can check if the move sequence was valid by comparing the number of
       *         processed moves to the length of the sequence.
       */
      unsigned int play(std::string seq)
      {
        for(unsigned int i = 0; i < seq.size(); i++) {
          int col = seq[i] - '1';
          if(col < 0 || col >= Position::WIDTH || !canPlay(col) || isWinningMove(col)) return i; // invalid move
          play(col);
        }
        return seq.size();
      }

      /**
       * Indicates whether the current player wins by playing a given column.
       * This function should never be called on a non-playable column.
       * @param col: 0-based index of a playable column.
       * @return true if current player makes an alignment by playing the corresponding column col.
       */
      bool isWinningMove(int col) const
      {
        uint64_t pos = current_position;
        pos |= (mask + bottom_mask(col)) & column_mask(col);
        return alignment(pos);
      }

      /**
       * @return number of moves played from the beginning of the game.
       */
      unsigned int nbMoves() const
      {
        return moves;
      }

      /**
       * @return a compact representation of a position on WIDTH*(HEIGHT+1) bits.
       */
      uint64_t key() const
      {
        return current_position + mask;
      }

      /**
       * Default constructor, build an empty position.
       */
      Position() : current_position{0}, mask{0}, moves{0} {}

    private:
      uint64_t current_position;
      uint64_t mask;
      unsigned int moves; // number of moves played since the beinning of the game.

      /**
       * Test an alignment for current player (identified by one in the bitboard pos)
       * @param a bitboard position of a player's cells.
       * @return true if the player has a 4-alignment.
       */
      static bool alignment(uint64_t pos) {
        // horizontal
        uint64_t m = pos & (pos >> (HEIGHT+1));
        if(m & (m >> (2*(HEIGHT+1)))) return true;

        // diagonal 1
        m = pos & (pos >> HEIGHT);
        if(m & (m >> (2*HEIGHT))) return true;

        // diagonal 2
        m = pos & (pos >> (HEIGHT+2));
        if(m & (m >> (2*(HEIGHT+2)))) return true;

        // vertical;
        m = pos & (pos >> 1);
        if(m & (m >> 2)) return true;

        return false;
      }

      // return a bitmask containg a single 1 corresponding to the top cel of a given column
      static uint64_t top_mask(int col) {
        return (UINT64_C(1) << (HEIGHT - 1)) << col*(HEIGHT+1);
      }

      // return a bitmask containg a single 1 corresponding to the bottom cell of a given column
      static uint64_t bottom_mask(int col) {
        return UINT64_C(1) << col*(HEIGHT+1);
      }

      // return a bitmask 1 on all the cells of a given column
      static uint64_t column_mask(int col) {
        return ((UINT64_C(1) << HEIGHT)-1) << col*(HEIGHT+1);
      }

  };

}} // end namespaces

#endif
<|endoftext|>


<commit_before>/*****************************************************************************
 * fileinfo.hpp: private wxWindows interface description
 *****************************************************************************
 * Copyright (C) 1999-2005 the VideoLAN team
 * $Id$
 *
 * Authors: Gildas Bazin <gbazin@videolan.org>
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifndef _WXVLC_FILEINFO_H_
#define _WXVLC_FILEINFO_H_

#include "wxwidgets.hpp"

#include <wx/treectrl.h>

namespace wxvlc
{
    class MetaDataPanel;
    class AdvancedInfoPanel;
    class InputStatsInfoPanel;
    class FileInfo: public wxFrame
    {
    public:
        /* Constructor */
        FileInfo( intf_thread_t *p_intf, wxWindow *p_parent );
        virtual ~FileInfo();
        void Update();

        vlc_bool_t b_need_update;

    private:
        void OnButtonClose( wxCommandEvent& event );
        void OnClose( wxCloseEvent& WXUNUSED(event) );

        DECLARE_EVENT_TABLE();

        intf_thread_t *p_intf;

        mtime_t last_update;

        MetaDataPanel *item_info;
        AdvancedInfoPanel *advanced_info;
        InputStatsInfoPanel *stats_info;

        wxBoxSizer *panel_sizer;
        bool b_stats;
    };
};

#endif
<commit_msg>fileinfo.hpp: we need to use b_stats in Update()<commit_after>/*****************************************************************************
 * fileinfo.hpp: private wxWindows interface description
 *****************************************************************************
 * Copyright (C) 1999-2005 the VideoLAN team
 * $Id$
 *
 * Authors: Gildas Bazin <gbazin@videolan.org>
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifndef _WXVLC_FILEINFO_H_
#define _WXVLC_FILEINFO_H_

#include "wxwidgets.hpp"

#include <wx/treectrl.h>

namespace wxvlc
{
    class MetaDataPanel;
    class AdvancedInfoPanel;
    class InputStatsInfoPanel;
    class FileInfo: public wxFrame
    {
    public:
        /* Constructor */
        FileInfo( intf_thread_t *p_intf, wxWindow *p_parent );
        virtual ~FileInfo();
        void Update();

        vlc_bool_t b_need_update;
        bool b_stats;

    private:
        void OnButtonClose( wxCommandEvent& event );
        void OnClose( wxCloseEvent& WXUNUSED(event) );

        DECLARE_EVENT_TABLE();

        intf_thread_t *p_intf;

        mtime_t last_update;

        MetaDataPanel *item_info;
        AdvancedInfoPanel *advanced_info;
        InputStatsInfoPanel *stats_info;

        wxBoxSizer *panel_sizer;
    };
};

#endif
<|endoftext|>