<commit_before>/*
 * main.cpp
 *
 * Copyright (C) ST-Ericsson SA 2011
 * Authors: Srimanta Panda <srimanta.panda@stericsson.com>,
 *          Ola Borgelin <ola.borgelin@stericsson.com>,
 *          Karin Hedlund <karin.hedlund@stericsson.com>,
 *          Markus Andersson <markus.m.andersson@stericsson.com> for ST-Ericsson.
 * License terms: 3-clause BSD license
 *
 */

/*
 * @addtogroup main
 * @{
 */
#include "main.h"
#include "CDAL.h"
#include "DutManager.h"
#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;

volatile bool isDone = false;
const string info = \
                    "\n \
----------------------- riff - Raw Image File Flasher -------------------------\n \
Version: 0.4.2\n \
"
                    "Flash a device. Try `riff --help' for more information. \n \
"
                    "-------------------------------------------------------------------------------";

const string cmdHelpString = " \n \
Usage: riff [OPTION]...[FILE]...\n\n \
Available command line arguments are:\n\n \
  -h, --help\t			Display this help message.\n \
  -m, --mode ACTION\t		Select the mode.\n \
					ACTION is `flash`, `erase` or `dump`\n \
  -c, --config PATH\t		Give path to configuration file.\n \
  -f, --flashimage IMAGEPATH\t	Give path to flashimage.\n \
  -a, --address FLASHADDR\t	Give a start address in hex.\n \
  -l, --length HEXLENGTH		Length of the dump [Byte] in hex.\n \
  -d, --dumppath DUMPPATH		File path on PC where to store dump.\n \
  -v, --verbose\t		Shows more detailed information.\n \
      --version\t		Shows version information.\n \
";

int main(int argc, char* argv[])
{
    signal(SIGINT, interrupt);

    cout << info << endl;

    handleCmdLineInput(argc, argv);

    logger_ = new Logger("Application");
    logger_->log(Logger::INFO, "Using config file %s", configFile);

    //Parse the config file.
    config_ = new Config(configFile);

    // if flashimage path has not been set from commandline
    //then use the path in the config file if it is set there.
    if (!strlen(flashimage)) {
        if (config_->valueExists("FLASH_IMG_PATH")) {
            strcpy(flashimage, config_->getValue("FLASH_IMG_PATH"));
        }
    }

    // Set the LCM path from ConfigFile, init the USB driver and set the callback function
    SetLCMLibPath(config_->getValue("LCMLIBPATH"));
    usb_init_driver(config_->getValue("VENDORID"), config_->getValue("PRODUCTID"));
    usb_set_listen_callback(UsbDeviceEventCallback);

    logger_->log(Logger::PROGRESS, "Listening on USB for device connection...");

    while (!isDone) {
        sleep(1);
    }

    usb_deinit_driver();

    _exit(exitstatus);
}

void interrupt(int param)
{
    logger_->log(Logger::PROGRESS, "Program interrupted...");
    exitstatus = 1;
    isDone = true;
}

void UsbDeviceEventCallback(DeviceStatus_t status, DeviceEvent_t event, Device_t device)
{
    if (COMM_DEVICE_SUCCESS == status) {
        const DUT* dut;

        switch (event) {
        case LIBUSB_DEVICE_CONNECTED:

            logger_->log(Logger::INFO, "Device detected on USB@%u", comm_get_physical_address(device));
            dut = DutManager::createDut(device);

            if (0 != dut) {
                logger_->log(Logger::PROGRESS, "Connected %s", dut->getId());
            }

            break;
        case LIBUSB_DEVICE_DISCONNECTED: {
            logger_->log(Logger::INFO, "Disconnect detected on USB@%u", comm_get_physical_address(device));
            dut = DutManager::getDut(device);

            if (0 != dut) {
                exitstatus = dut->getErrorCode();
                logger_->log(Logger::PROGRESS, "Disconnected %s", dut->getId());
                DutManager::destroyDut(device);
            }

            isDone = true;
        }
        break;
        default:
            logger_->log(Logger::ERROR, "Unknown USB event %d", event);
            break;
        }
    } else {
        logger_->log(Logger::ERROR, "USB device error %d", status);
    }
}
void handleCmdLineInput(int argc, char* argv[])
{
    string input;
    bool configPathSet = false;

    for (int i = 1; i != argc; ++i) {
        input = argv[i];

        if ("-h" == input || "--help" == input) {
            cout << cmdHelpString << endl;
            _exit(0);
        }

        else if ("-v" == input || "--verbose" == input) {
            Logger::verbose_ = true;
        }

        else if ("--version" == input) {
            _exit(0);
        }

        else if ("-m" == input || "--mode" == input) {
            i = checkCmdLineArgument(argc, i,  argv, mode);
        }

        else if ("-c" == input || "--config" == input) {
            configPathSet = true;
            i = checkCmdLineArgument(argc, i,  argv, configFile);

        }

        else if ("-f" == input || "--flashimage" == input) {
        	i = checkCmdLineArgument(argc, i,  argv, flashimage);
        }

        else if ("-a" == input || "--address" == input) {
        	i = checkCmdLineArgument(argc, i,  argv, address);
        }

        else if ("-l" == input || "--length" == input) {
        	i = checkCmdLineArgument(argc, i,  argv, length);
        }

        else if ("-d" == input || "--dumppath" == input) {
        	i = checkCmdLineArgument(argc, i,  argv, dumpPath);
        } else {
            cout << "Unknown option: " << input << endl;
        }
    }

    if (!configPathSet) {
        FILE* userConfig;
        char* home = getenv("HOME");
        char homeConfigPath[50];
        strcpy(homeConfigPath, home);
        strcat(homeConfigPath, "/.riff/config");

        userConfig = fopen(homeConfigPath, "rb");

        if (userConfig != NULL) {
            strcpy(configFile, homeConfigPath);
            fclose(userConfig);
        }
        else
        {
        	// It will check the default config in /usr/share folder otherwise
			userConfig = fopen(configFile, "r");
			if(userConfig == NULL)
			{
				cout << cmdHelpString << endl;
				_exit(0);
			}
        }

    }
	if (*dumpPath == '\0') {
		//Sets default dump path if not provided
		char* home = getenv("HOME");
		strcpy(dumpPath, home);
		strcat(dumpPath, "/flashdump.bin");
	}
    SequenceFactory::setArguments(configFile, mode, flashimage, address, length, dumpPath);
}

int checkCmdLineArgument(int argc, int counter, char* argv[], char* var)
{
    counter++;

    if (counter < argc)

    {
        strcpy(var, argv[counter]);
    } else {
        cout << "Please give a parameter to the option" << endl;
        counter--;
    }

    return counter;
}

/* @} */
<commit_msg>Return when we can't open the USB device<commit_after>/*
 * main.cpp
 *
 * Copyright (C) ST-Ericsson SA 2011
 * Authors: Srimanta Panda <srimanta.panda@stericsson.com>,
 *          Ola Borgelin <ola.borgelin@stericsson.com>,
 *          Karin Hedlund <karin.hedlund@stericsson.com>,
 *          Markus Andersson <markus.m.andersson@stericsson.com> for ST-Ericsson.
 * License terms: 3-clause BSD license
 *
 */

/*
 * @addtogroup main
 * @{
 */
#include "main.h"
#include "CDAL.h"
#include "DutManager.h"
#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;

volatile bool isDone = false;
const string info = \
                    "\n \
----------------------- riff - Raw Image File Flasher -------------------------\n \
Version: 0.4.2\n \
"
                    "Flash a device. Try `riff --help' for more information. \n \
"
                    "-------------------------------------------------------------------------------";

const string cmdHelpString = " \n \
Usage: riff [OPTION]...[FILE]...\n\n \
Available command line arguments are:\n\n \
  -h, --help\t			Display this help message.\n \
  -m, --mode ACTION\t		Select the mode.\n \
					ACTION is `flash`, `erase` or `dump`\n \
  -c, --config PATH\t		Give path to configuration file.\n \
  -f, --flashimage IMAGEPATH\t	Give path to flashimage.\n \
  -a, --address FLASHADDR\t	Give a start address in hex.\n \
  -l, --length HEXLENGTH		Length of the dump [Byte] in hex.\n \
  -d, --dumppath DUMPPATH		File path on PC where to store dump.\n \
  -v, --verbose\t		Shows more detailed information.\n \
      --version\t		Shows version information.\n \
";

int main(int argc, char* argv[])
{
    signal(SIGINT, interrupt);

    cout << info << endl;

    handleCmdLineInput(argc, argv);

    logger_ = new Logger("Application");
    logger_->log(Logger::INFO, "Using config file %s", configFile);

    //Parse the config file.
    config_ = new Config(configFile);

    // if flashimage path has not been set from commandline
    //then use the path in the config file if it is set there.
    if (!strlen(flashimage)) {
        if (config_->valueExists("FLASH_IMG_PATH")) {
            strcpy(flashimage, config_->getValue("FLASH_IMG_PATH"));
        }
    }

    // Set the LCM path from ConfigFile, init the USB driver and set the callback function
    SetLCMLibPath(config_->getValue("LCMLIBPATH"));
    usb_init_driver(config_->getValue("VENDORID"), config_->getValue("PRODUCTID"));
    usb_set_listen_callback(UsbDeviceEventCallback);

    logger_->log(Logger::PROGRESS, "Listening on USB for device connection...");

    while (!isDone) {
        sleep(1);
    }

    usb_deinit_driver();

    _exit(exitstatus);
}

void interrupt(int param)
{
    logger_->log(Logger::PROGRESS, "Program interrupted...");
    exitstatus = 1;
    isDone = true;
}

void UsbDeviceEventCallback(DeviceStatus_t status, DeviceEvent_t event, Device_t device)
{
    if (COMM_DEVICE_SUCCESS == status) {
        const DUT* dut;

        switch (event) {
        case LIBUSB_DEVICE_CONNECTED:

            logger_->log(Logger::INFO, "Device detected on USB@%u", comm_get_physical_address(device));
            dut = DutManager::createDut(device);

            if (0 != dut) {
                logger_->log(Logger::PROGRESS, "Connected %s", dut->getId());
            }

            break;
        case LIBUSB_DEVICE_DISCONNECTED: {
            logger_->log(Logger::INFO, "Disconnect detected on USB@%u", comm_get_physical_address(device));
            dut = DutManager::getDut(device);

            if (0 != dut) {
                exitstatus = dut->getErrorCode();
                logger_->log(Logger::PROGRESS, "Disconnected %s", dut->getId());
                DutManager::destroyDut(device);
            }

            isDone = true;
        }
        break;
        default:
            logger_->log(Logger::ERROR, "Unknown USB event %d", event);
            break;
        }
    } else if (COMM_DEVICE_LIBUSB_FAILED_TO_OPEN_PORT == status) {
        logger_->log(Logger::ERROR, "Cannot open USB device. Are you root?", status);
        isDone = true;
        exitstatus = 1;
    } else {
        logger_->log(Logger::ERROR, "USB device error %d", status);
    }
}
void handleCmdLineInput(int argc, char* argv[])
{
    string input;
    bool configPathSet = false;

    for (int i = 1; i != argc; ++i) {
        input = argv[i];

        if ("-h" == input || "--help" == input) {
            cout << cmdHelpString << endl;
            _exit(0);
        }

        else if ("-v" == input || "--verbose" == input) {
            Logger::verbose_ = true;
        }

        else if ("--version" == input) {
            _exit(0);
        }

        else if ("-m" == input || "--mode" == input) {
            i = checkCmdLineArgument(argc, i,  argv, mode);
        }

        else if ("-c" == input || "--config" == input) {
            configPathSet = true;
            i = checkCmdLineArgument(argc, i,  argv, configFile);

        }

        else if ("-f" == input || "--flashimage" == input) {
        	i = checkCmdLineArgument(argc, i,  argv, flashimage);
        }

        else if ("-a" == input || "--address" == input) {
        	i = checkCmdLineArgument(argc, i,  argv, address);
        }

        else if ("-l" == input || "--length" == input) {
        	i = checkCmdLineArgument(argc, i,  argv, length);
        }

        else if ("-d" == input || "--dumppath" == input) {
        	i = checkCmdLineArgument(argc, i,  argv, dumpPath);
        } else {
            cout << "Unknown option: " << input << endl;
        }
    }

    if (!configPathSet) {
        FILE* userConfig;
        char* home = getenv("HOME");
        char homeConfigPath[50];
        strcpy(homeConfigPath, home);
        strcat(homeConfigPath, "/.riff/config");

        userConfig = fopen(homeConfigPath, "rb");

        if (userConfig != NULL) {
            strcpy(configFile, homeConfigPath);
            fclose(userConfig);
        }
        else
        {
        	// It will check the default config in /usr/share folder otherwise
			userConfig = fopen(configFile, "r");
			if(userConfig == NULL)
			{
				cout << cmdHelpString << endl;
				_exit(0);
			}
        }

    }
	if (*dumpPath == '\0') {
		//Sets default dump path if not provided
		char* home = getenv("HOME");
		strcpy(dumpPath, home);
		strcat(dumpPath, "/flashdump.bin");
	}
    SequenceFactory::setArguments(configFile, mode, flashimage, address, length, dumpPath);
}

int checkCmdLineArgument(int argc, int counter, char* argv[], char* var)
{
    counter++;

    if (counter < argc)

    {
        strcpy(var, argv[counter]);
    } else {
        cout << "Please give a parameter to the option" << endl;
        counter--;
    }

    return counter;
}

/* @} */
<|endoftext|>


<commit_before>#include <fstream>
#include <iostream>
#include <regex>
#include <string>
#include <unordered_map>

using namespace std;

typedef unordered_map<string, char> umap;

umap get_rna_code(string table){
    //Let's agree that 'Z' represents Stop codon
    umap out;
    fstream rna_code;
    string line;
    rna_code.open(table);
    getline(rna_code, line);
    regex codon_rgx("((([AUGC]{3})[[:space:]]([A-Z])[[:space:]]*){4})");
    smatch codon;
    do {
        if (regex_search(line, codon, codon_rgx)) {
            cout << codon[0] << endl;//"<1\t2>" << codon[1] << "\t" << codon[2] << endl;
            for (auto res : codon) cout << res << endl;
        }
        getline(rna_code, line);
    } while (!rna_code.eof());
    return out;
}
int main() {
    get_rna_code("rna_codon_table.txt");
    return 0;
}
<commit_msg>Added solution for 'Translating RNA into Protein'<commit_after>#include <fstream>
#include <iostream>
#include <regex>
#include <string>
#include <unordered_map>

using namespace std;

typedef unordered_map<string, char> umap;

umap get_rna_code(string table){
    //Let's agree that 'Z' represents Stop codon
    umap out;
    fstream rna_code("rna_codon_table.txt");
    string line;
    regex codon("(([AUGC]{3})\\s([A-Z]))");
    while (!rna_code.eof()) {
        getline(rna_code, line);
        auto line_begin = std::sregex_iterator(line.begin(), line.end(), codon);
        auto line_end = std::sregex_iterator();
        for (std::sregex_iterator i = line_begin; i != line_end; ++i) {
            std::smatch match = *i;
            out.insert(make_pair(match[2].str(), match[3].str()[0]));
        }
    }
    return out;
}
int main() {
    umap protein_table = get_rna_code("rna_codon_table.txt");
    fstream rna_file("rna2protein.txt");
    string rna_seq, codon;
    string protein = "";
    getline(rna_file, rna_seq);
    for (int i = 0; i < rna_seq.size() - 2; i+=3) {
        codon = rna_seq.substr(i,3);
        if (protein_table[codon] == 'Z') {
            break;
        }
        protein += protein_table[codon];
    }
    cout << protein << endl;
    return 0;
}
<|endoftext|>


<commit_before>#include "IK.h"
#include "Rotation.h"
#include "Geometry.h"
#include <math3d/basis.h>
#include <math3d/rotationfit.h>
#include <math3d/Plane3D.h>
#include <math3d/Line3D.h>
#include <math3d/misc.h>
using namespace std;

IKGoal::IKGoal()
  : link(0),destLink(-1),posConstraint(PosNone),localPosition(Zero),rotConstraint(RotNone)
{
}

void IKGoal::SetFixedTransform(const RigidTransform& T)
{
  localPosition.setZero();
  SetFixedPosition(T.t);
  SetFixedRotation(T.R);
}

void IKGoal::SetPlanarPosition(const Vector3& point,const Vector3& normal)
{
  posConstraint = PosPlanar;
  endPosition = point;
  direction = normal;
}

void IKGoal::SetLinearPosition(const Vector3& point,const Vector3& d)
{
  posConstraint = PosLinear;
  endPosition = point;
  direction = d;
}

void IKGoal::SetFixedRotation(const Matrix3& R)
{
  rotConstraint = RotFixed;
  MomentRotation mR;
  mR.setMatrix(R);
  endRotation = mR;
}

void IKGoal::SetAxisRotation(const Vector3& locAxis,const Vector3& worldAxis)
{
  rotConstraint = RotAxis;
  localAxis = locAxis;
  Assert(FuzzyEquals(localAxis.normSquared(),One));
  endRotation = worldAxis;
}

void IKGoal::SetFromPoints(const vector<Vector3>& loc,const vector<Vector3>& wor,Real tol)
{
  Assert(loc.size()==wor.size());
  if(loc.size()==0) {
    SetFreePosition();
    SetFreeRotation();
  }
  else if(loc.size()==1) {
    localPosition=loc[0];
    SetFixedPosition(wor[0]);
    SetFreeRotation();
  }
  else if(loc.size()==2) {
    localPosition = 0.5*(loc[0]+loc[1]);
    SetFixedPosition(0.5*(wor[0]+wor[1]));
    if(loc[0].isEqual(loc[1],tol) || wor[0].isEqual(wor[1],tol)) {
      SetFreeRotation();
    }
    else {
      Vector3 laxis,waxis;
      laxis.sub(loc[1],loc[0]);
      waxis.sub(wor[1],wor[0]);
      laxis.inplaceNormalize();
      waxis.inplaceNormalize();
      SetAxisRotation(laxis,waxis);
    }
  }
  else {
    RigidTransform Tloc,Twor;
    Vector3 cov;
    Real res=FitFrames(loc,wor,Tloc,Twor,cov);
    if(IsInf(res)) {
      SetFreePosition();
      SetFreeRotation();
    }
    else {
      localPosition = -Tloc.t;
      SetFixedPosition(-Twor.t);
      SetFixedRotation(transpose(Twor.R)*Tloc.R);
      if(Abs(cov.z) < tol) {
	if(Abs(cov.y) < tol) {
	  if(Abs(cov.x) < tol) {
	    //just a point
	    SetFreeRotation();
	  }
	  else {
	    //just an axis, look at x column for axis
	    Vector3 wx,lx;
	    Tloc.R.getRow1(lx);
	    Twor.R.getRow1(wx);
	    SetAxisRotation(lx,wx);
	  }
	}
      }
    }
  }
}

void IKGoal::GetFixedGoalRotation(Matrix3& R) const
{
  Assert(rotConstraint == RotFixed);
  MomentRotation m(endRotation);
  m.getMatrix(R);
}

void IKGoal::GetFixedGoalTransform(RigidTransform& T) const
{
  Assert(posConstraint == PosFixed);
  Assert(rotConstraint == RotFixed);
  MomentRotation m(endRotation);
  GetRotationAboutLocalPoint(localPosition,endPosition,m,T);
}

void IKGoal::GetBaseEdgeRotation(Matrix3& R0) const
{
  GetMinimalRotation(localAxis,endRotation,R0);
}

void IKGoal::GetEdgeGoalTransform(Real theta,RigidTransform& T) const
{
  Matrix3 R0,RTheta;
  GetBaseEdgeRotation(R0);
  AngleAxisRotation aa;
  aa.axis = localAxis;
  aa.angle = theta;
  aa.getMatrix(RTheta);
  T.R.mul(R0,RTheta);
  T.t = endPosition - T.R*localPosition;
}

void IKGoal::GetClosestGoalTransform(const RigidTransform& T0,RigidTransform& T) const
{
  //fill out rotation first
  if(rotConstraint == RotFixed) {
    GetFixedGoalRotation(T.R);
  }
  else if(rotConstraint == RotAxis) {
    //T.R*localAxis = endRotation
    GetMinimalRotation(localAxis,T0.R*endRotation,T.R);
    //make it so orthogonal directions perform a rotation similar to T0.R
    Vector3 lx,ly,rx,ry,refx;
    GetCanonicalBasis(localAxis,lx,ly);
    rx = T.R*rx;
    ry = T.R*ry;
    refx = T0.R*lx;
    Real x = dot(refx,rx);
    Real y = dot(refx,ry);
    //find the rotation about endRotation that gets closer to this
    Real theta = Atan2(y,x);
    AngleAxisRotation aa;
    aa.angle = theta;
    aa.axis = T0.R*endRotation;

    Matrix3 Rrot;
    aa.getMatrix(Rrot);
    T.R = Rrot*T.R;
  }
  else
    T.R = T0.R;

  T.t = endPosition - T.R*localPosition;
  if(posConstraint == PosPlanar) {
    //find closest transform on plane to T0.t
    Plane3D p;
    p.setPointNormal(T.t,direction);
    p.project(T0.t,T.t);
  }
  else if(posConstraint == PosLinear) {
    //find closest transform on line to T0.t
    Line3D line;
    line.source = T.t;
    line.direction = direction;
    line.closestPoint(T0.t,T.t);
  }
  else if(posConstraint == PosNone)
    T.t = T0.t;
}

void IKGoal::Transform(const RigidTransform& T)
{
  endPosition = T*endPosition;
  direction = T.R*direction;
  if(rotConstraint == IKGoal::RotFixed) {
    MomentRotation m; m.set(endRotation);
    Matrix3 R;
    m.getMatrix(R);
    R = T.R*R;
    Assert(IsFinite(R));
    m.setMatrix(R);
    endRotation = m;
  }
  else if(rotConstraint == IKGoal::RotAxis) {
    endRotation = T.R*endRotation;
  }
}

void IKGoal::RemoveRotationAxis(const Vector3& p,const Vector3& axis)
{
  switch(rotConstraint) {
  case 0: //done
    break;
  case 1: //single-axis rotation
    FatalError("TODO - set dual-axis rotation");
    break;
  case 2: //dual-axis rotation
    //if one of the axes are parallel to the normal, all is well
    FatalError("TODO - dual-axis rotation isn't implemented");
    break;
  case 3: //fixed rotation
    //allow it to rotate about the cp normal
    {
      Vector3 locAxis;
      Vector3 locPos;
      RigidTransform T;
      GetFixedGoalTransform(T);
      T.R.mulTranspose(axis,locAxis);
      T.mulInverse(p,locPos);
      SetAxisRotation(locAxis,axis);
      localPosition = locPos;
      endPosition = p;
    }
    break;
  }
}

void IKGoal::RemoveRotationAxis(const Vector3& axis)
{
  switch(rotConstraint) {
  case IKGoal::PosNone: //done
    break;
  case IKGoal::RotTwoAxis: //dual-axis rotation
    //if one of the axes are parallel to the normal, all is well
    FatalError("TODO - dual-axis rotation isn't implemented");
    break;
  case IKGoal::RotAxis: //single-axis rotation
    FatalError("TODO - set dual-axis rotation");
    break;
  case IKGoal::RotFixed: //fixed rotation
    //allow it to rotate about the cp normal
    {
      Vector3 locAxis;
      RigidTransform T;
      GetFixedGoalTransform(T);
      T.R.mulTranspose(axis,locAxis);
      SetAxisRotation(locAxis,axis);
    }
    break;
  }
}

void IKGoal::RemovePositionAxis(const Vector3& dir)
{
  switch(posConstraint) {
  case IKGoal::PosNone: //done
    break;
  case IKGoal::PosPlanar: //fixed plane
    if(!FuzzyZero(direction.dot(dir)))
      posConstraint = IKGoal::PosNone;
    break;
  case IKGoal::PosLinear: //fixed line
    if(!FuzzyZero(direction.dot(dir))) {
      Vector3 v;
      v.setCross(direction,dir);
      direction.setNormalized(v);
      posConstraint = IKGoal::PosPlanar;
    }
    break;
  case IKGoal::PosFixed: //fixed position
    direction.setNormalized(dir);
    posConstraint = IKGoal::PosLinear;
    break;
  }
}

void IKGoal::GetError(const RigidTransform& Trel,Real poserr[3],Real orierr[3]) const
{
  Vector3 perr=Trel*localPosition-endPosition;
  if(posConstraint == IKGoal::PosFixed) {
    perr.get(poserr[0],poserr[1],poserr[2]);
  }
  else if(posConstraint == IKGoal::PosLinear) {
    Vector3 xb,yb;
    direction.getOrthogonalBasis(xb,yb);
    poserr[0] = dot(perr,xb);
    poserr[1] = dot(perr,yb);
  }
  else if(posConstraint == IKGoal::PosPlanar) {
    poserr[0] = dot(perr,direction);
  }

  if(rotConstraint==IKGoal::RotFixed) {
    MomentRotation em(endRotation);
    Matrix3 Rgoal,Rdiff;
    em.getMatrix(Rgoal);
    Rdiff.mulTransposeB(Trel.R,Rgoal);
    Assert(IsFinite(Rdiff));
    em.setMatrix(Rdiff);
    orierr[0]=em.x;
    orierr[1]=em.y;
    orierr[2]=em.z;
  }
  else if(rotConstraint==IKGoal::RotAxis) {
    Vector3 x,y;
    endRotation.getOrthogonalBasis(x,y);
    Vector3 curAxis;
    Trel.R.mul(localAxis,curAxis);
    orierr[0] = dot(curAxis,x);
    orierr[1] = dot(curAxis,y);
  }
  else if(rotConstraint==IKGoal::RotNone) { }
  else {
    FatalError("EvalIKGoal(): Invalid number of rotation terms");
  }
}

istream& operator >> (istream& in,IKGoal& data)
{
  in >> data.link >> data.destLink;
  char ptype,rtype;
  in>>ptype;
  if(ptype == 'N') { //no position
    data.posConstraint = IKGoal::PosNone;
  }
  else if(ptype == 'P') {  //planar
    data.posConstraint = IKGoal::PosPlanar;
    in >> data.localPosition >> data.endPosition >> data.direction;
  }
  else if(ptype == 'L') { //linear
    data.posConstraint = IKGoal::PosLinear;
    in >> data.localPosition >> data.endPosition >> data.direction;
  }
  else if(ptype == 'F' ) { //fixed
    data.posConstraint = IKGoal::PosFixed;
    in >> data.localPosition >> data.endPosition;
  }
  else {
    fprintf(stderr,"IKGoal: invalid position type character %c\n",ptype);
    in.setstate(ios::badbit);
    return in;
  }
  in>>rtype;
  if(rtype == 'N') { //no rotation
    data.rotConstraint = IKGoal::RotNone;
  }
  else if(rtype == 'T') {  //twoaxis
    data.rotConstraint = IKGoal::RotTwoAxis;
    in >> data.localAxis >> data.endRotation;
  }
  else if(rtype == 'A') { //axis
    data.rotConstraint = IKGoal::RotAxis;
    in >> data.localAxis >> data.endRotation;
  }
  else if(rtype == 'F' ) { //fixed
    data.rotConstraint = IKGoal::RotFixed;
    in >> data.endRotation;
  }
  else {
    fprintf(stderr,"IKGoal: invalid rotation type character %c\n",rtype);
    in.setstate(ios::badbit);
    return in;
  }
  return in;
}

std::ostream& operator << (std::ostream& out,const IKGoal& data)
{
  out<<data.link<<" "<<data.destLink<<endl;
  switch(data.posConstraint) {
  case IKGoal::PosNone:
    out<<"N"<<endl;
    break;
  case IKGoal::PosPlanar:
    out<<"P "<<data.localPosition<<"   "<<data.endPosition<<"   "<<data.direction<<endl;
    break;
  case IKGoal::PosLinear:
    out<<"L "<<data.localPosition<<"   "<<data.endPosition<<"   "<<data.direction<<endl;
    break;
  case IKGoal::PosFixed:
    out<<"F "<<data.localPosition<<"   "<<data.endPosition<<endl;
    break;
  }
  switch(data.rotConstraint) {
  case IKGoal::RotNone:
    out<<"N"<<endl;
    break;
  case IKGoal::RotTwoAxis:
    out<<"T "<<data.localAxis<<"   "<<data.endRotation<<endl;
    break;
  case IKGoal::RotAxis:
    out<<"A "<<data.localAxis<<"   "<<data.endRotation<<endl;
    break;
  case IKGoal::RotFixed:
    out<<"F "<<data.endRotation<<endl;
    break;
  }
  return out;
}
<commit_msg>Fixing error in IK constraint<commit_after>#include "IK.h"
#include "Rotation.h"
#include "Geometry.h"
#include <math3d/basis.h>
#include <math3d/rotationfit.h>
#include <math3d/Plane3D.h>
#include <math3d/Line3D.h>
#include <math3d/misc.h>
using namespace std;

IKGoal::IKGoal()
  : link(0),destLink(-1),posConstraint(PosNone),localPosition(Zero),rotConstraint(RotNone)
{
}

void IKGoal::SetFixedTransform(const RigidTransform& T)
{
  localPosition.setZero();
  SetFixedPosition(T.t);
  SetFixedRotation(T.R);
}

void IKGoal::SetPlanarPosition(const Vector3& point,const Vector3& normal)
{
  posConstraint = PosPlanar;
  endPosition = point;
  direction = normal;
}

void IKGoal::SetLinearPosition(const Vector3& point,const Vector3& d)
{
  posConstraint = PosLinear;
  endPosition = point;
  direction = d;
}

void IKGoal::SetFixedRotation(const Matrix3& R)
{
  rotConstraint = RotFixed;
  MomentRotation mR;
  mR.setMatrix(R);
  endRotation = mR;
}

void IKGoal::SetAxisRotation(const Vector3& locAxis,const Vector3& worldAxis)
{
  rotConstraint = RotAxis;
  localAxis = locAxis;
  Assert(FuzzyEquals(localAxis.normSquared(),One));
  endRotation = worldAxis;
}

void IKGoal::SetFromPoints(const vector<Vector3>& loc,const vector<Vector3>& wor,Real tol)
{
  Assert(loc.size()==wor.size());
  if(loc.size()==0) {
    SetFreePosition();
    SetFreeRotation();
  }
  else if(loc.size()==1) {
    localPosition=loc[0];
    SetFixedPosition(wor[0]);
    SetFreeRotation();
  }
  else if(loc.size()==2) {
    localPosition = 0.5*(loc[0]+loc[1]);
    SetFixedPosition(0.5*(wor[0]+wor[1]));
    if(loc[0].isEqual(loc[1],tol) || wor[0].isEqual(wor[1],tol)) {
      SetFreeRotation();
    }
    else {
      Vector3 laxis,waxis;
      laxis.sub(loc[1],loc[0]);
      waxis.sub(wor[1],wor[0]);
      laxis.inplaceNormalize();
      waxis.inplaceNormalize();
      SetAxisRotation(laxis,waxis);
    }
  }
  else {
    RigidTransform Tloc,Twor;
    Vector3 cov;
    Real res=FitFrames(loc,wor,Tloc,Twor,cov);
    if(IsInf(res)) {
      SetFreePosition();
      SetFreeRotation();
    }
    else {
      localPosition = -Tloc.t;
      SetFixedPosition(-Twor.t);
      SetFixedRotation(transpose(Twor.R)*Tloc.R);
      if(Abs(cov.z) < tol) {
	if(Abs(cov.y) < tol) {
	  if(Abs(cov.x) < tol) {
	    //just a point
	    SetFreeRotation();
	  }
	  else {
	    //just an axis, look at x column for axis
	    Vector3 wx,lx;
	    Tloc.R.getRow1(lx);
	    Twor.R.getRow1(wx);
	    SetAxisRotation(lx,wx);
	  }
	}
      }
    }
  }
}

void IKGoal::GetFixedGoalRotation(Matrix3& R) const
{
  Assert(rotConstraint == RotFixed);
  MomentRotation m(endRotation);
  m.getMatrix(R);
}

void IKGoal::GetFixedGoalTransform(RigidTransform& T) const
{
  Assert(posConstraint == PosFixed);
  Assert(rotConstraint == RotFixed);
  MomentRotation m(endRotation);
  GetRotationAboutLocalPoint(localPosition,endPosition,m,T);
}

void IKGoal::GetBaseEdgeRotation(Matrix3& R0) const
{
  GetMinimalRotation(localAxis,endRotation,R0);
}

void IKGoal::GetEdgeGoalTransform(Real theta,RigidTransform& T) const
{
  Matrix3 R0,RTheta;
  GetBaseEdgeRotation(R0);
  AngleAxisRotation aa;
  aa.axis = localAxis;
  aa.angle = theta;
  aa.getMatrix(RTheta);
  T.R.mul(R0,RTheta);
  T.t = endPosition - T.R*localPosition;
}

void IKGoal::GetClosestGoalTransform(const RigidTransform& T0,RigidTransform& T) const
{
  //fill out rotation first
  if(rotConstraint == RotFixed) {
    GetFixedGoalRotation(T.R);
  }
  else if(rotConstraint == RotAxis) {
    //T.R*localAxis = endRotation
    GetMinimalRotation(localAxis,T0.R*endRotation,T.R);
    //make it so orthogonal directions perform a rotation similar to T0.R
    Vector3 lx,ly,rx,ry,refx;
    GetCanonicalBasis(localAxis,lx,ly);
    rx = T.R*rx;
    ry = T.R*ry;
    refx = T0.R*lx;
    Real x = dot(refx,rx);
    Real y = dot(refx,ry);
    //find the rotation about endRotation that gets closer to this
    Real theta = Atan2(y,x);
    AngleAxisRotation aa;
    aa.angle = theta;
    aa.axis = T0.R*endRotation;

    Matrix3 Rrot;
    aa.getMatrix(Rrot);
    T.R = Rrot*T.R;
  }
  else
    T.R = T0.R;

  T.t = endPosition - T.R*localPosition;
  if(posConstraint == PosPlanar) {
    //find closest transform on plane to T0.t
    Plane3D p;
    p.setPointNormal(T.t,direction);
    p.project(T0.t,T.t);
  }
  else if(posConstraint == PosLinear) {
    //find closest transform on line to T0.t
    Line3D line;
    line.source = T.t;
    line.direction = direction;
    line.closestPoint(T0.t,T.t);
  }
  else if(posConstraint == PosNone)
    T.t = T0.t;
}

void IKGoal::Transform(const RigidTransform& T)
{
  endPosition = T*endPosition;
  direction = T.R*direction;
  if(rotConstraint == IKGoal::RotFixed) {
    MomentRotation m; m.set(endRotation);
    Matrix3 R;
    m.getMatrix(R);
    R = T.R*R;
    Assert(IsFinite(R));
    m.setMatrix(R);
    endRotation = m;
  }
  else if(rotConstraint == IKGoal::RotAxis) {
    endRotation = T.R*endRotation;
  }
}

void IKGoal::RemoveRotationAxis(const Vector3& p,const Vector3& axis)
{
  switch(rotConstraint) {
  case 0: //done
    break;
  case 1: //single-axis rotation
    FatalError("TODO - set dual-axis rotation");
    break;
  case 2: //dual-axis rotation
    //if one of the axes are parallel to the normal, all is well
    FatalError("TODO - dual-axis rotation isn't implemented");
    break;
  case 3: //fixed rotation
    //allow it to rotate about the cp normal
    {
      Vector3 locAxis;
      Vector3 locPos;
      RigidTransform T;
      GetFixedGoalTransform(T);
      T.R.mulTranspose(axis,locAxis);
      T.mulInverse(p,locPos);
      SetAxisRotation(locAxis,axis);
      localPosition = locPos;
      endPosition = p;
    }
    break;
  }
}

void IKGoal::RemoveRotationAxis(const Vector3& axis)
{
  switch(rotConstraint) {
  case IKGoal::PosNone: //done
    break;
  case IKGoal::RotTwoAxis: //dual-axis rotation
    //if one of the axes are parallel to the normal, all is well
    FatalError("TODO - dual-axis rotation isn't implemented");
    break;
  case IKGoal::RotAxis: //single-axis rotation
    FatalError("TODO - set dual-axis rotation");
    break;
  case IKGoal::RotFixed: //fixed rotation
    //allow it to rotate about the cp normal
    {
      Vector3 locAxis;
      RigidTransform T;
      GetFixedGoalTransform(T);
      T.R.mulTranspose(axis,locAxis);
      SetAxisRotation(locAxis,axis);
    }
    break;
  }
}

void IKGoal::RemovePositionAxis(const Vector3& dir)
{
  switch(posConstraint) {
  case IKGoal::PosNone: //done
    break;
  case IKGoal::PosPlanar: //fixed plane
    if(!FuzzyZero(direction.dot(dir)))
      posConstraint = IKGoal::PosNone;
    break;
  case IKGoal::PosLinear: //fixed line
    if(!FuzzyZero(direction.dot(dir))) {
      Vector3 v;
      v.setCross(direction,dir);
      direction.setNormalized(v);
      posConstraint = IKGoal::PosPlanar;
    }
    break;
  case IKGoal::PosFixed: //fixed position
    direction.setNormalized(dir);
    posConstraint = IKGoal::PosLinear;
    break;
  }
}

void IKGoal::GetError(const RigidTransform& Trel,Real poserr[3],Real orierr[3]) const
{
  Vector3 perr=Trel*localPosition-endPosition;
  if(posConstraint == IKGoal::PosFixed) {
    perr.get(poserr[0],poserr[1],poserr[2]);
  }
  else if(posConstraint == IKGoal::PosLinear) {
    Vector3 xb,yb;
    direction.getOrthogonalBasis(xb,yb);
    poserr[0] = dot(perr,xb);
    poserr[1] = dot(perr,yb);
  }
  else if(posConstraint == IKGoal::PosPlanar) {
    poserr[0] = dot(perr,direction);
  }

  if(rotConstraint==IKGoal::RotFixed) {
    MomentRotation em(endRotation);
    Matrix3 Rgoal,Rdiff;
    em.getMatrix(Rgoal);
    Rdiff.mulTransposeB(Trel.R,Rgoal);
    Assert(IsFinite(Rdiff));
    em.setMatrix(Rdiff);
    orierr[0]=em.x;
    orierr[1]=em.y;
    orierr[2]=em.z;
  }
  else if(rotConstraint==IKGoal::RotAxis) {
    Real neg = Max(-localAxis.dot(endRotation),0.0);
    Vector3 x,y;
    endRotation.getOrthogonalBasis(x,y);
    Vector3 curAxis;
    Trel.R.mul(localAxis,curAxis);
    orierr[0] = dot(curAxis,x)+neg;
    orierr[1] = dot(curAxis,y)+neg;
  }
  else if(rotConstraint==IKGoal::RotNone) { }
  else {
    FatalError("EvalIKGoal(): Invalid number of rotation terms");
  }
}

istream& operator >> (istream& in,IKGoal& data)
{
  in >> data.link >> data.destLink;
  char ptype,rtype;
  in>>ptype;
  if(ptype == 'N') { //no position
    data.posConstraint = IKGoal::PosNone;
  }
  else if(ptype == 'P') {  //planar
    data.posConstraint = IKGoal::PosPlanar;
    in >> data.localPosition >> data.endPosition >> data.direction;
  }
  else if(ptype == 'L') { //linear
    data.posConstraint = IKGoal::PosLinear;
    in >> data.localPosition >> data.endPosition >> data.direction;
  }
  else if(ptype == 'F' ) { //fixed
    data.posConstraint = IKGoal::PosFixed;
    in >> data.localPosition >> data.endPosition;
  }
  else {
    fprintf(stderr,"IKGoal: invalid position type character %c\n",ptype);
    in.setstate(ios::badbit);
    return in;
  }
  in>>rtype;
  if(rtype == 'N') { //no rotation
    data.rotConstraint = IKGoal::RotNone;
  }
  else if(rtype == 'T') {  //twoaxis
    data.rotConstraint = IKGoal::RotTwoAxis;
    in >> data.localAxis >> data.endRotation;
  }
  else if(rtype == 'A') { //axis
    data.rotConstraint = IKGoal::RotAxis;
    in >> data.localAxis >> data.endRotation;
  }
  else if(rtype == 'F' ) { //fixed
    data.rotConstraint = IKGoal::RotFixed;
    in >> data.endRotation;
  }
  else {
    fprintf(stderr,"IKGoal: invalid rotation type character %c\n",rtype);
    in.setstate(ios::badbit);
    return in;
  }
  return in;
}

std::ostream& operator << (std::ostream& out,const IKGoal& data)
{
  out<<data.link<<" "<<data.destLink<<endl;
  switch(data.posConstraint) {
  case IKGoal::PosNone:
    out<<"N"<<endl;
    break;
  case IKGoal::PosPlanar:
    out<<"P "<<data.localPosition<<"   "<<data.endPosition<<"   "<<data.direction<<endl;
    break;
  case IKGoal::PosLinear:
    out<<"L "<<data.localPosition<<"   "<<data.endPosition<<"   "<<data.direction<<endl;
    break;
  case IKGoal::PosFixed:
    out<<"F "<<data.localPosition<<"   "<<data.endPosition<<endl;
    break;
  }
  switch(data.rotConstraint) {
  case IKGoal::RotNone:
    out<<"N"<<endl;
    break;
  case IKGoal::RotTwoAxis:
    out<<"T "<<data.localAxis<<"   "<<data.endRotation<<endl;
    break;
  case IKGoal::RotAxis:
    out<<"A "<<data.localAxis<<"   "<<data.endRotation<<endl;
    break;
  case IKGoal::RotFixed:
    out<<"F "<<data.endRotation<<endl;
    break;
  }
  return out;
}
<|endoftext|>


<commit_before>// Copyright 2016-2017 Francesco Biscani (bluescarni@gmail.com)
//
// This file is part of the mp++ library.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <quadmath.h>

#include <mp++/mp++.hpp>

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

using namespace mppp;

TEST_CASE("real128 signbit")
{
    real128 r;
    REQUIRE(!r.signbit());
    REQUIRE(!signbit(r));
    r = -0.;
    REQUIRE(r.signbit());
    REQUIRE(signbit(r));
    r = -1;
    REQUIRE(r.signbit());
    REQUIRE(signbit(r));
    r = 1;
    REQUIRE(!r.signbit());
    REQUIRE(!signbit(r));
    r = "inf";
    REQUIRE(!r.signbit());
    REQUIRE(!signbit(r));
    r = "-inf";
    REQUIRE(r.signbit());
    REQUIRE(signbit(r));
    r = "nan";
    REQUIRE(!r.signbit());
    REQUIRE(!signbit(r));
    r = ::copysignq(r.m_value, ::__float128(-1));
    REQUIRE(r.signbit());
    REQUIRE(signbit(r));
}
<commit_msg>Another test fix.<commit_after>// Copyright 2016-2017 Francesco Biscani (bluescarni@gmail.com)
//
// This file is part of the mp++ library.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <quadmath.h>

#include <mp++/mp++.hpp>

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

using namespace mppp;

TEST_CASE("real128 signbit")
{
    real128 r;
    REQUIRE(!r.signbit());
    REQUIRE(!signbit(r));
    r = -0.;
    REQUIRE(r.signbit());
    REQUIRE(signbit(r));
    r = -1;
    REQUIRE(r.signbit());
    REQUIRE(signbit(r));
    r = 1;
    REQUIRE(!r.signbit());
    REQUIRE(!signbit(r));
    r = "inf";
    REQUIRE(!r.signbit());
    REQUIRE(!signbit(r));
    r = "-inf";
    REQUIRE(r.signbit());
    REQUIRE(signbit(r));
    r = "nan";
    REQUIRE(!r.signbit());
    REQUIRE(!signbit(r));
    r = ::copysignq(r.m_value, __float128(-1));
    REQUIRE(r.signbit());
    REQUIRE(signbit(r));
}
<|endoftext|>


<commit_before>#include <iostream>
#include "bots.h"
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>

const int _LADO = 10;

using boost::asio::ip::tcp;

void send(tcp::socket &socket, const std::string & str)
{
    boost::asio::write(socket, boost::asio::buffer(str + "\n"), boost::asio::transfer_all());
}

void pinta_escenario( bots mis_bots, int paso)
{
	std::cout << "Paso : " << paso << std::endl;

	for ( int col = 0; col < _LADO + 2; col++ ) // Primera fila de X
        	std::cout << 'X';
	std::cout << std::endl;
	for ( int fila = 0; fila < _LADO; fila++ ) //! Recorre toda la altura
        {
		std::cout << 'X'; // Primera X de la fila
		for ( int col = 0; col < _LADO; col++ ) // Espacios en blanco
		{
			bot * pos_bot = mis_bots.find_at( { col, fila} );
			//std::cout << pos_bot->get_team();

			if ( pos_bot == nullptr )
                        	std::cout << ' ';
			else
				std::cout << pos_bot->get_team();

		}
		std::cout << 'X'; //! Espacios de 1a altura - fila
                std::cout << std::endl;
        }
	for ( int col = 0; col < _LADO + 2; col++ ) // Primera fila de X
                        std::cout << 'X';
	std::cout << std::endl;
}

int main (int argc, char* argv[])
{

	//std::cout << "\x1B[2J\x1B[H"; // Despeja la pantalla del terminal
	std::cout << "A jugar!!" << std::endl;

	boost::asio::io_service io_service; // Inicia comunicaciones

	tcp::resolver resolver(io_service); // Resuelve la comunicación
	auto endpoint_iterator = resolver.resolve({ argv[1], argv[2] }); // Iterador hacia puerto y dirección

	std::shared_ptr<tcp::socket> socket(new tcp::socket(io_service)); // Puntero compartido hacia el socket

	boost::asio::connect(*socket, endpoint_iterator); // Conexión

	int paso = 0;

	// Variables de comunicacion

	boost::mutex state_mutex;
	bool gameover = false;
	bool connected = false;
	bot::team_id id = 6666;
	bot::field_size field_width;
	bot::field_size field_height;
	int win_width = 500;
	int win_height = 500;

	bots mi_bots = bots(_LADO, _LADO); // Tamaño del campo 10x10, usa la pila
	// bots *mi_bots = new bots(10,10) // al monticulo

	mi_bots.generate(4,4); // Número de equipos y número de miembros por equipo, usa la pila
	// mi_bots->generate(3,10); // al monticulo

	boost::asio::streambuf buf;

	read_until(*socket, buf, "\n");

	std::string data;
	std::istream is(&buf);
	std::getline(is, data);

	std::istringstream mi_stream(data);

	std::string command;
	mi_stream >> command;

	// Lee la información inicial
	if(command == "welcome")
	{
        mi_stream >> id;
        std::cout << "team id: " << id << std::endl;
        //ai.set_team(id);

        mi_stream >> field_width;
        mi_stream >> field_height;
        mi_bots.set_size(field_width, field_height);
        std::cout << "setting field: " << field_width << " x " << field_height << std::endl;

        //set_screen(win_width, win_height, field_width, field_height);
        //connected = true;
    }

	//while ( std::cin.get() != ' ' );

	while (!gameover)
	{
		{
			read_until(*socket, buf, "\n"); //Leo el bufer
			std::istream is2(&buf); // Input Stream (lectura) a la clase buf
			std::getline(is2, data); // Convierte a String y guarda en data
			std::istringstream mi_stream2(data); // Input Stream (letura) al string data
			mi_stream2 >> command;

			//Lee el estado del escenario
			if(command == "state")
			{
				std::cout << "Ha llegado: " << command << std::endl;
				std::stringstream state;

				while(!mi_stream2.eof()) {
					std::string a;
					mi_stream2 >> a;
					state << a << " ";
				}
				std::cout << state.str() << std::endl;

				boost::archive::text_iarchive ia(state);
				{
					// mutex:
					// segfaults if it draws during a state update (drawing +
					// incomplete state is fatal)
					boost::mutex::scoped_lock lock(state_mutex);
					ia >> mi_bots;
					paso++;
					std::cout << "\x1B[2J\x1B[H";
					pinta_escenario(mi_bots, paso);
				}
			}
			else
			{
				std::cout << "GAME OVER " << command << std::endl;
			}

		}

		//mi_bots.step();
		//paso++;

		mi_bots.for_each_bot([&] ( bot & b ) {
			//std::cout << b.get_team() << "\t"; // std::endl;
			//std::cout << b.get_x() << "\t";
			//std::cout << b.get_y() << "\t";
			//std::cout << b.get_energy() << "\t";
			//std::cout << std::endl;

			//mi_bots.can_move( b, bot::W);

			//if ( b.get_team() == 0)
			//{
			//	b.try_to_do(bot::W);
			//}

			std::stringstream stream;
            stream << "move " << b.get_x() << " " << b.get_y() << " " << bot::W;
            //stream << "gameover";
            send(*socket, stream.str());

		});

		//pinta_escenario(mis_bots_ord);
		//pinta_escenario(mi_bots, paso);

		while ( std::cin.get() != ' ' );
		//std::cout << "\x1B[2J\x1B[H";

	}
	return 0;
}
<commit_msg>antes de read asinc<commit_after>#include <iostream>
#include "bots.h"
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>

using boost::asio::ip::tcp;

void async_send(tcp::socket &socket, const std::string & str)
{
    boost::asio::async_write(socket, boost::asio::buffer(str + "\n"), boost::asio::transfer_all());
}

void pinta_escenario( bots mis_bots, int paso, int cols, int filas)
{
	std::cout << "Paso : " << paso << std::endl;

	for ( int col = 0; col < cols + 2; col++ ) // Primera fila de X
        	std::cout << 'X';
	std::cout << std::endl;
	for ( int fila = 0; fila < filas; fila++ ) //! Recorre toda la altura
        {
		std::cout << 'X'; // Primera X de la fila
		for ( int col = 0; col < cols; col++ ) // Espacios en blanco
		{
			bot * pos_bot = mis_bots.find_at( { col, fila} );
			if ( pos_bot == nullptr )
                        	std::cout << ' ';
			else
				std::cout << pos_bot->get_team();
		}
		std::cout << 'X'; //! Espacios de 1a altura - fila
                std::cout << std::endl;
        }
	for ( int col = 0; col < cols + 2; col++ ) // Primera fila de X
                        std::cout << 'X';
	std::cout << std::endl;
}

int main (int argc, char* argv[])
{
	boost::asio::io_service io_service; // Inicia comunicaciones
	tcp::resolver resolver(io_service); // Resuelve la comunicación
	auto endpoint_iterator = resolver.resolve({ argv[1], argv[2] }); // Iterador hacia puerto y dirección
	std::shared_ptr<tcp::socket> socket(new tcp::socket(io_service)); // Puntero compartido hacia el socket
	boost::asio::connect(*socket, endpoint_iterator); // Conexión

	io_service.run();

	int paso = 0;

	// Variables de comunicacion
	boost::mutex state_mutex;
	bool gameover = false;
	bool connected = false;
	bot::team_id id = 6666;
	bot::field_size field_width;
	bot::field_size field_height;
	int win_width = 500;
	int win_height = 500;
	// Mi instancia de la clase bots
	bots mi_bots = bots(field_width, field_height); // Tamaño del campo 10x10, usa la pila
	//Lee el bufer de comunicaciones
	boost::asio::streambuf buf;
	read_until(*socket, buf, "\n");
	std::string data;
	std::istream is(&buf);
	std::getline(is, data);
	std::istringstream mi_stream(data);
	// Lee la primer palabra
	std::string command;
	mi_stream >> command;
	// Lee la información inicial
	if(command == "welcome")
	{
        mi_stream >> id;
        std::cout << "team id: " << id << std::endl;
        //ai.set_team(id);
        mi_stream >> field_width;
        mi_stream >> field_height;
        mi_bots.set_size(field_width, field_height);
        std::cout << "setting field: " << field_width << " x " << field_height << std::endl;
    }

	while (!gameover)
	{
		{
			read_until(*socket, buf, "\n"); //Leo el bufer
			std::istream is2(&buf); // Input Stream (lectura) a la clase buf
			std::getline(is2, data); // Convierte a String y guarda en data
			std::istringstream mi_stream2(data); // Input Stream (letura) al string data
			mi_stream2 >> command;

			//Lee el estado del escenario
			if(command == "state")
			{
				std::stringstream state;

				while(!mi_stream2.eof()) {
					std::string a;
					mi_stream2 >> a;
					state << a << " ";
				}
				std::cout << state.str() << std::endl;

				boost::archive::text_iarchive ia(state);
				{
					boost::mutex::scoped_lock lock(state_mutex);
					ia >> mi_bots;
					paso++;
					std::cout << "\x1B[2J\x1B[H"; // Limpia pantalla
					pinta_escenario(mi_bots, paso, field_width, field_height);
				}
			}
			else
			{
				std::cout << "GAME OVER " << command << std::endl;
			}

		}

		mi_bots.for_each_bot([&] ( bot & b ) {
		std::stringstream stream;
		// Envia movimeinte del bot
        stream << "move " << b.get_x() << " " << b.get_y() << " " << bot::W;
        async_send(*socket, stream.str());

		});

		//while ( std::cin.get() != ' ' ); // Espera entrada espacio
	}
	return 0;
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	R8C グループ・A/D 制御
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2015, 2017 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/R8C/blob/master/LICENSE
*/
//=====================================================================//
#include "common/vect.h"
#include "M120AN/adc.hpp"
#include "M120AN/intr.hpp"
#include "M120AN/system.hpp"

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  A/D 制御クラス
		@param[in]	TASK	A/D 変換終了時起動タスク
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class TASK>
	class adc_io {

		static TASK	task_;
		static volatile uint8_t intr_count_;

	public:
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  チャネル・タイプ
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class cnv_type : uint8_t {
			CH0,		//< チャネル０のみ
			CH1,		//< チャネル１のみ
			CH0_CH1		//< ０，１チャネル
		};

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  チャネル・グループ
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class ch_grp : uint8_t {
			AN0_AN1,	//< AN0, AN1
			AN2_AN3,	//< AN2, AN3
			AN4_AN7		//< AN4, AN7
		};

		static inline void itask() {
			++intr_count_;
			task_();
			// IR 関係フラグは必ず mov 命令で・・
			volatile uint8_t r = ADICSR();
			ADICSR = 0x00;
		}

	private:
		uint8_t	level_;
		uint8_t	count_;

		// ※同期が必要なら、実装する
		void sleep_() const {
			asm("nop");
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		adc_io() : level_(0), count_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  変換開始
			@param[in]	ct		変換タイプ
			@param[in]	grp		グループ
			@param[in]	cycle	繰り返し変換の場合「true」
			@param[in]	level	割り込みレベル（０の場合割り込みを使用しない）
		*/
		//-----------------------------------------------------------------//
		void start(cnv_type ct, ch_grp cg, bool cycle, uint8_t level = 0)
		{
			level_ = level;

			MSTCR.MSTAD = 0;

			ADCON0.ADST = 0;

			uint8_t md = 0;
			if(ct == cnv_type::CH0_CH1) md = 2;
			if(cycle) ++md;
			ADMOD = ADMOD.CKS.b(3) | ADMOD.MD.b(md);

			uint8_t chn = 0;
			if(ct == cnv_type::CH1) chn = 1;
			ADINSEL = ADINSEL.CH0.b(chn) | ADINSEL.ADGSEL.b(static_cast<uint8_t>(cg));

			ILVL7.B01 = level_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  変換開始
			@param[in]	f	変換停止の場合「false」
		*/
		//-----------------------------------------------------------------//
		void scan(bool f = 1) {
			count_ = intr_count_;
			if(f && level_ > 0) {
				ADICSR.ADIE = 1;
			}
			ADCON0.ADST = f;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  変換終了検査
			@return 変換終了なら「true」
		*/
		//-----------------------------------------------------------------//
		bool get_state() const {
			if(level_ == 0) {
				bool f = ADICSR.ADF();
				if(f) ADICSR.ADF = 0;
				return f;
			} else {
				return count_ != intr_count_;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  変換終了を同期
		*/
		//-----------------------------------------------------------------//
		void sync() const {
			while(!get_state()) sleep_();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  変換結果の取得
			@param[in]	chanel	チャネル（０、１）
			@return 変換結果
		*/
		//-----------------------------------------------------------------//
		uint16_t get_value(bool chanel) const {
			if(chanel) {
				return AD1();
			} else {
				return AD0();
			}
		}
	};

	// スタティック実態定義
	template<class TASK>
	TASK adc_io<TASK>::task_;

	template<class TASK>
	volatile uint8_t adc_io<TASK>::intr_count_ = 0;
}
<commit_msg>Update: cleanup<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	R8C グループ・A/D 制御
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2015, 2017 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/R8C/blob/master/LICENSE
*/
//=====================================================================//
#include "common/vect.h"
#include "M120AN/adc.hpp"
#include "M120AN/intr.hpp"
#include "M120AN/system.hpp"

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  A/D 制御クラス
		@param[in]	TASK	A/D 変換終了時起動タスク
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class TASK>
	class adc_io {

		static TASK	task_;
		static volatile uint8_t intr_count_;

	public:
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  チャネル・タイプ
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class CH_TYPE : uint8_t {
			CH0,		//< チャネル０のみ
			CH1,		//< チャネル１のみ
			CH0_CH1		//< ０，１チャネル
		};

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  チャネル・グループ
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class CH_GROUP : uint8_t {
			AN0_AN1,	//< AN0, AN1
			AN2_AN3,	//< AN2, AN3
			AN4_AN7		//< AN4, AN7
		};

		static inline void itask() {
			++intr_count_;
			task_();
			// IR 関係フラグは必ず mov 命令で・・
			volatile uint8_t r = ADICSR();
			ADICSR = 0x00;
		}

	private:
		uint8_t	level_;
		uint8_t	count_;

		// ※同期が必要なら、実装する
		void sleep_() const {
			asm("nop");
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		adc_io() : level_(0), count_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  変換開始
			@param[in]	ct		チャネル・タイプ
			@param[in]	grp		チャネル・グループ
			@param[in]	cycle	繰り返し変換の場合「true」
			@param[in]	level	割り込みレベル（０の場合割り込みを使用しない）
		*/
		//-----------------------------------------------------------------//
		void start(CH_TYPE ct, CH_GROUP cg, bool cycle, uint8_t level = 0)
		{
			level_ = level;

			MSTCR.MSTAD = 0;

			ADCON0.ADST = 0;

			uint8_t md = 0;
			if(ct == CH_TYPE::CH0_CH1) md = 2;
			if(cycle) ++md;
			ADMOD = ADMOD.CKS.b(3) | ADMOD.MD.b(md);

			uint8_t chn = 0;
			if(ct == CH_TYPE::CH1) chn = 1;
			ADINSEL = ADINSEL.CH0.b(chn) | ADINSEL.ADGSEL.b(static_cast<uint8_t>(cg));

			ILVL7.B01 = level_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  変換開始
			@param[in]	f	変換停止の場合「false」
		*/
		//-----------------------------------------------------------------//
		void scan(bool f = 1) {
			count_ = intr_count_;
			if(f && level_ > 0) {
				ADICSR.ADIE = 1;
			}
			ADCON0.ADST = f;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  変換終了検査
			@return 変換終了なら「true」
		*/
		//-----------------------------------------------------------------//
		bool get_state() const {
			if(level_ == 0) {
				bool f = ADICSR.ADF();
				if(f) ADICSR.ADF = 0;
				return f;
			} else {
				return count_ != intr_count_;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  変換終了を同期
		*/
		//-----------------------------------------------------------------//
		void sync() const {
			while(!get_state()) sleep_();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  変換結果の取得
			@param[in]	chanel	チャネル（０、１）
			@return 変換結果
		*/
		//-----------------------------------------------------------------//
		uint16_t get_value(bool chanel) const {
			if(chanel) {
				return AD1();
			} else {
				return AD0();
			}
		}
	};

	// スタティック実態定義
	template<class TASK>
	TASK adc_io<TASK>::task_;

	template<class TASK>
	volatile uint8_t adc_io<TASK>::intr_count_ = 0;
}
<|endoftext|>


<commit_before>
TEST_CASE("Semaphores.", "[semaphore]")
{
    SECTION("Local Semaphore.")
    {
        const auto initCount  = 2u;
        const auto maxCount   = 3u;

        auto semaphore = oqpi::semaphore("", oqpi::sync_object_creation_options::open_or_create, initCount, maxCount);
        REQUIRE(semaphore.isValid());

        auto success = semaphore.tryWait(); // semaphoreCount = 1.
        REQUIRE(success);

        success = semaphore.tryWait(); // semaphoreCount = 0.
        REQUIRE(success);

        success = semaphore.tryWait(); // semaphoreCount = 0.
        REQUIRE(!success);

        semaphore.notifyOne(); // Semaphore count = 1.

        success = semaphore.tryWait(); // semaphoreCount = 0.
        REQUIRE(success);

        semaphore.notifyAll(); // semaphoreCount = 3.

        success = semaphore.tryWait() // semaphoreCount = 2.
            && semaphore.tryWait() // semaphoreCount = 1.
            && semaphore.tryWait(); // semaphoreCount = 0.

        REQUIRE(success);
    }
    SECTION("Global Semaphore.")
    {
        const auto initCount  = 2u;
        const auto maxCount   = 3u;

        auto semaphore = oqpi::global_semaphore("Global\\oqpiTestSemaphore", oqpi::sync_object_creation_options::open_existing);
        REQUIRE(!semaphore.isValid());

        semaphore = oqpi::global_semaphore("Global\\oqpiTestSemaphore", oqpi::sync_object_creation_options::create_if_nonexistent, initCount, maxCount);
        REQUIRE(semaphore.isValid());

        auto semaphore2 = oqpi::global_semaphore("Global\\oqpiTestSemaphore", oqpi::sync_object_creation_options::open_existing);
        REQUIRE(semaphore2.isValid());

        REQUIRE(semaphore.getName() == semaphore2.getName());

        auto success = semaphore.tryWait(); // semaphoreCount = 1.
        REQUIRE(success);

        success = semaphore2.tryWait(); // semaphoreCount = 0.
        REQUIRE(success);

        success = semaphore2.tryWait(); // semaphoreCount = 0.
        REQUIRE(!success);

        semaphore2.notifyOne(); // Semaphore count = 1.

        success = semaphore.tryWait(); // semaphoreCount = 0.
        REQUIRE(success);

        semaphore.notifyAll(); // semaphoreCount = 3.

        success = semaphore2.tryWait() // semaphoreCount = 2.
            && semaphore2.tryWait() // semaphoreCount = 1.
            && semaphore2.tryWait(); // semaphoreCount = 0.

        REQUIRE(success);
    }
}
<commit_msg>Update the names of semaphores in tests to make them valid in posix<commit_after>
TEST_CASE("Semaphores.", "[semaphore]")
{
    SECTION("Local Semaphore.")
    {
        const auto initCount  = 2u;
        const auto maxCount   = 3u;

        auto semaphore = oqpi::semaphore("", oqpi::sync_object_creation_options::open_or_create, initCount, maxCount);
        REQUIRE(semaphore.isValid());

        auto success = semaphore.tryWait(); // semaphoreCount = 1.
        REQUIRE(success);

        success = semaphore.tryWait(); // semaphoreCount = 0.
        REQUIRE(success);

        success = semaphore.tryWait(); // semaphoreCount = 0.
        REQUIRE(!success);

        semaphore.notifyOne(); // Semaphore count = 1.

        success = semaphore.tryWait(); // semaphoreCount = 0.
        REQUIRE(success);

        semaphore.notifyAll(); // semaphoreCount = 3.

        success = semaphore.tryWait() // semaphoreCount = 2.
            && semaphore.tryWait() // semaphoreCount = 1.
            && semaphore.tryWait(); // semaphoreCount = 0.

        REQUIRE(success);
    }
    SECTION("Global Semaphore.")
    {
        const auto initCount  = 2u;
        const auto maxCount   = 3u;

        auto semaphore = oqpi::global_semaphore("/Global\\oqpiTestSemaphore", oqpi::sync_object_creation_options::open_existing);
        REQUIRE(!semaphore.isValid());

        semaphore = oqpi::global_semaphore("/Global\\oqpiTestSemaphore", oqpi::sync_object_creation_options::create_if_nonexistent, initCount, maxCount);
        REQUIRE(semaphore.isValid());

        auto semaphore2 = oqpi::global_semaphore("/Global\\oqpiTestSemaphore", oqpi::sync_object_creation_options::open_existing);
        REQUIRE(semaphore2.isValid());

        REQUIRE(semaphore.getName() == semaphore2.getName());

        auto success = semaphore.tryWait(); // semaphoreCount = 1.
        REQUIRE(success);

        success = semaphore2.tryWait(); // semaphoreCount = 0.
        REQUIRE(success);

        success = semaphore2.tryWait(); // semaphoreCount = 0.
        REQUIRE(!success);

        semaphore2.notifyOne(); // Semaphore count = 1.

        success = semaphore.tryWait(); // semaphoreCount = 0.
        REQUIRE(success);

        semaphore.notifyAll(); // semaphoreCount = 3.

        success = semaphore2.tryWait() // semaphoreCount = 2.
            && semaphore2.tryWait() // semaphoreCount = 1.
            && semaphore2.tryWait(); // semaphoreCount = 0.

        REQUIRE(success);
    }
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	R8C グループ・タイマー RB I/O 制御 @n
			Copyright 2015 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/vect.h"
#include "system.hpp"
#include "intr.hpp"
#include "timer_rb.hpp"

/// F_CLK はタイマー周期計算で必要で、設定が無いとエラーにします。
#ifndef F_CLK
#  error "trb_io.hpp requires F_CLK to be defined"
#endif

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  タイマー RB I/O 制御クラス
		@param[in]	TASK 割り込み内で実行されるクラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class TASK, typename CNT>
	class trb_io {
	public:
		static TASK task_;

		static volatile CNT	count_;

		static INTERRUPT_FUNC void itask() {
			++count_;
			task_();
			// IR 関係フラグは必ず mov 命令で・・
			volatile uint8_t r = TRBIR();
			TRBIR = TRBIR.TRBIF.b(false) | (r & TRBIR.TRBIE.b());
		}

		uint16_t	limit_;

	private:

		// ※同期が必要なら、実装する
		void sleep_() const {
			asm("nop");
		}

		CNT get_timer_() const {
			return TRBPRE() | (TRBPR() << 8);
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		__attribute__ ((section (".text")))
		trb_io() : limit_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  タイマー開始
			@param[in]	hz	周期（周波数）
			@param[in]	ir_lvl	割り込みレベル（０の場合割り込みを使用しない）
			@return 設定範囲を超えたら「false」
		*/
		//-----------------------------------------------------------------//
		bool start_timer(uint16_t hz, uint8_t ir_lvl = 0) {
			MSTCR.MSTTRB = 0;  // モジュールスタンバイ解除

			TRBCR.TSTART = 0;

			uint32_t tn = F_CLK / hz;
			uint8_t div = 0;
			while(tn > 65536) {
				tn >>= 1;
				++div;
				if(div == 4) {
					tn >>= 1;
				}
				if(div >= 7) return false;
			}
			if(tn) --tn;
			if(tn == 0) return false;

			static const uint8_t tbl[8] = {
				0b000, 0b011, 0b100, 0b001, 0b101, 0b110, 0b111
			};

			// タイマーモード、１６ビットタイマー
			TRBMR = TRBMR.TMOD.b(0) | TRBMR.TCNT16.b() | TRBMR.TCK.b(tbl[div]);

			limit_  = tn;
			TRBPRE = tn & 0xff;
			TRBPR  = tn >> 8;

			ILVLC.B01 = ir_lvl;
			if(ir_lvl) {
				TRBIR = TRBIR.TRBIE.b();
			} else {
				TRBIR = TRBIR.TRBIE.b(false);
			}

			TRBCR.TSTART = 1;

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  タイマー同期
		*/
		//-----------------------------------------------------------------//
		void sync() const {
			if(TRBIR.TRBIE()) {
				volatile CNT n = count_;
				while(n == count_) sleep_();
			} else {
				while(TRBIR.TRBIF() == 0) sleep_();
				TRBIR.TRBIF = 0;
				++count_;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  カウント値の取得
			@return カウント値
		*/
		//-----------------------------------------------------------------//
		CNT get_count() const { return count_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  リミット値の取得（ダウンカウントレジスタの設定値）
			@return リミット値
		*/
		//-----------------------------------------------------------------//
		uint16_t get_limit() const { return limit_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  タイマー値の取得（クロック毎にダウンカウントされる値）
			@return タイマー値
		*/
		//-----------------------------------------------------------------//
		uint16_t get_timer() const {
			uint16_t n = get_timer_();
			// 桁上がりを考慮して、連続して同じ値が読まれるまでループする。
			while(n != get_timer_()) {
				n = get_timer_();
			}
			return n;
		}

	};

	// スタティック実態定義
	template<class TASK, typename CNT>
	TASK trb_io<TASK, CNT>::task_;
	template<class TASK, typename CNT>
	volatile CNT trb_io<TASK, CNT>::count_;
}
<commit_msg>update task_type<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	R8C グループ・タイマー RB I/O 制御 @n
			Copyright 2015 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/vect.h"
#include "system.hpp"
#include "intr.hpp"
#include "timer_rb.hpp"

/// F_CLK はタイマー周期計算で必要で、設定が無いとエラーにします。
#ifndef F_CLK
#  error "trb_io.hpp requires F_CLK to be defined"
#endif

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  タイマー RB I/O 制御クラス
		@param[in]	TASK 割り込み内で実行されるクラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class TASK, typename CNT>
	class trb_io {
	public:
		typedef TASK task_type;

		static TASK task_;

		static volatile CNT	count_;

		static INTERRUPT_FUNC void itask() {
			++count_;
			task_();
			// IR 関係フラグは必ず mov 命令で・・
			volatile uint8_t r = TRBIR();
			TRBIR = TRBIR.TRBIF.b(false) | (r & TRBIR.TRBIE.b());
		}

		uint16_t	limit_;

	private:

		// ※同期が必要なら、実装する
		void sleep_() const {
			asm("nop");
		}

		CNT get_timer_() const {
			return TRBPRE() | (TRBPR() << 8);
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		__attribute__ ((section (".text")))
		trb_io() : limit_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  タイマー開始
			@param[in]	hz	周期（周波数）
			@param[in]	ir_lvl	割り込みレベル（０の場合割り込みを使用しない）
			@return 設定範囲を超えたら「false」
		*/
		//-----------------------------------------------------------------//
		bool start_timer(uint16_t hz, uint8_t ir_lvl = 0) {
			MSTCR.MSTTRB = 0;  // モジュールスタンバイ解除

			TRBCR.TSTART = 0;

			uint32_t tn = F_CLK / hz;
			uint8_t div = 0;
			while(tn > 65536) {
				tn >>= 1;
				++div;
				if(div == 4) {
					tn >>= 1;
				}
				if(div >= 7) return false;
			}
			if(tn) --tn;
			if(tn == 0) return false;

			static const uint8_t tbl[8] = {
				0b000, 0b011, 0b100, 0b001, 0b101, 0b110, 0b111
			};

			// タイマーモード、１６ビットタイマー
			TRBMR = TRBMR.TMOD.b(0) | TRBMR.TCNT16.b() | TRBMR.TCK.b(tbl[div]);

			limit_  = tn;
			TRBPRE = tn & 0xff;
			TRBPR  = tn >> 8;

			ILVLC.B01 = ir_lvl;
			if(ir_lvl) {
				TRBIR = TRBIR.TRBIE.b();
			} else {
				TRBIR = TRBIR.TRBIE.b(false);
			}

			TRBCR.TSTART = 1;

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  タイマー同期
		*/
		//-----------------------------------------------------------------//
		void sync() const {
			if(TRBIR.TRBIE()) {
				volatile CNT n = count_;
				while(n == count_) sleep_();
			} else {
				while(TRBIR.TRBIF() == 0) sleep_();
				TRBIR.TRBIF = 0;
				++count_;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  カウント値の取得
			@return カウント値
		*/
		//-----------------------------------------------------------------//
		CNT get_count() const { return count_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  リミット値の取得（ダウンカウントレジスタの設定値）
			@return リミット値
		*/
		//-----------------------------------------------------------------//
		uint16_t get_limit() const { return limit_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  タイマー値の取得（クロック毎にダウンカウントされる値）
			@return タイマー値
		*/
		//-----------------------------------------------------------------//
		uint16_t get_timer() const {
			uint16_t n = get_timer_();
			// 桁上がりを考慮して、連続して同じ値が読まれるまでループする。
			while(n != get_timer_()) {
				n = get_timer_();
			}
			return n;
		}

	};

	// スタティック実態定義
	template<class TASK, typename CNT>
	TASK trb_io<TASK, CNT>::task_;
	template<class TASK, typename CNT>
	volatile CNT trb_io<TASK, CNT>::count_;
}
<|endoftext|>


<commit_before>#include "testsettings.hpp"
#ifdef TEST_UTIL_ERROR

#include <realm/util/basic_system_errors.hpp>

#include "test.hpp"

using namespace realm;
using namespace realm::util;

// Test independence and thread-safety
// -----------------------------------
//
// All tests must be thread safe and independent of each other. This
// is required because it allows for both shuffling of the execution
// order and for parallelized testing.
//
// In particular, avoid using std::rand() since it is not guaranteed
// to be thread safe. Instead use the API offered in
// `test/util/random.hpp`.
//
// All files created in tests must use the TEST_PATH macro (or one of
// its friends) to obtain a suitable file system path. See
// `test/util/test_path.hpp`.
//
//
// Debugging and the ONLY() macro
// ------------------------------
//
// A simple way of disabling all tests except one called `Foo`, is to
// replace TEST(Foo) with ONLY(Foo) and then recompile and rerun the
// test suite. Note that you can also use filtering by setting the
// environment varible `UNITTEST_FILTER`. See `README.md` for more on
// this.
//
// Another way to debug a particular test, is to copy that test into
// `experiments/testcase.cpp` and then run `sh build.sh
// check-testcase` (or one of its friends) from the command line.

TEST(BasicSystemErrors_Category)
{
    std::error_code err = make_error_code(error::operation_aborted);
    CHECK_EQUAL(err.category().name(), "realm.basic_system");
}

TEST(BasicSystemErrors_Messages)
{
    {
        std::error_code err = make_error_code(error::address_family_not_supported);
        CHECK_GREATER(std::strlen(err.message().c_str()), 0);
        CHECK(err.message() != "Unknown error");
    }
    {
        std::error_code err = make_error_code(error::invalid_argument);
        CHECK_GREATER(std::strlen(err.message().c_str()), 0);
        CHECK(err.message() != "Unknown error");
    }
    {
        std::error_code err = make_error_code(error::no_memory);
        CHECK_GREATER(std::strlen(err.message().c_str()), 0);
        CHECK(err.message() != "Unknown error");
    }
    {
        std::error_code err = make_error_code(error::operation_aborted);
        CHECK_GREATER(std::strlen(err.message().c_str()), 0);
        CHECK(err.message() != "Unknown error");
    }

    // Ensure that if we pass an unknown error code, we get some error reporting
    // This may potentially pass on some operating system. If this test starts failing, simply change the
    // magic number below.
    {
        std::error_code err = make_error_code(static_cast<error::basic_system_errors>(64532));
        CHECK_EQUAL(err.message(), "Unknown error 64532");
    }
}

#endif // TEST_BASIC_SYSTEM_ERRORS
<commit_msg>Updated tests<commit_after>#include "testsettings.hpp"
#ifdef TEST_UTIL_ERROR

#include <realm/util/basic_system_errors.hpp>

#include "test.hpp"

using namespace realm;
using namespace realm::util;

// Test independence and thread-safety
// -----------------------------------
//
// All tests must be thread safe and independent of each other. This
// is required because it allows for both shuffling of the execution
// order and for parallelized testing.
//
// In particular, avoid using std::rand() since it is not guaranteed
// to be thread safe. Instead use the API offered in
// `test/util/random.hpp`.
//
// All files created in tests must use the TEST_PATH macro (or one of
// its friends) to obtain a suitable file system path. See
// `test/util/test_path.hpp`.
//
//
// Debugging and the ONLY() macro
// ------------------------------
//
// A simple way of disabling all tests except one called `Foo`, is to
// replace TEST(Foo) with ONLY(Foo) and then recompile and rerun the
// test suite. Note that you can also use filtering by setting the
// environment varible `UNITTEST_FILTER`. See `README.md` for more on
// this.
//
// Another way to debug a particular test, is to copy that test into
// `experiments/testcase.cpp` and then run `sh build.sh
// check-testcase` (or one of its friends) from the command line.

TEST(BasicSystemErrors_Category)
{
    std::error_code err = make_error_code(error::operation_aborted);
    CHECK_EQUAL(err.category().name(), "realm.basic_system");
}

TEST(BasicSystemErrors_Messages)
{
    {
        std::error_code err = make_error_code(error::address_family_not_supported);
        CHECK_GREATER(err.message().length(), 0);
    }
    {
        std::error_code err = make_error_code(error::invalid_argument);
        CHECK_GREATER(err.message().length(), 0);
    }
    {
        std::error_code err = make_error_code(error::no_memory);
        CHECK_GREATER(err.message().length(), 0);
    }
    {
        std::error_code err = make_error_code(error::operation_aborted);
        CHECK_GREATER(err.message().length(), 0);
    }

    // Ensure that if we pass an unknown error code, we get some error reporting
    // This may potentially pass on some operating system. If this test starts failing, simply change the
    // magic number below.
    {
        std::error_code err = make_error_code(static_cast<error::basic_system_errors>(64532));
        CHECK_GREATER(err.message().length(), 0);
    }
}

#endif // TEST_BASIC_SYSTEM_ERRORS
<|endoftext|>


<commit_before>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "APIGrammar.h"
#include "RequestHandler.h"
#include "Http/Request.h"

#include "../DataStructures/JSONContainer.h"
#include "../Library/OSRM.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"

#include <osrm/Reply.h>
#include <osrm/RouteParameters.h>

#include <ctime>

#include <algorithm>
#include <iostream>

RequestHandler::RequestHandler() : routing_machine(nullptr) {}

void RequestHandler::handle_request(const http::Request &req, http::Reply &reply)
{
    // parse command
    try
    {
        std::string request;
        URIDecode(req.uri, request);

        // deactivated as GCC apparently does not implement that, not even in 4.9
        // std::time_t t = std::time(nullptr);
        // SimpleLogger().Write() << std::put_time(std::localtime(&t), "%m-%d-%Y %H:%M:%S") <<
        //     " " << req.endpoint.to_string() << " " <<
        //     req.referrer << ( 0 == req.referrer.length() ? "- " :" ") <<
        //     req.agent << ( 0 == req.agent.length() ? "- " :" ") << request;

        time_t ltime;
        struct tm *Tm;

        ltime = time(nullptr);
        Tm = localtime(&ltime);

        SimpleLogger().Write() << (Tm->tm_mday < 10 ? "0" : "") << Tm->tm_mday << "-"
                               << (Tm->tm_mon + 1 < 10 ? "0" : "") << (Tm->tm_mon + 1) << "-"
                               << 1900 + Tm->tm_year << " " << (Tm->tm_hour < 10 ? "0" : "")
                               << Tm->tm_hour << ":" << (Tm->tm_min < 10 ? "0" : "") << Tm->tm_min
                               << ":" << (Tm->tm_sec < 10 ? "0" : "") << Tm->tm_sec << " "
                               << req.endpoint.to_string() << " " << req.referrer
                               << (0 == req.referrer.length() ? "- " : " ") << req.agent
                               << (0 == req.agent.length() ? "- " : " ") << request;

        RouteParameters route_parameters;
        APIGrammarParser api_parser(&route_parameters);

        auto it = request.begin();
        const bool result = boost::spirit::qi::parse(it, request.end(), api_parser);

        if (!result || (it != request.end()))
        {
            reply = http::Reply::StockReply(http::Reply::badRequest);
            reply.content.clear();
            const int position = std::distance(request.begin(), it);
            JSON::Object json_result;
            json_result.values["status"] = 400;
            std::string message = ("Query string malformed close to position " + IntToString(position));
            json_result.values["status_message"] = message;
            JSON::render(reply.content, json_result);
        }
        else
        {
            // parsing done, lets call the right plugin to handle the request
            BOOST_ASSERT_MSG(routing_machine != nullptr, "pointer not init'ed");

            if (!route_parameters.jsonp_parameter.empty())
            {
                const std::string json_p = (route_parameters.jsonp_parameter + "(");
                reply.content.insert(reply.content.end(), json_p.begin(), json_p.end());
            }
            routing_machine->RunQuery(route_parameters, reply);

            // set headers, still ugly and should be reworked
            reply.headers.resize(3);
            if ("gpx" == route_parameters.output_format)
            {
                reply.headers[1].name = "Content-Type";
                reply.headers[1].value = "application/gpx+xml; charset=UTF-8";
                reply.headers[2].name = "Content-Disposition";
                reply.headers[2].value = "attachment; filename=\"route.gpx\"";
            }
            else if (route_parameters.jsonp_parameter.empty())
            {
                reply.headers[1].name = "Content-Type";
                reply.headers[1].value = "application/x-javascript; charset=UTF-8";
                reply.headers[2].name = "Content-Disposition";
                reply.headers[2].value = "inline; filename=\"response.json\"";
            }
            else
            {
                reply.content.push_back(')');
                reply.headers[1].name = "Content-Type";
                reply.headers[1].value = "text/javascript; charset=UTF-8";
                reply.headers[2].name = "Content-Disposition";
                reply.headers[2].value = "inline; filename=\"response.js\"";
            }
            reply.headers[0].name = "Content-Length";
            reply.headers[0].value = IntToString(reply.content.size());
            return;
        }
    }
    catch (const std::exception &e)
    {
        reply = http::Reply::StockReply(http::Reply::internalServerError);
        SimpleLogger().Write(logWARNING) << "[server error] code: " << e.what()
                                         << ", uri: " << req.uri;
        return;
    }
}

void RequestHandler::RegisterRoutingMachine(OSRM *osrm) { routing_machine = osrm; }
<commit_msg>refactor RequestHandler to remove code duplication, nested blocks and object copies<commit_after>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "APIGrammar.h"
#include "RequestHandler.h"
#include "Http/Request.h"

#include "../DataStructures/JSONContainer.h"
#include "../Library/OSRM.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"

#include <osrm/Reply.h>
#include <osrm/RouteParameters.h>

#include <ctime>

#include <algorithm>
#include <iostream>

RequestHandler::RequestHandler() : routing_machine(nullptr) {}

void RequestHandler::handle_request(const http::Request &req, http::Reply &reply)
{
    // parse command
    try
    {
        std::string request;
        URIDecode(req.uri, request);

        // deactivated as GCC apparently does not implement that, not even in 4.9
        // std::time_t t = std::time(nullptr);
        // SimpleLogger().Write() << std::put_time(std::localtime(&t), "%m-%d-%Y %H:%M:%S") <<
        //     " " << req.endpoint.to_string() << " " <<
        //     req.referrer << ( 0 == req.referrer.length() ? "- " :" ") <<
        //     req.agent << ( 0 == req.agent.length() ? "- " :" ") << request;

        time_t ltime;
        struct tm *Tm;

        ltime = time(nullptr);
        Tm = localtime(&ltime);

        // log timestamp
        SimpleLogger().Write() << (Tm->tm_mday < 10 ? "0" : "") << Tm->tm_mday << "-"
                               << (Tm->tm_mon + 1 < 10 ? "0" : "") << (Tm->tm_mon + 1) << "-"
                               << 1900 + Tm->tm_year << " " << (Tm->tm_hour < 10 ? "0" : "")
                               << Tm->tm_hour << ":" << (Tm->tm_min < 10 ? "0" : "") << Tm->tm_min
                               << ":" << (Tm->tm_sec < 10 ? "0" : "") << Tm->tm_sec << " "
                               << req.endpoint.to_string() << " " << req.referrer
                               << (0 == req.referrer.length() ? "- " : " ") << req.agent
                               << (0 == req.agent.length() ? "- " : " ") << request;

        RouteParameters route_parameters;
        APIGrammarParser api_parser(&route_parameters);

        auto it = request.begin();
        const bool result = boost::spirit::qi::parse(it, request.end(), api_parser);

        // check if the was an error with the request
        if (!result || (it != request.end()))
        {
            reply = http::Reply::StockReply(http::Reply::badRequest);
            reply.content.clear();
            const int position = std::distance(request.begin(), it);
            JSON::Object json_result;
            json_result.values["status"] = 400;
            std::string message = ("Query string malformed close to position " + IntToString(position));
            json_result.values["status_message"] = message;
            JSON::render(reply.content, json_result);
            return;
        }

        // parsing done, lets call the right plugin to handle the request
        BOOST_ASSERT_MSG(routing_machine != nullptr, "pointer not init'ed");

        if (!route_parameters.jsonp_parameter.empty())
        {   // prepend response with jsonp parameter
            const std::string json_p = (route_parameters.jsonp_parameter + "(");
            reply.content.insert(reply.content.end(), json_p.begin(), json_p.end());
        }
        routing_machine->RunQuery(route_parameters, reply);
        if (!route_parameters.jsonp_parameter.empty())
        {   // append brace to jsonp response
            reply.content.push_back(')');
        }

        // set headers
        reply.headers.emplace_back("Content-Length", UintToString(reply.content.size()));
        if ("gpx" == route_parameters.output_format)
        {   // gpx file
            reply.headers.emplace_back("Content-Type", "application/gpx+xml; charset=UTF-8");
            reply.headers.emplace_back("Content-Disposition", "attachment; filename=\"route.gpx\"");
        }
        else if (route_parameters.jsonp_parameter.empty())
        {   // json file
            reply.headers.emplace_back("Content-Type", "application/x-javascript; charset=UTF-8");
            reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.json\"");
        }
        else
        {   // jsonp
            reply.headers.emplace_back("Content-Type", "text/javascript; charset=UTF-8");
            reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.js\"");
        }
    }
    catch (const std::exception &e)
    {
        reply = http::Reply::StockReply(http::Reply::internalServerError);
        SimpleLogger().Write(logWARNING) << "[server error] code: " << e.what()
                                         << ", uri: " << req.uri;
        return;
    }
}

void RequestHandler::RegisterRoutingMachine(OSRM *osrm) { routing_machine = osrm; }
<|endoftext|>


<commit_before><commit_msg>overclock: fix the reboot<commit_after><|endoftext|>


<commit_before>#include "KeyGrabber.h"

#include <string>

KeyGrabber *KeyGrabber::instance = NULL;

KeyGrabber *KeyGrabber::Instance() {
    if (instance == NULL) {
        instance = new KeyGrabber();
    }

    return instance;
}

bool KeyGrabber::Hook() {
    _mouseHook = SetWindowsHookEx(WH_MOUSE_LL,
        LowLevelMouseProc, NULL, NULL);

    _keyHook = SetWindowsHookEx(WH_KEYBOARD_LL,
        LowLevelKeyboardProc, NULL, NULL);

    return _mouseHook && _keyHook;
}

bool KeyGrabber::Unhook() {
    BOOL unMouse = UnhookWindowsHookEx(_mouseHook);
    BOOL unKey = UnhookWindowsHookEx(_keyHook);
    return unMouse && unKey;
}

void KeyGrabber::Grab(HWND hwnd) {
    _updateHwnd = hwnd;
    Hook();
}

bool KeyGrabber::IsModifier(DWORD vk) {
    switch (vk) {
    case VK_MENU:
    case VK_LMENU:
    case VK_RMENU:
    case VK_CONTROL:
    case VK_LCONTROL:
    case VK_RCONTROL:
    case VK_SHIFT:
    case VK_LSHIFT:
    case VK_RSHIFT:
    case VK_LWIN:
    case VK_RWIN:
        return true;
    }
    return false;
}

int KeyGrabber::Modifiers() {
    int mods = 0;
    mods += (GetKeyState(VK_MENU) & 0x8000) << 1;
    mods += (GetKeyState(VK_CONTROL) & 0x8000) << 2;
    mods += (GetKeyState(VK_SHIFT) & 0x8000) << 3;
    mods += (GetKeyState(VK_LWIN) & 0x8000) << 4;
    mods += (GetKeyState(VK_RWIN) & 0x8000) << 4;
    return mods;
}

std::wstring KeyGrabber::ModString(int modifiers) {
    std::wstring str = L"";
    if (modifiers & HKM_MOD_ALT) {
        str += VKToString(VK_MENU) + L" + ";
    }
    if (modifiers & HKM_MOD_CTRL) {
        str += VKToString(VK_CONTROL) + L" + ";
    }
    if (modifiers & HKM_MOD_SHF) {
        str += VKToString(VK_SHIFT) + L" + ";
    }
    if (modifiers & HKM_MOD_WIN) {
        str += L"Win + ";
    }

    return str;
}

std::wstring KeyGrabber::VKToString(
    unsigned int vk, bool extendedKey, bool distinguishLeftRight) {

    BOOL dontCare = distinguishLeftRight ? FALSE : TRUE;
    int extended = extendedKey ? 0x1 : 0x0;

    unsigned int scanCode = MapVirtualKey(vk, MAPVK_VK_TO_VSC);
    scanCode = scanCode << 16;
    scanCode |= extended << 24;
    scanCode |= dontCare << 25;
    wchar_t buf[256] = {};
    GetKeyNameText(scanCode, buf, 256);
    return std::wstring(buf);
}

LRESULT CALLBACK
KeyGrabber::KeyProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode < 0) {
        return CallNextHookEx(NULL, nCode, wParam, lParam);
    }

    if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) {
        KBDLLHOOKSTRUCT *kbInfo = (KBDLLHOOKSTRUCT*) lParam;

        DWORD vk = kbInfo->vkCode;
        if (IsModifier(kbInfo->vkCode)) {
            /* Ignore modifier keys */
            return CallNextHookEx(NULL, nCode, wParam, lParam);
        }

        /* GetKeyNameText expects the following:
         * 16-23: scan code
         *    24: extended key flag
         *    25: 'do not care' bit (don't distinguish between L/R keys) */
        BOOL dontCare = TRUE;
        LONG newlParam;
        newlParam = (kbInfo->scanCode << 16);
        newlParam |= (kbInfo->flags & 0x1) << 24;
        newlParam |= dontCare << 25;
        if (kbInfo->vkCode == VK_RSHIFT) {
            /* For some reason, the right shift key ends up having its extended
             * key flag set and then prints the wrong thing. This doesn't matter
             * here, but we'll fix it in case we need this info later. */
            newlParam ^= 0x1000000;
        }

        wchar_t buf[256] = {};
        GetKeyNameText(newlParam, buf, 256);
        int mods = Modifiers();
        std::wstring modStr = ModString(mods) + buf;
        SetWindowText(_updateHwnd, modStr.c_str());
    }

    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

LRESULT CALLBACK
KeyGrabber::MouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode < 0) {
        return CallNextHookEx(NULL, nCode, wParam, lParam);
    }

    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

LRESULT CALLBACK
KeyGrabber::LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
    return KeyGrabber::instance->MouseProc(nCode, wParam, lParam);
}

LRESULT CALLBACK
KeyGrabber::LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
    return KeyGrabber::instance->KeyProc(nCode, wParam, lParam);
}<commit_msg>Eat valid key combinations to avoid passing them on<commit_after>#include "KeyGrabber.h"

#include <string>

KeyGrabber *KeyGrabber::instance = NULL;

KeyGrabber *KeyGrabber::Instance() {
    if (instance == NULL) {
        instance = new KeyGrabber();
    }

    return instance;
}

bool KeyGrabber::Hook() {
    _mouseHook = SetWindowsHookEx(WH_MOUSE_LL,
        LowLevelMouseProc, NULL, NULL);

    _keyHook = SetWindowsHookEx(WH_KEYBOARD_LL,
        LowLevelKeyboardProc, NULL, NULL);

    return _mouseHook && _keyHook;
}

bool KeyGrabber::Unhook() {
    BOOL unMouse = UnhookWindowsHookEx(_mouseHook);
    BOOL unKey = UnhookWindowsHookEx(_keyHook);
    return unMouse && unKey;
}

void KeyGrabber::Grab(HWND hwnd) {
    _updateHwnd = hwnd;
    Hook();
}

bool KeyGrabber::IsModifier(DWORD vk) {
    switch (vk) {
    case VK_MENU:
    case VK_LMENU:
    case VK_RMENU:
    case VK_CONTROL:
    case VK_LCONTROL:
    case VK_RCONTROL:
    case VK_SHIFT:
    case VK_LSHIFT:
    case VK_RSHIFT:
    case VK_LWIN:
    case VK_RWIN:
        return true;
    }
    return false;
}

int KeyGrabber::Modifiers() {
    int mods = 0;
    mods += (GetKeyState(VK_MENU) & 0x8000) << 1;
    mods += (GetKeyState(VK_CONTROL) & 0x8000) << 2;
    mods += (GetKeyState(VK_SHIFT) & 0x8000) << 3;
    mods += (GetKeyState(VK_LWIN) & 0x8000) << 4;
    mods += (GetKeyState(VK_RWIN) & 0x8000) << 4;
    return mods;
}

std::wstring KeyGrabber::ModString(int modifiers) {
    std::wstring str = L"";
    if (modifiers & HKM_MOD_ALT) {
        str += VKToString(VK_MENU) + L" + ";
    }
    if (modifiers & HKM_MOD_CTRL) {
        str += VKToString(VK_CONTROL) + L" + ";
    }
    if (modifiers & HKM_MOD_SHF) {
        str += VKToString(VK_SHIFT) + L" + ";
    }
    if (modifiers & HKM_MOD_WIN) {
        str += L"Win + ";
    }

    return str;
}

std::wstring KeyGrabber::VKToString(
    unsigned int vk, bool extendedKey, bool distinguishLeftRight) {

    BOOL dontCare = distinguishLeftRight ? FALSE : TRUE;
    int extended = extendedKey ? 0x1 : 0x0;

    unsigned int scanCode = MapVirtualKey(vk, MAPVK_VK_TO_VSC);
    scanCode = scanCode << 16;
    scanCode |= extended << 24;
    scanCode |= dontCare << 25;
    wchar_t buf[256] = {};
    GetKeyNameText(scanCode, buf, 256);
    return std::wstring(buf);
}

LRESULT CALLBACK
KeyGrabber::KeyProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode < 0) {
        return CallNextHookEx(NULL, nCode, wParam, lParam);
    }

    if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) {
        KBDLLHOOKSTRUCT *kbInfo = (KBDLLHOOKSTRUCT*) lParam;

        DWORD vk = kbInfo->vkCode;
        if (IsModifier(kbInfo->vkCode)) {
            /* Ignore modifier keys */
            return CallNextHookEx(NULL, nCode, wParam, lParam);
        }

        /* GetKeyNameText expects the following:
         * 16-23: scan code
         *    24: extended key flag
         *    25: 'do not care' bit (don't distinguish between L/R keys) */
        BOOL dontCare = TRUE;
        LONG newlParam;
        newlParam = (kbInfo->scanCode << 16);
        newlParam |= (kbInfo->flags & 0x1) << 24;
        newlParam |= dontCare << 25;
        if (kbInfo->vkCode == VK_RSHIFT) {
            /* For some reason, the right shift key ends up having its extended
             * key flag set and then prints the wrong thing. This doesn't matter
             * here, but we'll fix it in case we need this info later. */
            newlParam ^= 0x1000000;
        }

        wchar_t buf[256] = {};
        GetKeyNameText(newlParam, buf, 256);
        int mods = Modifiers();
        std::wstring modStr = ModString(mods) + buf;
        SetWindowText(_updateHwnd, modStr.c_str());

        /* Prevent other applications from receiving this event */
        return (LRESULT) 1;
    }

    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

LRESULT CALLBACK
KeyGrabber::MouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode < 0) {
        return CallNextHookEx(NULL, nCode, wParam, lParam);
    }

    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

LRESULT CALLBACK
KeyGrabber::LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
    return KeyGrabber::instance->MouseProc(nCode, wParam, lParam);
}

LRESULT CALLBACK
KeyGrabber::LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
    return KeyGrabber::instance->KeyProc(nCode, wParam, lParam);
}<|endoftext|>


<commit_before><commit_msg>GTK: don't dereference stale ConstrainedWindow pointer.<commit_after><|endoftext|>