<commit_before>//
//  CatenisApiClient.cpp
//  CatenisAPIClientCpp
//
//  Created by Sungwoo Bae on 5/25/17.
//
#include <CatenisApiClient.h>

#include <iostream>
#include <sstream>
#include <stdio.h>
#include <iomanip>
#include <string>
#include <iterator>
#include <map>
#include <ctime>

#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/regex.hpp>

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

int main()
{
    ctn::CtnApiClient *client = new ctn::CtnApiClient("d4XwmaAyRJdSYp4CZuTA", "86ccbaeaff0e6fc9cff989dde3f1b2c2e92761202c40873b07166b7f20b4d7cb682be163305cae4a2f8df557536163416f539b2f6f17fb5f6a20e309fdbec9ce", "beta.catenis.io");

    std::string result;
    client->readMessage("mAsM3cF27vLk6KA4fZoG", result);
    sleep(5);
    //client->logMessage("hey1234", result);
    //client->retrieveMessageContainer("mAsM3cF27vLk6KA4fZoG", result);
    client->sendMessage(ctn::Device("dcdHMFcZh4qmGAmiMg75", false), "hey whats up",result);
    std::cout << result;

    return 0;
}

bool ctn::CtnApiClient::logMessage(std::string message, std::string &data, const MethodOption &option)
{
    std::map<std::string, std::string> params;
    std::map<std::string, std::string> queries;
    boost::property_tree::ptree request_data;

    // write request body
    request_data.put("message", message);
    request_data.put("options.encoding", option.encoding);
    request_data.put("options.encrypt", option.encrypt);
    request_data.put("options.storage", option.storage);

    return httpRequest("POST", "messages/log", params, queries, request_data, data);
}

bool ctn::CtnApiClient::sendMessage(const Device &device, std::string message, std::string &data, const MethodOption &option)
{
    std::map<std::string, std::string> params;
    std::map<std::string, std::string> queries;
    boost::property_tree::ptree request_data;

    // write request body
    request_data.put("targetDevice.id", device.id);
    request_data.put("targetDevice.isProdUniqueId", device.is_prod_uniqueid);
    request_data.put("options.encoding", option.encoding);
    request_data.put("message", message);
    request_data.put("options.encoding", option.encoding);
    request_data.put("options.encrypt", option.encrypt);
    request_data.put("options.storage", option.storage);

    return httpRequest("POST", "messages/send", params, queries, request_data, data);
}

bool ctn::CtnApiClient::readMessage(std::string message_id, std::string &data, const MethodOption &option)
{
    std::map<std::string, std::string> params;
    std::map<std::string, std::string> queries;
    boost::property_tree::ptree request_data;

    params[":messageId"] = message_id;
    queries["encoding"] = option.encoding;

    return httpRequest("GET", "messages/:messageId", params, queries, request_data, data);
}

bool ctn::CtnApiClient::retrieveMessageContainer(std::string message_id, std::string &data)
{
    std::map<std::string, std::string> params;
    std::map<std::string, std::string> queries;
    boost::property_tree::ptree request_data;

    params[":messageId"] = message_id;

    return httpRequest("GET", "messages/:messageId/container", params, queries, request_data, data);
}

// http request
bool ctn::CtnApiClient::httpRequest(std::string verb, std::string methodpath, std::map<std::string, std::string> &params, std::map<std::string, std::string> &queries, boost::property_tree::ptree &request_data, std::string &response_data)
{
    bool success = true;

    // Add entire path
    methodpath = this->root_api_endpoint_ + "/" + methodpath;

    // Process methodpath from params and queries
    for(auto const &data : params)
    {
        methodpath.replace(methodpath.find(data.first), data.first.length(), data.second);
    }
    for(auto const &data : queries)
    {
        // if not first query add "&", else add "?"
        if(data != *queries.begin()) methodpath += "&";
        else methodpath += "?";
        methodpath += data.first + "=" + data.second;
    }

    // Create neccesary headers
    time_t now = std::time(0);
    char iso_time[17];
    strftime(iso_time, sizeof iso_time, "%Y%m%dT%H%M%SZ", gmtime(&now));
    std::map<std::string, std::string> headers;

    headers["host"] = this->host_;
    headers[TIME_STAMP_HDR] = std::string(iso_time);

    std::string payload_json = "";
    // if POST, process payload
    if(verb == "POST")
    {
        std::ostringstream payload_buf;
        write_json (payload_buf, request_data, false);

        // fix boost.ptree bug where it treats all types as string
        boost::regex exp("\"(null|true|false|[0-9]+(\\.[0-9]+)?)\"");
        payload_json = boost::regex_replace(payload_buf.str(), exp, "$1");
    }

    // Create signature and add to header
    signRequest(verb, methodpath, headers, payload_json, now);

    // Set up TCP/IP connection with server and send request
    try
    {
        /*
        // HTTP
        boost::asio::io_service io_service;
        // Get a list of endpoints corresponding to the server name.
        tcp::resolver resolver(io_service);
        tcp::resolver::query query(headers["host"], "http");
        tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);

        // Try each endpoint until we successfully establish a connection.
        tcp::socket socket(io_service);
        boost::asio::connect(socket, endpoint_iterator);
        */

        // HTTPS
        boost::asio::io_service io_service;
        // Get a list of endpoints corresponding to the server name.
        tcp::resolver resolver(io_service);
        tcp::resolver::query query(headers["host"], "https");
        tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);

        // Create context
        boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);

        // Try each endpoint until successful connection
        boost::asio::ssl::stream<tcp::socket> socket(io_service, ctx);
        boost::asio::connect(socket.lowest_layer(), endpoint_iterator);

        // Handshake with server
        socket.set_verify_mode(boost::asio::ssl::verify_none);
        socket.handshake(boost::asio::ssl::stream_base::handshake_type::client);

        // Form the request. We specify the "Connection: close" header so that the
        // server will close the socket after transmitting the response. This will
        // allow us to treat all data up until the EOF as the content.
        boost::asio::streambuf request;
        std::ostream request_stream(&request);

        // Use HTTP 1.0 for now, since persistent connections not needed yet
        request_stream << verb << " " << methodpath << " HTTP/1.0\r\n";
        for(auto const &data : headers)
        {
            request_stream << data.first << ": " << data.second << "\r\n";
        }
        // add extra headers if POST
        if(verb == "POST")
        {
            request_stream << "Content-Type: application/json; charset=utf-8\r\n";
            request_stream << "Content-Length: " << payload_json.length() << "\r\n";
        }
        request_stream << "Connection: close\r\n\r\n";

        // add payload
        request_stream << payload_json;

        //std::cout << &request;

        // Send the request.
        boost::asio::write(socket, request);

        // Check that response is OK.
        boost::asio::streambuf response_buf;
        boost::system::error_code error;

        boost::asio::read_until(socket, response_buf, "\r\n");
        std::istream response_stream(&response_buf);

        std::string http_version;
        response_stream >> http_version;
        unsigned int status_code;
        response_stream >> status_code;
        std::string status_message;
        std::getline(response_stream, status_message);
        if (!response_stream || http_version.substr(0, 5) != "HTTP/")
        {
            std::cout << "Invalid response\n";
            success = false;
        }
        if (status_code != 200)
        {
            std::cout << "Response returned with status code " << status_code << "\n";
            success = false;
        }

        // Read all headers and flush buffer
        int headerSize = boost::asio::read_until(socket, response_buf, "\r\n\r\n");
        response_buf.consume(headerSize);

        // Read until EOF or Short read,
        boost::asio::read(socket, response_buf, boost::asio::transfer_all(), error);
        if (error != boost::asio::error::eof && error !=  boost::system::error_code(ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ), boost::asio::error::get_ssl_category()))
            throw boost::system::system_error(error);

        // Write response data
        // boost::property_tree::json_parser::read_json(response_stream, response_data);
        response_data = std::string(std::istreambuf_iterator<char>(response_stream), {});
    }
    catch (std::exception& e)
    {
        std::cout << "Exception: " << e.what() << "\n";
        success = false;
    }

    return success;
}

// Constructor
ctn::CtnApiClient::CtnApiClient(std::string device_id, std::string api_access_secret, std::string host, std::string environment, bool secure, std::string version)
{
    this->device_id_ = device_id;
    this->api_access_secret_ = api_access_secret;

    this->host_ = host;
    this->subdomain_ = environment;
    this->secure_ = secure;
    this->version_ = version;

    this->root_api_endpoint_ = API_PATH + this->version_;
}

// Generate Signature
void ctn::CtnApiClient::signRequest(std::string verb, std::string endpoint, std::map<std::string, std::string> &headers, std::string payload, time_t now)
{
    std::string timestamp = headers[TIME_STAMP_HDR];
    char date_buffer[9];
    std::string signdate;
    bool use_same_signkey;

    // Use last signkey if date < valid days
    if(this->last_signkey_.length() != 0 && std::difftime(now, this->last_signdate_)/(3600 * 24) < SIGN_VALID_DAYS)
    {
        use_same_signkey = true;
        strftime(date_buffer, sizeof date_buffer, "%Y%m%d", gmtime(&last_signdate_));
        signdate = std::string(date_buffer);
    }
    else
    {
        use_same_signkey = false;
        this->last_signdate_ = now;
        strftime(date_buffer, sizeof date_buffer, "%Y%m%d", gmtime(&now));
        signdate = std::string(date_buffer);
    }

    // 1) Compute conformed request
    std::string conf_req = verb + "\n";
    conf_req += endpoint + "\n";
    for(auto const &data : headers)
    {
        // All header must be in lower case
        conf_req += data.first + ":" + data.second + "\n";
    }
    conf_req += "\n" + hashData(payload) + "\n";

    // 2) Assemble string to sign
    std::string str_to_sign = SIGN_METHOD_ID + "\n";
    str_to_sign += timestamp + "\n";
    std::string scope = signdate + "/" + SCOPE_REQUEST;
    str_to_sign += scope + "\n";
    str_to_sign += hashData(conf_req) + "\n";

    // 3) Generate signature
    std::string datekey = signData(SIGN_VERSION_ID + this->api_access_secret_, signdate);
    std::string signkey;
    // check bool and use last sign key
    if(use_same_signkey) signkey = this->last_signkey_;
    else signkey = this->last_signkey_ = signData(datekey, SCOPE_REQUEST);
    std::string signature = signData(signkey, str_to_sign, true);

    // 4) add auth header
    headers["authorization"] = SIGN_METHOD_ID + " Credential=" + this->device_id_ + "/" + scope + ", Signature=" + signature;

    return;
}

// SHA256 Hash
std::string ctn::CtnApiClient::hashData(const std::string str)
{
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256_CTX sha256;
    SHA256_Init(&sha256);
    SHA256_Update(&sha256, str.c_str(), str.size());
    SHA256_Final(hash, &sha256);
    std::stringstream ss;
    ss << std::hex;
    for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
    {
        ss << std::setw(2) << std::setfill('0') << (int)hash[i];
    }
    return ss.str();
}

// HMAC-SHA256 signing
std::string ctn::CtnApiClient::signData(std::string key, std::string data, bool hex_encode)
{
    unsigned int len;
    unsigned char *raw = HMAC(EVP_sha256(), (unsigned char*) key.c_str(), key.length(),  (unsigned char*) data.c_str(), data.length(), NULL, &len);
    std::stringstream ss;

    if(hex_encode == false)
    {
        ss << raw;
    }
    else
    {
        ss << std::hex;
        for(int i = 0; i < len; i++)
        {
            ss << std::setw(2) << std::setfill('0') << (int)raw[i];
        }

    }
    return ss.str();
}
<commit_msg>Support for both http and https<commit_after>//
//  CatenisApiClient.cpp
//  CatenisAPIClientCpp
//
//  Created by Sungwoo Bae on 5/25/17.
//
#include <CatenisApiClient.h>

#include <iostream>
#include <sstream>
#include <stdio.h>
#include <iomanip>
#include <string>
#include <iterator>
#include <map>
#include <ctime>

#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/regex.hpp>

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

int main()
{
    ctn::CtnApiClient client("d4XwmaAyRJdSYp4CZuTA", "86ccbaeaff0e6fc9cff989dde3f1b2c2e92761202c40873b07166b7f20b4d7cb682be163305cae4a2f8df557536163416f539b2f6f17fb5f6a20e309fdbec9ce", "beta.catenis.io");

    std::string result;
    client.readMessage("mAsM3cF27vLk6KA4fZoG", result);
    //client->logMessage("hey1234", result);
    //client->retrieveMessageContainer("mAsM3cF27vLk6KA4fZoG", result);
    client.sendMessage(ctn::Device("dcdHMFcZh4qmGAmiMg75", false), "hey whats up",result);
    std::cout << result;

    return 0;
}

bool ctn::CtnApiClient::logMessage(std::string message, std::string &data, const MethodOption &option)
{
    std::map<std::string, std::string> params;
    std::map<std::string, std::string> queries;
    boost::property_tree::ptree request_data;

    // write request body
    request_data.put("message", message);
    request_data.put("options.encoding", option.encoding);
    request_data.put("options.encrypt", option.encrypt);
    request_data.put("options.storage", option.storage);

    return httpRequest("POST", "messages/log", params, queries, request_data, data);
}

bool ctn::CtnApiClient::sendMessage(const Device &device, std::string message, std::string &data, const MethodOption &option)
{
    std::map<std::string, std::string> params;
    std::map<std::string, std::string> queries;
    boost::property_tree::ptree request_data;

    // write request body
    request_data.put("targetDevice.id", device.id);
    request_data.put("targetDevice.isProdUniqueId", device.is_prod_uniqueid);
    request_data.put("options.encoding", option.encoding);
    request_data.put("message", message);
    request_data.put("options.encoding", option.encoding);
    request_data.put("options.encrypt", option.encrypt);
    request_data.put("options.storage", option.storage);

    return httpRequest("POST", "messages/send", params, queries, request_data, data);
}

bool ctn::CtnApiClient::readMessage(std::string message_id, std::string &data, const MethodOption &option)
{
    std::map<std::string, std::string> params;
    std::map<std::string, std::string> queries;
    boost::property_tree::ptree request_data;

    params[":messageId"] = message_id;
    queries["encoding"] = option.encoding;

    return httpRequest("GET", "messages/:messageId", params, queries, request_data, data);
}

bool ctn::CtnApiClient::retrieveMessageContainer(std::string message_id, std::string &data)
{
    std::map<std::string, std::string> params;
    std::map<std::string, std::string> queries;
    boost::property_tree::ptree request_data;

    params[":messageId"] = message_id;

    return httpRequest("GET", "messages/:messageId/container", params, queries, request_data, data);
}

// http request
bool ctn::CtnApiClient::httpRequest(std::string verb, std::string methodpath, std::map<std::string, std::string> &params, std::map<std::string, std::string> &queries, boost::property_tree::ptree &request_data, std::string &response_data)
{
    bool success = true;

    // Add entire path
    methodpath = this->root_api_endpoint_ + "/" + methodpath;

    // Process methodpath from params and queries
    for(auto const &data : params)
    {
        methodpath.replace(methodpath.find(data.first), data.first.length(), data.second);
    }
    for(auto const &data : queries)
    {
        // if not first query add "&", else add "?"
        if(data != *queries.begin()) methodpath += "&";
        else methodpath += "?";
        methodpath += data.first + "=" + data.second;
    }

    // Create neccesary headers
    time_t now = std::time(0);
    char iso_time[17];
    strftime(iso_time, sizeof iso_time, "%Y%m%dT%H%M%SZ", gmtime(&now));
    std::map<std::string, std::string> headers;

    headers["host"] = this->host_;
    headers[TIME_STAMP_HDR] = std::string(iso_time);

    std::string payload_json = "";
    // if POST, process payload
    if(verb == "POST")
    {
        std::ostringstream payload_buf;
        write_json (payload_buf, request_data, false);

        // fix boost.ptree bug where it treats all types as string
        boost::regex exp("\"(null|true|false|[0-9]+(\\.[0-9]+)?)\"");
        payload_json = boost::regex_replace(payload_buf.str(), exp, "$1");
    }

    // Create signature and add to header
    signRequest(verb, methodpath, headers, payload_json, now);

    // Set up TCP/IP connection with server and send request
    try
    {
        std::string prefix = (this->secure_ ? "https" : "http");

        // Get a list of endpoints corresponding to the server name
        boost::asio::io_service io_service;
        tcp::resolver resolver(io_service);
        tcp::resolver::query query(headers["host"], prefix);
        tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);

        // Declare both socket types to reuse most http_request code for ssl and http
        tcp::socket *http_socket;
        boost::asio::ssl::stream<tcp::socket> *ssl_socket;

        if(this->secure_)
        {
            // HTTPS
            // Create context
            boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
            ssl_socket = new boost::asio::ssl::stream<tcp::socket>(io_service, ctx);

            // Try each endpoint until successful connection
            //boost::asio::ssl::stream<tcp::socket> socket(io_service, ctx);
            boost::asio::connect(ssl_socket->lowest_layer(), endpoint_iterator);

            // Handshake with server
            ssl_socket->set_verify_mode(boost::asio::ssl::verify_none);
            ssl_socket->handshake(boost::asio::ssl::stream_base::handshake_type::client);
        }
        else
        {
            // HTTP
            // Try each endpoint until we successfully establish a connection.
            http_socket = new tcp::socket(io_service);
            boost::asio::connect(*http_socket, endpoint_iterator);
        }

        // Form the request. We specify the "Connection: close" header so that the
        // server will close the socket after transmitting the response. This will
        // allow us to treat all data up until the EOF as the content.
        boost::asio::streambuf request;
        std::ostream request_stream(&request);

        // Use HTTP 1.0 for now, since persistent connections not needed yet
        request_stream << verb << " " << methodpath << " HTTP/1.0\r\n";
        for(auto const &data : headers)
        {
            request_stream << data.first << ": " << data.second << "\r\n";
        }
        // add extra headers if POST
        if(verb == "POST")
        {
            request_stream << "Content-Type: application/json; charset=utf-8\r\n";
            request_stream << "Content-Length: " << payload_json.length() << "\r\n";
        }
        request_stream << "Connection: close\r\n\r\n";

        // add payload
        request_stream << payload_json;

        // Send the request, if statements needed check to use ssl_socket or http_socket
        if(this->secure_) boost::asio::write(*ssl_socket, request);
        else boost::asio::write(*http_socket, request);

        // Check that response is OK.
        boost::asio::streambuf response_buf;
        boost::system::error_code error;
        if(this->secure_) boost::asio::read_until(*ssl_socket, response_buf, "\r\n");
        else boost::asio::read_until(*http_socket, response_buf, "\r\n");
        std::istream response_stream(&response_buf);

        std::string http_version;
        response_stream >> http_version;
        unsigned int status_code;
        response_stream >> status_code;
        std::string status_message;
        std::getline(response_stream, status_message);
        if (!response_stream || http_version.substr(0, 5) != "HTTP/")
        {
            std::cout << "Invalid response\n";
            success = false;
        }
        if (status_code != 200)
        {
            std::cout << "Response returned with status code " << status_code << "\n";
            success = false;
        }

        // Read all headers and flush buffer
        int headerSize;
        if(this->secure_) headerSize = boost::asio::read_until(*ssl_socket, response_buf, "\r\n\r\n");
        else headerSize = boost::asio::read_until(*http_socket, response_buf, "\r\n\r\n");
        response_buf.consume(headerSize);

        // Read until EOF or Short read,
        if(this->secure_) boost::asio::read(*ssl_socket, response_buf, boost::asio::transfer_all(), error);
        else boost::asio::read(*http_socket, response_buf, boost::asio::transfer_all(), error);
        if (error != boost::asio::error::eof && error !=  boost::system::error_code(ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ), boost::asio::error::get_ssl_category()))
            throw boost::system::system_error(error);

        // Write response data
        // boost::property_tree::json_parser::read_json(response_stream, response_data);
        response_data = std::string(std::istreambuf_iterator<char>(response_stream), {});
    }
    catch (std::exception& e)
    {
        std::cout << "Exception: " << e.what() << "\n";
        success = false;
    }

    return success;
}

// Constructor
ctn::CtnApiClient::CtnApiClient(std::string device_id, std::string api_access_secret, std::string host, std::string environment, bool secure, std::string version)
{
    this->device_id_ = device_id;
    this->api_access_secret_ = api_access_secret;

    this->host_ = host;
    this->subdomain_ = environment;
    this->secure_ = secure;
    this->version_ = version;

    this->root_api_endpoint_ = API_PATH + this->version_;
}

// Generate Signature
void ctn::CtnApiClient::signRequest(std::string verb, std::string endpoint, std::map<std::string, std::string> &headers, std::string payload, time_t now)
{
    std::string timestamp = headers[TIME_STAMP_HDR];
    char date_buffer[9];
    std::string signdate;
    bool use_same_signkey;

    // Use last signkey if date < valid days
    if(this->last_signkey_.length() != 0 && std::difftime(now, this->last_signdate_)/(3600 * 24) < SIGN_VALID_DAYS)
    {
        use_same_signkey = true;
        strftime(date_buffer, sizeof date_buffer, "%Y%m%d", gmtime(&last_signdate_));
        signdate = std::string(date_buffer);
    }
    else
    {
        use_same_signkey = false;
        this->last_signdate_ = now;
        strftime(date_buffer, sizeof date_buffer, "%Y%m%d", gmtime(&now));
        signdate = std::string(date_buffer);
    }

    // 1) Compute conformed request
    std::string conf_req = verb + "\n";
    conf_req += endpoint + "\n";
    for(auto const &data : headers)
    {
        // All header must be in lower case
        conf_req += data.first + ":" + data.second + "\n";
    }
    conf_req += "\n" + hashData(payload) + "\n";

    // 2) Assemble string to sign
    std::string str_to_sign = SIGN_METHOD_ID + "\n";
    str_to_sign += timestamp + "\n";
    std::string scope = signdate + "/" + SCOPE_REQUEST;
    str_to_sign += scope + "\n";
    str_to_sign += hashData(conf_req) + "\n";

    // 3) Generate signature
    std::string datekey = signData(SIGN_VERSION_ID + this->api_access_secret_, signdate);
    std::string signkey;
    // check bool and use last sign key
    if(use_same_signkey) signkey = this->last_signkey_;
    else signkey = this->last_signkey_ = signData(datekey, SCOPE_REQUEST);
    std::string signature = signData(signkey, str_to_sign, true);

    // 4) add auth header
    headers["authorization"] = SIGN_METHOD_ID + " Credential=" + this->device_id_ + "/" + scope + ", Signature=" + signature;

    return;
}

// SHA256 Hash
std::string ctn::CtnApiClient::hashData(const std::string str)
{
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256_CTX sha256;
    SHA256_Init(&sha256);
    SHA256_Update(&sha256, str.c_str(), str.size());
    SHA256_Final(hash, &sha256);
    std::stringstream ss;
    ss << std::hex;
    for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
    {
        ss << std::setw(2) << std::setfill('0') << (int)hash[i];
    }
    return ss.str();
}

// HMAC-SHA256 signing
std::string ctn::CtnApiClient::signData(std::string key, std::string data, bool hex_encode)
{
    unsigned int len;
    unsigned char *raw = HMAC(EVP_sha256(), (unsigned char*) key.c_str(), key.length(),  (unsigned char*) data.c_str(), data.length(), NULL, &len);
    std::stringstream ss;

    if(hex_encode == false)
    {
        ss << raw;
    }
    else
    {
        ss << std::hex;
        for(int i = 0; i < len; i++)
        {
            ss << std::setw(2) << std::setfill('0') << (int)raw[i];
        }

    }
    return ss.str();
}
<|endoftext|>


<commit_before>#include "PauseMenuState.h"
#include "SDL2_framework/Game.h"
#include "MainMenuState.h"

const std::string PauseMenuState::s_menuID = "PAUSEMENU";

PauseMenuState::PauseMenuState() : MenuState::MenuState(3) {
	s_vActions.push_back(PauseMenuState::resumeGame);
	s_vActions.push_back(PauseMenuState::goToMainMenu);
	s_vActions.push_back(PauseMenuState::quitGame);
}

std::string PauseMenuState::getStateID() const {
	return s_menuID;
}

void PauseMenuState::resumeGame() {
	Game::Instance()->getStateMachine()->popState();
}

void PauseMenuState::goToMainMenu() {
	Game::Instance()->getStateMachine()->clean();
	Game::Instance()->getStateMachine()->pushState(new MainMenuState());
}

void PauseMenuState::quitGame() {
	Game::Instance()->quit();
}
<commit_msg>pause menu xml file set<commit_after>#include "PauseMenuState.h"
#include "SDL2_framework/Game.h"
#include "MainMenuState.h"

const std::string PauseMenuState::s_menuID = "PAUSEMENU";

PauseMenuState::PauseMenuState() : MenuState::MenuState(3) {
	m_sConfigFile = "configs/menus.xml",
	s_vActions.push_back(PauseMenuState::resumeGame);
	s_vActions.push_back(PauseMenuState::goToMainMenu);
	s_vActions.push_back(PauseMenuState::quitGame);
}

std::string PauseMenuState::getStateID() const {
	return s_menuID;
}

void PauseMenuState::resumeGame() {
	Game::Instance()->getStateMachine()->popState();
}

void PauseMenuState::goToMainMenu() {
	Game::Instance()->getStateMachine()->clean();
	Game::Instance()->getStateMachine()->pushState(new MainMenuState());
}

void PauseMenuState::quitGame() {
	Game::Instance()->quit();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: lngmerge.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: hr $ $Date: 2006-08-14 17:08:27 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
// local includes
#include "export.hxx"

DECLARE_LIST( LngLineList, ByteString * )

#define LNG_OK              0x0000
#define LNG_FILE_NOTFOUND   0x0001
#define LNG_COULD_NOT_OPEN  0x0002
#define SDF_OK              0x0003
#define SDF_FILE_NOTFOUND   0x0004
#define SDF_COULD_NOT_OPEN  0x0005

//
// class LngParser
//

class LngParser
{
private:
    USHORT nError;
    LngLineList *pLines;
    ByteString sSource;
    BOOL bDBIsUTF8;
    BOOL bULF;
    bool bQuiet;
    std::vector<ByteString> aLanguages;

    void FillInFallbacks( ByteStringHashMap Text );
    bool isNextGroup(  ByteString &sGroup_out , ByteString &sLine_in);
    void ReadLine( const ByteString &sLine_in , ByteStringHashMap &rText_inout );
    void WriteSDF( SvFileStream &aSDFStream , ByteStringHashMap &rText_inout ,
                    const ByteString &rPrj ,
                    const ByteString &rRoot , const ByteString &sActFileName , const ByteString &sID );
public:
    LngParser( const ByteString &rLngFile, BOOL bUTF8, BOOL bULFFormat, bool bQuiet_in );
    ~LngParser();

    BOOL CreateSDF( const ByteString &rSDFFile, const ByteString &rPrj, const ByteString &rRoot );
    BOOL Merge( const ByteString &rSDFFile, const ByteString &rDestinationFile , const ByteString &rPrj );
};
<commit_msg>INTEGRATION: CWS changefileheader (1.8.96); FILE MERGED 2008/03/28 15:41:57 rt 1.8.96.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: lngmerge.hxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
// local includes
#include "export.hxx"

DECLARE_LIST( LngLineList, ByteString * )

#define LNG_OK              0x0000
#define LNG_FILE_NOTFOUND   0x0001
#define LNG_COULD_NOT_OPEN  0x0002
#define SDF_OK              0x0003
#define SDF_FILE_NOTFOUND   0x0004
#define SDF_COULD_NOT_OPEN  0x0005

//
// class LngParser
//

class LngParser
{
private:
    USHORT nError;
    LngLineList *pLines;
    ByteString sSource;
    BOOL bDBIsUTF8;
    BOOL bULF;
    bool bQuiet;
    std::vector<ByteString> aLanguages;

    void FillInFallbacks( ByteStringHashMap Text );
    bool isNextGroup(  ByteString &sGroup_out , ByteString &sLine_in);
    void ReadLine( const ByteString &sLine_in , ByteStringHashMap &rText_inout );
    void WriteSDF( SvFileStream &aSDFStream , ByteStringHashMap &rText_inout ,
                    const ByteString &rPrj ,
                    const ByteString &rRoot , const ByteString &sActFileName , const ByteString &sID );
public:
    LngParser( const ByteString &rLngFile, BOOL bUTF8, BOOL bULFFormat, bool bQuiet_in );
    ~LngParser();

    BOOL CreateSDF( const ByteString &rSDFFile, const ByteString &rPrj, const ByteString &rRoot );
    BOOL Merge( const ByteString &rSDFFile, const ByteString &rDestinationFile , const ByteString &rPrj );
};
<|endoftext|>


<commit_before>#include "atom.h"

bool Atom::match(Atom &b){
  bool isMatch = true;

  if( this->symbol() != b.symbol() ){
    isMatch = false;
  }else{
    this->_value = b.value();
  }
  return isMatch;
}

bool Atom::match( Number &b){
  bool isMatch = true;

  if( this->symbol() != b.symbol() ){
    isMatch = false;
  }
  return isMatch;
}
bool Atom::match(Variable &a){
  bool isMatch = true;
  if(a.value().empty() ){
      a._value = this->value();
  }
  if( a.value() != this->value() ){
    isMatch = false;
  }
  return isMatch;
}
<commit_msg>Delete atom.cpp<commit_after><|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2013 Danny Y., Rapptz

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef SOL_TRAITS_HPP
#define SOL_TRAITS_HPP

#include "tuple.hpp"
#include <type_traits>

namespace sol {
template<class T, class...>
struct are_same : std::true_type { };

template<class T, class U, class... Args>
struct are_same<T, U, Args...> : std::integral_constant <bool, std::is_same<T, U>::value && are_same<T, Args...>::value> { };

template<bool B>
using Bool = std::integral_constant<bool, B>;

template<typename T>
using Not = Bool<!T::value>;

template<typename Condition, typename Then, typename Else>
using If = typename std::conditional<Condition::value, Then, Else>::type;

template<typename... Args>
struct And : Bool<true> {};

template<typename T, typename... Args>
struct And<T, Args...> : If<T, And<Args...>, Bool<false>> {};

template<typename... Args>
struct Or : Bool<true> {};

template<typename T, typename... Args>
struct Or<T, Args...> : If<Not<T>, Or<Args...>, Bool<true>> {};

template<typename... Args>
using EnableIf = typename std::enable_if<And<Args...>::value, int>::type;

template<typename... Args>
using DisableIf = typename std::enable_if<Not<And<Args...>>::value, int>::type;

template<typename T>
using Unqualified = typename std::remove_cv<typename std::remove_reference<T>::type>::type;

template<typename T>
using Decay = typename std::decay<T>::type;

template<typename... Args>
struct return_type {
    typedef std::tuple<Args...> type;
};

template<typename T>
struct return_type<T> {
    typedef T type;
};

template<>
struct return_type<> : types<>{
    typedef void type;
};

template<typename... Args>
struct is_tuple : std::false_type{ };

template<typename... Args>
struct is_tuple<std::tuple<Args...>> : std::true_type{ };

template <typename T, template <typename...> class Templ>
struct is_specialization_of : std::false_type { };
template <typename... T, template <typename...> class Templ>
struct is_specialization_of<Templ<T...>, Templ> : std::true_type { };

namespace detail {
template<typename T, bool isclass = std::is_class<Unqualified<T>>::value>
struct is_function_impl : std::is_function<typename std::remove_pointer<T>::type> {};

template<typename T>
struct is_function_impl<T, true> {
    using yes = char;
    using no = struct { char s[2]; };

    struct F { void operator()(); };
    struct Derived : T, F {};
    template<typename U, U> struct Check;

    template<typename V>
    static no test(Check<void (F::*)(), &V::operator()>*);

    template<typename>
    static yes test(...);

    static const bool value = sizeof(test<Derived>(0)) == sizeof(yes);
};
} // detail

template<typename T>
struct Function : Bool<detail::is_function_impl<T>::value> {};

template<typename TFuncSignature>
struct function_traits;

template<typename T, typename R, typename... Args>
struct function_traits<R(T::*)(Args...)> {
    static const std::size_t arity = sizeof...(Args);
    static const bool is_member_function = true;
    typedef std::tuple<Args...> arg_tuple_type;
    typedef types<Args...> args_type;
    typedef R(T::* function_pointer_type)(Args...);
    typedef typename std::remove_pointer<function_pointer_type>::type function_type;
    typedef R(*free_function_pointer_type)(Args...);
    typedef R return_type;
    template<std::size_t i>
    using arg = typename std::tuple_element<i, arg_tuple_type>::type;
};

template<typename T, typename R, typename... Args>
struct function_traits<R(T::*)(Args...) const> {
    static const std::size_t arity = sizeof...(Args);
    static const bool is_member_function = true;
    typedef std::tuple<Args...> arg_tuple_type;
    typedef types<Args...> args_type;
    typedef R(T::* function_pointer_type)(Args...);
    typedef typename std::remove_pointer<function_pointer_type>::type function_type;
    typedef R(*free_function_pointer_type)(Args...);
    typedef R return_type;
    template<std::size_t i>
    using arg = typename std::tuple_element<i, arg_tuple_type>::type;
};

template<typename R, typename... Args>
struct function_traits<R(Args...)> {
    static const std::size_t arity = sizeof...(Args);
    static const bool is_member_function = false;
    typedef std::tuple<Args...> arg_tuple_type;
    typedef types<Args...> args_type;
    typedef R(function_type)(Args...);
    typedef R(*function_pointer_type)(Args...);
    typedef R(*free_function_pointer_type)(Args...);
    typedef R return_type;
    template<std::size_t i>
    using arg = typename std::tuple_element<i, arg_tuple_type>::type;
};

template<typename R, typename... Args>
struct function_traits<R(*)(Args...)> {
    static const std::size_t arity = sizeof...(Args);
    static const bool is_member_function = false;
    typedef std::tuple<Args...> arg_tuple_type;
    typedef types<Args...> args_type;
    typedef R(function_type)(Args...);
    typedef R(*function_pointer_type)(Args...);
    typedef R(*free_function_pointer_type)(Args...);
    typedef R return_type;
    template<std::size_t i>
    using arg = typename std::tuple_element<i, arg_tuple_type>::type;
};

struct has_begin_end_impl {
    template<typename T, typename U = Unqualified<T>,
                         typename B = decltype(std::declval<U&>().begin()),
                         typename E = decltype(std::declval<U&>().end())>
    static std::true_type test(int);

    template<typename...>
    static std::false_type test(...);
};

template<typename T>
struct has_begin_end : decltype(has_begin_end_impl::test<T>(0)) {};

struct has_key_value_pair_impl {
    template<typename T, typename U = Unqualified<T>,
             typename V = typename U::value_type,
             typename F = decltype(std::declval<V&>().first),
             typename S = decltype(std::declval<V&>().second)>
    static std::true_type test(int);

    template<typename...>
    static std::false_type test(...);
};

template<typename T>
struct has_key_value_pair : decltype(has_key_value_pair_impl::test<T>(0)) {};
} // sol

#endif // SOL_TRAITS_HPP
<commit_msg>better `Or` implementation i don't think i use it anymore though...<commit_after>// The MIT License (MIT)

// Copyright (c) 2013 Danny Y., Rapptz

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef SOL_TRAITS_HPP
#define SOL_TRAITS_HPP

#include "tuple.hpp"
#include <type_traits>

namespace sol {
template<class T, class...>
struct are_same : std::true_type { };

template<class T, class U, class... Args>
struct are_same<T, U, Args...> : std::integral_constant <bool, std::is_same<T, U>::value && are_same<T, Args...>::value> { };

template<bool B>
using Bool = std::integral_constant<bool, B>;

template<typename T>
using Not = Bool<!T::value>;

template<typename Condition, typename Then, typename Else>
using If = typename std::conditional<Condition::value, Then, Else>::type;

template<typename... Args>
struct And : Bool<true> {};

template<typename T, typename... Args>
struct And<T, Args...> : If<T, And<Args...>, Bool<false>> {};

template<typename... Args>
struct Or : Bool<true> {};

template<typename T, typename... Args>
struct Or<T, Args...> : If<T, Bool<true>, Or<Args...>> {};

template<typename... Args>
using EnableIf = typename std::enable_if<And<Args...>::value, int>::type;

template<typename... Args>
using DisableIf = typename std::enable_if<Not<And<Args...>>::value, int>::type;

template<typename T>
using Unqualified = typename std::remove_cv<typename std::remove_reference<T>::type>::type;

template<typename T>
using Decay = typename std::decay<T>::type;

template<typename... Args>
struct return_type {
    typedef std::tuple<Args...> type;
};

template<typename T>
struct return_type<T> {
    typedef T type;
};

template<>
struct return_type<> : types<>{
    typedef void type;
};

template<typename... Args>
struct is_tuple : std::false_type{ };

template<typename... Args>
struct is_tuple<std::tuple<Args...>> : std::true_type{ };

template <typename T, template <typename...> class Templ>
struct is_specialization_of : std::false_type { };
template <typename... T, template <typename...> class Templ>
struct is_specialization_of<Templ<T...>, Templ> : std::true_type { };

namespace detail {
template<typename T, bool isclass = std::is_class<Unqualified<T>>::value>
struct is_function_impl : std::is_function<typename std::remove_pointer<T>::type> {};

template<typename T>
struct is_function_impl<T, true> {
    using yes = char;
    using no = struct { char s[2]; };

    struct F { void operator()(); };
    struct Derived : T, F {};
    template<typename U, U> struct Check;

    template<typename V>
    static no test(Check<void (F::*)(), &V::operator()>*);

    template<typename>
    static yes test(...);

    static const bool value = sizeof(test<Derived>(0)) == sizeof(yes);
};
} // detail

template<typename T>
struct Function : Bool<detail::is_function_impl<T>::value> {};

template<typename TFuncSignature>
struct function_traits;

template<typename T, typename R, typename... Args>
struct function_traits<R(T::*)(Args...)> {
    static const std::size_t arity = sizeof...(Args);
    static const bool is_member_function = true;
    typedef std::tuple<Args...> arg_tuple_type;
    typedef types<Args...> args_type;
    typedef R(T::* function_pointer_type)(Args...);
    typedef typename std::remove_pointer<function_pointer_type>::type function_type;
    typedef R(*free_function_pointer_type)(Args...);
    typedef R return_type;
    template<std::size_t i>
    using arg = typename std::tuple_element<i, arg_tuple_type>::type;
};

template<typename T, typename R, typename... Args>
struct function_traits<R(T::*)(Args...) const> {
    static const std::size_t arity = sizeof...(Args);
    static const bool is_member_function = true;
    typedef std::tuple<Args...> arg_tuple_type;
    typedef types<Args...> args_type;
    typedef R(T::* function_pointer_type)(Args...);
    typedef typename std::remove_pointer<function_pointer_type>::type function_type;
    typedef R(*free_function_pointer_type)(Args...);
    typedef R return_type;
    template<std::size_t i>
    using arg = typename std::tuple_element<i, arg_tuple_type>::type;
};

template<typename R, typename... Args>
struct function_traits<R(Args...)> {
    static const std::size_t arity = sizeof...(Args);
    static const bool is_member_function = false;
    typedef std::tuple<Args...> arg_tuple_type;
    typedef types<Args...> args_type;
    typedef R(function_type)(Args...);
    typedef R(*function_pointer_type)(Args...);
    typedef R(*free_function_pointer_type)(Args...);
    typedef R return_type;
    template<std::size_t i>
    using arg = typename std::tuple_element<i, arg_tuple_type>::type;
};

template<typename R, typename... Args>
struct function_traits<R(*)(Args...)> {
    static const std::size_t arity = sizeof...(Args);
    static const bool is_member_function = false;
    typedef std::tuple<Args...> arg_tuple_type;
    typedef types<Args...> args_type;
    typedef R(function_type)(Args...);
    typedef R(*function_pointer_type)(Args...);
    typedef R(*free_function_pointer_type)(Args...);
    typedef R return_type;
    template<std::size_t i>
    using arg = typename std::tuple_element<i, arg_tuple_type>::type;
};

struct has_begin_end_impl {
    template<typename T, typename U = Unqualified<T>,
                         typename B = decltype(std::declval<U&>().begin()),
                         typename E = decltype(std::declval<U&>().end())>
    static std::true_type test(int);

    template<typename...>
    static std::false_type test(...);
};

template<typename T>
struct has_begin_end : decltype(has_begin_end_impl::test<T>(0)) {};

struct has_key_value_pair_impl {
    template<typename T, typename U = Unqualified<T>,
             typename V = typename U::value_type,
             typename F = decltype(std::declval<V&>().first),
             typename S = decltype(std::declval<V&>().second)>
    static std::true_type test(int);

    template<typename...>
    static std::false_type test(...);
};

template<typename T>
struct has_key_value_pair : decltype(has_key_value_pair_impl::test<T>(0)) {};
} // sol

#endif // SOL_TRAITS_HPP
<|endoftext|>


<commit_before>#include "TicTacToeBoard.h"
#include <iostream>
using namespace std;

/**
 * Class for representing a 3x3 Tic-Tac-Toe game board, using the Piece enum
 * to represent the spaces on the board.
**/
TicTacToeBoard::TicTacToeBoard()
{
  turn = X;
  for(int i = 0; i < BOARDSIZE; i++) {
    for(int j = 0; j < BOARDSIZE; j++) {
      board[i][j] = Blank;
    }
  }
}

/**
 * Switches turn member variable to represent whether it's X's or O's turn
 * and returns whose turn it is
**/
Piece TicTacToeBoard::toggleTurn()
{
  if (turn == X) {
    turn = O;
  } else {
    turn = X;
  }
  return turn;
}

/**
 * Places the piece of the current turn on the board, returns what
 * piece is placed, and toggles which Piece's turn it is. placePiece does
 * NOT allow to place a piece in a location where there is already a piece.
 * In that case, placePiece just returns what is already at that location.
 * Out of bounds coordinates return the Piece Invalid value. When the game
 * is over, no more pieces can be placed so attempting to place a piece
 * should neither change the board nor change whose turn it is.
**/
Piece TicTacToeBoard::placePiece(int row, int column)
{
  if (getPiece(row, column) == Invalid || getWinner() != Invalid) return Invalid;
  if (getPiece(row, column) == Blank) {
    board[row][column] = turn;
    toggleTurn();
  }
  return getPiece(row, column);
}

/**
 * Returns what piece is at the provided coordinates, or Blank if there
 * are no pieces there, or Invalid if the coordinates are out of bounds
**/
Piece TicTacToeBoard::getPiece(int row, int column)
{
  // If position is out of board bounds, then return Invalid.
  if (row > BOARDSIZE || row < 0 || column > BOARDSIZE || column < 0) return Invalid;
  return board[row][column];
}

/**
 * Returns which Piece has won, if there is a winner, Invalid if the game
 * is not over, or Blank if the board is filled and no one has won.
**/
Piece TicTacToeBoard::getWinner()
{
  Piece winner = Invalid;

  // Check for horizontal wins.
  bool isRowSame = false;
  for (int i = 0; i < BOARDSIZE; i++) {
    for (int j = 0; j < BOARDSIZE - 1; j++) {
      // Check if first two pieces match.
      if (j == 0) {
        isRowSame = getPiece(i, j) == getPiece(i, j + 1);
        if (getPiece(i, j) == Blank) isRowSame = false;
      }
      // Check if current two pieces and previous pieces match.
      else isRowSame = getPiece(i, j) == getPiece(i, j + 1) && isRowSame;
    }
    if (isRowSame) {
      winner = getPiece(i, 0);
    }
  }

  // Check for vertical wins.
  bool isColumnSame = false;
  for (int j = 0; j < BOARDSIZE; j++) {
    for (int i = 0; i < BOARDSIZE - 1; i++) {
      // Check if first two pieces match.
      if (i == 0) {
        isColumnSame = getPiece(i, j) == getPiece(i + 1, j);
        if (getPiece(i, j) == Blank) isColumnSame = false;
      }
      // Check if current two pieces and previous pieces match.
      else isColumnSame = getPiece(i, j) == getPiece(i + 1, j) && isColumnSame;
    }
    if (isColumnSame) {
      winner = getPiece(0, j);
    }
  }

  // Check for diagonal top left to bottom right win.
  bool isDiagonalSame = false;
  for (int i = 0; i < BOARDSIZE - 1; i++) {
    // Check if first two pieces match.
    if (i == 0) {
      isDiagonalSame = getPiece(i, i) == getPiece(i + 1, i + 1);
      if (getPiece(i, i) == Blank) isDiagonalSame = false;
    }
    // Check if current two pieces and previous pieces match.
    else isDiagonalSame = getPiece(i, i) == getPiece(i + 1, i + 1) && isDiagonalSame;
  }
  if (isDiagonalSame) {
    winner = getPiece(0, 0);
  }

  // Check for diagonal top right to bottom left win.
  isDiagonalSame = false;
  for (int i = 0; i < BOARDSIZE - 1; i++) {
    // Check if first two pieces match.
    if (i == 0) {
      isDiagonalSame = getPiece((BOARDSIZE - 1) - i, i) == getPiece((BOARDSIZE - 1) - i - 1, i + 1);
      if (getPiece((BOARDSIZE - 1) - i, i) == Blank) isDiagonalSame = false;
    }
    // Check if current two pieces and previous pieces match.
    else isDiagonalSame = getPiece((BOARDSIZE - 1) - i, i) == getPiece((BOARDSIZE - 1) - i - 1, i + 1) && isDiagonalSame;
  }
  if (isDiagonalSame) {
    winner = getPiece(0, BOARDSIZE - 1);
  }

  // If there is no winner, check board to see if there is a tie.
  if (winner == Invalid) {
    bool isTie = true;
    for (int i = 0; i < BOARDSIZE; i++) {
      for (int j = 0; j < BOARDSIZE; j++) {
        if (getPiece(i, j) == Blank) isTie = false;
      }
    }
    if (isTie) return Blank;
  }

  return winner;
}
<commit_msg>Make placepiece function not work because i forgot to do that<commit_after>#include "TicTacToeBoard.h"
#include <iostream>
using namespace std;

/**
 * Class for representing a 3x3 Tic-Tac-Toe game board, using the Piece enum
 * to represent the spaces on the board.
**/
TicTacToeBoard::TicTacToeBoard()
{
  turn = X;
  for(int i = 0; i < BOARDSIZE; i++) {
    for(int j = 0; j < BOARDSIZE; j++) {
      board[i][j] = Blank;
    }
  }
}

/**
 * Switches turn member variable to represent whether it's X's or O's turn
 * and returns whose turn it is
**/
Piece TicTacToeBoard::toggleTurn()
{
  if (turn == X) {
    turn = O;
  } else {
    turn = X;
  }
  return turn;
}

/*
  BUG: Outputting wrong peice. Shoud output the right piece.
*/
/**
 * Places the piece of the current turn on the board, returns what
 * piece is placed, and toggles which Piece's turn it is. placePiece does
 * NOT allow to place a piece in a location where there is already a piece.
 * In that case, placePiece just returns what is already at that location.
 * Out of bounds coordinates return the Piece Invalid value. When the game
 * is over, no more pieces can be placed so attempting to place a piece
 * should neither change the board nor change whose turn it is.
**/
Piece TicTacToeBoard::placePiece(int row, int column)
{
  if (getPiece(row, column) == Invalid || getWinner() != Invalid) return Invalid;
  if (getPiece(row, column) == Blank) {
    board[row][column] = turn;
    toggleTurn();
  }
  return getPiece(column, row);
}

/**
 * Returns what piece is at the provided coordinates, or Blank if there
 * are no pieces there, or Invalid if the coordinates are out of bounds
**/
Piece TicTacToeBoard::getPiece(int row, int column)
{
  // If position is out of board bounds, then return Invalid.
  if (row > BOARDSIZE || row < 0 || column > BOARDSIZE || column < 0) return Invalid;
  return board[row][column];
}

/**
 * Returns which Piece has won, if there is a winner, Invalid if the game
 * is not over, or Blank if the board is filled and no one has won.
**/
Piece TicTacToeBoard::getWinner()
{
  Piece winner = Invalid;

  // Check for horizontal wins.
  bool isRowSame = false;
  for (int i = 0; i < BOARDSIZE; i++) {
    for (int j = 0; j < BOARDSIZE - 1; j++) {
      // Check if first two pieces match.
      if (j == 0) {
        isRowSame = getPiece(i, j) == getPiece(i, j + 1);
        if (getPiece(i, j) == Blank) isRowSame = false;
      }
      // Check if current two pieces and previous pieces match.
      else isRowSame = getPiece(i, j) == getPiece(i, j + 1) && isRowSame;
    }
    if (isRowSame) {
      winner = getPiece(i, 0);
    }
  }

  // Check for vertical wins.
  bool isColumnSame = false;
  for (int j = 0; j < BOARDSIZE; j++) {
    for (int i = 0; i < BOARDSIZE - 1; i++) {
      // Check if first two pieces match.
      if (i == 0) {
        isColumnSame = getPiece(i, j) == getPiece(i + 1, j);
        if (getPiece(i, j) == Blank) isColumnSame = false;
      }
      // Check if current two pieces and previous pieces match.
      else isColumnSame = getPiece(i, j) == getPiece(i + 1, j) && isColumnSame;
    }
    if (isColumnSame) {
      winner = getPiece(0, j);
    }
  }

  // Check for diagonal top left to bottom right win.
  bool isDiagonalSame = false;
  for (int i = 0; i < BOARDSIZE - 1; i++) {
    // Check if first two pieces match.
    if (i == 0) {
      isDiagonalSame = getPiece(i, i) == getPiece(i + 1, i + 1);
      if (getPiece(i, i) == Blank) isDiagonalSame = false;
    }
    // Check if current two pieces and previous pieces match.
    else isDiagonalSame = getPiece(i, i) == getPiece(i + 1, i + 1) && isDiagonalSame;
  }
  if (isDiagonalSame) {
    winner = getPiece(0, 0);
  }

  // Check for diagonal top right to bottom left win.
  isDiagonalSame = false;
  for (int i = 0; i < BOARDSIZE - 1; i++) {
    // Check if first two pieces match.
    if (i == 0) {
      isDiagonalSame = getPiece((BOARDSIZE - 1) - i, i) == getPiece((BOARDSIZE - 1) - i - 1, i + 1);
      if (getPiece((BOARDSIZE - 1) - i, i) == Blank) isDiagonalSame = false;
    }
    // Check if current two pieces and previous pieces match.
    else isDiagonalSame = getPiece((BOARDSIZE - 1) - i, i) == getPiece((BOARDSIZE - 1) - i - 1, i + 1) && isDiagonalSame;
  }
  if (isDiagonalSame) {
    winner = getPiece(0, BOARDSIZE - 1);
  }

  // If there is no winner, check board to see if there is a tie.
  if (winner == Invalid) {
    bool isTie = true;
    for (int i = 0; i < BOARDSIZE; i++) {
      for (int j = 0; j < BOARDSIZE; j++) {
        if (getPiece(i, j) == Blank) isTie = false;
      }
    }
    if (isTie) return Blank;
  }

  return winner;
}
<|endoftext|>


<commit_before>#include "CollisionChecker.hpp"

CollisionChecker* CollisionChecker::cc = NULL;

CollisionChecker::CollisionChecker(void){}

void CollisionChecker::Register (Sprite* s1, Sprite* s2) {
	Pair p(s1, s2);

	std::list<Pair>::const_iterator i;
	for(i = pairs.begin(); i != pairs.end(); i++) {
		if(i->first == s1 && i->second == s2)
			return;
		if(i->first == s2 && i->second == s1)
			return;
	}
	pairs.push_back(p);
	return;
}

void CollisionChecker::Cancel (Sprite* s1, Sprite* s2) {
	Pair p(s1, s2);
	cancel_queue.push_back(p);
	return;
}

void CollisionChecker::Commit(void) {
	std::list<Pair>::iterator ite;
	for (ite = cancel_queue.begin(); ite != cancel_queue.end(); ite++)
		pairs.remove(*ite);
	return;
}

// CheckFunctor members
void CollisionChecker::CheckFunctor::operator () (Pair const& p) const {
	if (p.first->CollisionCheck(p.second))
			p.first->NotifyCollision(p.second);
}
// ////////////////////

CollisionChecker* CollisionChecker::Singleton(void) {
	if (!cc)
		cc = new CollisionChecker();
	return cc;
}

void CollisionChecker::Check(void) {
	std::for_each(pairs.begin(), pairs.end(), CheckFunctor());
}
<commit_msg>Fixed huge cancelation queue bug<commit_after>#include "CollisionChecker.hpp"

CollisionChecker* CollisionChecker::cc = NULL;

CollisionChecker::CollisionChecker(void){}

void CollisionChecker::Register (Sprite* s1, Sprite* s2) {
	Pair p(s1, s2);

	std::list<Pair>::const_iterator i;
	for(i = pairs.begin(); i != pairs.end(); i++) {
		if(i->first == s1 && i->second == s2)
			return;
		if(i->first == s2 && i->second == s1)
			return;
	}
	pairs.push_back(p);
	return;
}

void CollisionChecker::Cancel (Sprite* s1, Sprite* s2) {
	Pair p(s1, s2);
	cancel_queue.push_back(p);
	return;
}

void CollisionChecker::Commit(void) {
	std::list<Pair>::iterator ite;
	for (ite = cancel_queue.begin(); ite != cancel_queue.end(); ite++)
		pairs.remove(*ite);

	cancel_queue.clear();
	return;
}

// CheckFunctor members
void CollisionChecker::CheckFunctor::operator () (Pair const& p) const {
	if (p.first->CollisionCheck(p.second))
			p.first->NotifyCollision(p.second);
}
// ////////////////////

CollisionChecker* CollisionChecker::Singleton(void) {
	if (!cc)
		cc = new CollisionChecker();
	return cc;
}

void CollisionChecker::Check(void) {
	std::for_each(pairs.begin(), pairs.end(), CheckFunctor());
}
<|endoftext|>


<commit_before>#include "Sound.h"
#ifdef WIN32
#include <SDL/SDL_mixer.h>
#else
#include <SDL_mixer/SDL_mixer.h>
#endif
#include <SDL/SDL.h>
#include <queue>

#include <map>
#include <math.h>
#include "Utilities/ResourceManager.h"
#include "Logging.h"

namespace Sound
{

namespace Internal
{

typedef std::map<std::string, Mix_Chunk*> EffectsMap;
typedef std::map<std::string, Mix_Music*> MusicMap;
std::queue<std::string> preloadQueue;
EffectsMap effects;
MusicMap musics;

SDL_mutex* effectMapLock = NULL;
SDL_mutex* preloadQueueLock = NULL;
SDL_cond* preloadQueueCondition = NULL;

Mix_Chunk* SoundNamed ( const std::string& name )
{
	SDL_LockMutex(effectMapLock);
	EffectsMap::iterator iter = effects.find(name);
	if (iter == effects.end())
	{
		// load the sound
		std::string path = "Sounds/" + name + ".aiff";
		SDL_RWops* ops = ResourceManager::OpenFile(path);
		Mix_Chunk* newChunk = Mix_LoadWAV_RW(ops, 1);
		if (!newChunk)
		{
            LOG("Sound", LOG_WARNING, "Decoding sound '%s' failed! Error: %s", name.c_str(), Mix_GetError());
			effects[name] = NULL;
			SDL_UnlockMutex(effectMapLock);
			return NULL;
		}
		effects[name] = newChunk;
		SDL_UnlockMutex(effectMapLock);
		return newChunk;
	}
	else
	{
		SDL_UnlockMutex(effectMapLock);
		return iter->second;
	}
}

void PreloadingThread ()
{
	SDL_LockMutex(preloadQueueLock);
	while (SDL_CondWait(preloadQueueCondition, preloadQueueLock))
	{
		while (!preloadQueue.empty())
		{
			std::string nextSound = preloadQueue.front();
			preloadQueue.pop();
			SoundNamed(nextSound);
		}
	}
}

const char* extensions[] =
{
	".s3m",
	".ogg",
	".xm",
	".mod",
	".aiff",
	NULL
};

Mix_Music* MusicNamed ( const std::string& name )
{
	MusicMap::iterator iter = musics.find(name);
	if (iter == musics.end())
	{
		// load the sound
		Mix_Music* newMusic = NULL;
		for (unsigned i = 0; extensions[i] != NULL; i++)
		{
			std::string path = "Music/" + name + extensions[i];
			SDL_RWops* ops = ResourceManager::OpenFile(path);
			if (!ops)
				continue;
			newMusic = Mix_LoadMUS_RW(ops);
			if (newMusic)
				break;
		}
		musics[name] = newMusic;
		return newMusic;
	}
	else
	{
		return iter->second;
	}
}

std::string songName;

}

using namespace Internal;

static bool disable_music = false;

void Init ( int frequency, int resolution, int sources )
{
	int volume_sound = MIX_MAX_VOLUME, volume_music = MIX_MAX_VOLUME;
	Uint16 format;
	switch (resolution)
	{
		case 8:
			format = AUDIO_S8;
			break;
		case 16:
			format = AUDIO_S16SYS;
			break;
/*		case 24:
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
			format = 0x8018;
#else
			format = 0x9018;
#endif
			break;*/
		default:
            LOG("Sound", LOG_NOTICE, "Unsupported audio format, defaulting to 16-bit");
			format = AUDIO_S16SYS;
			break;
	}
	Mix_OpenAudio(frequency, format, 2, 4096);
	Mix_AllocateChannels(sources);
	Mix_VolumeMusic(volume_music);
	Mix_Volume(-1, volume_sound);
	if (getenv("APOLLO_MUSIC_DISABLE"))
		disable_music = true;
	effectMapLock = SDL_CreateMutex();
	preloadQueueLock = SDL_CreateMutex();
	preloadQueueCondition = SDL_CreateCond();
}

void Preload ( const std::string& name )
{
	SDL_LockMutex(preloadQueueLock);
	preloadQueue.push(name);
	SDL_UnlockMutex(preloadQueueLock);
	SDL_CondSignal(preloadQueueCondition);
}

void PlaySoundSDL ( const std::string& name, float gain, float pan )
{
	Mix_Chunk* chunk = SoundNamed(name);
	if (!chunk)
		return;
	Uint8 ipan = pan * 127;
	int ivolume = gain * (MIX_MAX_VOLUME / 2);
	int channel = Mix_GroupAvailable(-1);
	Mix_UnregisterAllEffects(channel);
	if (ipan != 127)
		Mix_SetPanning(channel, 0xFF - ipan, ipan);
	if (fabs(gain - 1.0f) > 0.0003f)
		Mix_SetDistance(channel, 1 / gain);
	Mix_PlayChannel(channel, chunk, 0);
}

void PlayMusic ( const std::string& music )
{
	if (disable_music)
		return;
	Mix_Music* mus = MusicNamed(music);
	if (mus)
	{
		Mix_PlayMusic(mus, -1);
		songName = music;
	}
}

void StopMusic ()
{
	songName = "(no song)";
	Mix_HaltMusic();
}

std::string MusicName ()
{
	return songName;
}

float MusicVolume ()
{
	return Mix_VolumeMusic(-1) / (float)MIX_MAX_VOLUME;
}

void SetMusicVolume ( float _mvol )
{
	Mix_VolumeMusic(_mvol * MIX_MAX_VOLUME);
}

float SoundVolume ()
{
	return Mix_Volume(-1, -1) / (float)MIX_MAX_VOLUME;
}

void SetSoundVolume ( float _mvol )
{
	Mix_Volume(-1, MIX_MAX_VOLUME * _mvol);
}

}
<commit_msg>Sound update: use Mix_Init.<commit_after>#include "Sound.h"
#ifdef WIN32
#include <SDL/SDL_mixer.h>
#else
#include <SDL_mixer/SDL_mixer.h>
#endif
#include <SDL/SDL.h>
#include <queue>

#include <map>
#include <math.h>
#include "Utilities/ResourceManager.h"
#include "Logging.h"

namespace Sound
{

namespace Internal
{

typedef std::map<std::string, Mix_Chunk*> EffectsMap;
typedef std::map<std::string, Mix_Music*> MusicMap;
std::queue<std::string> preloadQueue;
EffectsMap effects;
MusicMap musics;

SDL_mutex* effectMapLock = NULL;
SDL_mutex* preloadQueueLock = NULL;
SDL_cond* preloadQueueCondition = NULL;

Mix_Chunk* SoundNamed ( const std::string& name )
{
	SDL_LockMutex(effectMapLock);
	EffectsMap::iterator iter = effects.find(name);
	if (iter == effects.end())
	{
		// load the sound
		std::string path = "Sounds/" + name + ".aiff";
		SDL_RWops* ops = ResourceManager::OpenFile(path);
		Mix_Chunk* newChunk = Mix_LoadWAV_RW(ops, 1);
		if (!newChunk)
		{
            LOG("Sound", LOG_WARNING, "Decoding sound '%s' failed! Error: %s", name.c_str(), Mix_GetError());
			effects[name] = NULL;
			SDL_UnlockMutex(effectMapLock);
			return NULL;
		}
		effects[name] = newChunk;
		SDL_UnlockMutex(effectMapLock);
		return newChunk;
	}
	else
	{
		SDL_UnlockMutex(effectMapLock);
		return iter->second;
	}
}

void PreloadingThread ()
{
	SDL_LockMutex(preloadQueueLock);
	while (SDL_CondWait(preloadQueueCondition, preloadQueueLock))
	{
		while (!preloadQueue.empty())
		{
			std::string nextSound = preloadQueue.front();
			preloadQueue.pop();
			SoundNamed(nextSound);
		}
	}
}

const char* extensions[] =
{
	".s3m",
	".ogg",
	".xm",
	".mod",
	".aiff",
	NULL
};

Mix_Music* MusicNamed ( const std::string& name )
{
	MusicMap::iterator iter = musics.find(name);
	if (iter == musics.end())
	{
		// load the sound
		Mix_Music* newMusic = NULL;
		for (unsigned i = 0; extensions[i] != NULL; i++)
		{
			std::string path = "Music/" + name + extensions[i];
			SDL_RWops* ops = ResourceManager::OpenFile(path);
			if (!ops)
				continue;
			newMusic = Mix_LoadMUS_RW(ops);
			if (newMusic)
				break;
		}
		musics[name] = newMusic;
		return newMusic;
	}
	else
	{
		return iter->second;
	}
}

std::string songName;

}

using namespace Internal;

static bool disable_music = false;

void Init ( int frequency, int resolution, int sources )
{
	Mix_Init(MIX_INIT_MOD|MIX_INIT_OGG);
	int volume_sound = MIX_MAX_VOLUME, volume_music = MIX_MAX_VOLUME;
	Uint16 format;
	switch (resolution)
	{
		case 8:
			format = AUDIO_S8;
			break;
		case 16:
			format = AUDIO_S16SYS;
			break;
/*		case 24:
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
			format = 0x8018;
#else
			format = 0x9018;
#endif
			break;*/
		default:
            LOG("Sound", LOG_NOTICE, "Unsupported audio format, defaulting to 16-bit");
			format = AUDIO_S16SYS;
			break;
	}
	Mix_OpenAudio(frequency, format, 2, 4096);
	Mix_AllocateChannels(sources);
	Mix_VolumeMusic(volume_music);
	Mix_Volume(-1, volume_sound);
	if (getenv("APOLLO_MUSIC_DISABLE"))
		disable_music = true;
	effectMapLock = SDL_CreateMutex();
	preloadQueueLock = SDL_CreateMutex();
	preloadQueueCondition = SDL_CreateCond();
}

void Preload ( const std::string& name )
{
	SDL_LockMutex(preloadQueueLock);
	preloadQueue.push(name);
	SDL_UnlockMutex(preloadQueueLock);
	SDL_CondSignal(preloadQueueCondition);
}

void PlaySoundSDL ( const std::string& name, float gain, float pan )
{
	Mix_Chunk* chunk = SoundNamed(name);
	if (!chunk)
		return;
	Uint8 ipan = pan * 127;
	int ivolume = gain * (MIX_MAX_VOLUME / 2);
	int channel = Mix_GroupAvailable(-1);
	Mix_UnregisterAllEffects(channel);
	if (ipan != 127)
		Mix_SetPanning(channel, 0xFF - ipan, ipan);
	if (fabs(gain - 1.0f) > 0.0003f)
		Mix_SetDistance(channel, 1 / gain);
	Mix_PlayChannel(channel, chunk, 0);
}

void PlayMusic ( const std::string& music )
{
	if (disable_music)
		return;
	Mix_Music* mus = MusicNamed(music);
	if (mus)
	{
		Mix_PlayMusic(mus, -1);
		songName = music;
	}
}

void StopMusic ()
{
	songName = "(no song)";
	Mix_HaltMusic();
}

std::string MusicName ()
{
	return songName;
}

float MusicVolume ()
{
	return Mix_VolumeMusic(-1) / (float)MIX_MAX_VOLUME;
}

void SetMusicVolume ( float _mvol )
{
	Mix_VolumeMusic(_mvol * MIX_MAX_VOLUME);
}

float SoundVolume ()
{
	return Mix_Volume(-1, -1) / (float)MIX_MAX_VOLUME;
}

void SetSoundVolume ( float _mvol )
{
	Mix_Volume(-1, MIX_MAX_VOLUME * _mvol);
}

}
<|endoftext|>


<commit_before>#include <string.h>
#include <linux/input-event-codes.h>

extern "C"
{
#include <wlr/backend/session.h>
#include <wlr/backend/multi.h>
}

#include "keyboard.hpp"
#include "core.hpp"
#include "input-manager.hpp"
#include "compositor-view.hpp"
#include "input-inhibit.hpp"

static void handle_keyboard_key_cb(wl_listener* listener, void *data)
{
    auto ev = static_cast<wlr_event_keyboard_key*> (data);
    wf_keyboard::listeners *lss = wl_container_of(listener, lss, key);

    auto seat = core->get_current_seat();
    wlr_seat_set_keyboard(seat, lss->keyboard->device);

    if (!core->input->handle_keyboard_key(ev->keycode, ev->state))
    {
        wlr_seat_keyboard_notify_key(core->input->seat, ev->time_msec,
                                     ev->keycode, ev->state);
    }

    wlr_idle_notify_activity(core->protocols.idle, seat);
}

static void handle_keyboard_mod_cb(wl_listener* listener, void* data)
{
    auto kbd = static_cast<wlr_keyboard*> (data);
    wf_keyboard::listeners *lss = wl_container_of(listener, lss, modifier);

    auto seat = core->get_current_seat();
    wlr_seat_set_keyboard(seat, lss->keyboard->device);
    wlr_seat_keyboard_send_modifiers(core->input->seat, &kbd->modifiers);

    wlr_idle_notify_activity(core->protocols.idle, seat);
}

wf_keyboard::wf_keyboard(wlr_input_device *dev, wayfire_config *config)
    : handle(dev->keyboard), device(dev)
{
    auto section = config->get_section("input");

    model   = section->get_option("xkb_model", "");
    variant = section->get_option("xkb_variant", "");
    layout  = section->get_option("xkb_layout", "");
    options = section->get_option("xkb_option", "");
    rules   = section->get_option("xkb_rule", "");

    repeat_rate  = section->get_option("kb_repeat_rate", "40");
    repeat_delay = section->get_option("kb_repeat_delay", "400");

    lss.keyboard = this;
    lss.key.notify      = handle_keyboard_key_cb;
    lss.modifier.notify = handle_keyboard_mod_cb;

    wl_signal_add(&dev->keyboard->events.key,       &lss.key);
    wl_signal_add(&dev->keyboard->events.modifiers, &lss.modifier);

    reload_input_options();
    wlr_seat_set_keyboard(core->get_current_seat(), dev);
}

void wf_keyboard::reload_input_options()
{
    auto ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);

    auto rules = this->rules->as_string();
    auto model = this->model->as_string();
    auto layout = this->layout->as_string();
    auto variant = this->variant->as_string();
    auto options = this->options->as_string();

    xkb_rule_names names;
    names.rules   = rules.c_str();
    names.model   = model.c_str();
    names.layout  = layout.c_str();
    names.variant = variant.c_str();
    names.options = options.c_str();

    auto keymap = xkb_map_new_from_names(ctx, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);

    wlr_keyboard_set_keymap(handle, keymap);

    xkb_keymap_unref(keymap);
    xkb_context_unref(ctx);

    wlr_keyboard_set_repeat_info(handle, repeat_rate->as_int(),
                                 repeat_delay->as_int());
}

wf_keyboard::~wf_keyboard() { }

/* input manager things */

void input_manager::set_keyboard_focus(wayfire_view view, wlr_seat *seat)
{
    auto kbd = wlr_seat_get_keyboard(seat);

    auto surface = view ? view->get_keyboard_focus_surface() : NULL;
    auto iv = interactive_view_from_view(view.get());
    auto oiv = interactive_view_from_view(keyboard_focus.get());

    if (oiv)
        oiv->handle_keyboard_leave();
    if (iv)
        iv->handle_keyboard_enter();

    /* Don't focus if we have an active grab */
    if (kbd != NULL && !active_grab)
    {
        wlr_seat_keyboard_notify_enter(seat, surface, kbd->keycodes,
            kbd->num_keycodes, &kbd->modifiers);
    } else
    {
        wlr_seat_keyboard_notify_enter(seat, surface, NULL, 0, NULL);
    }

    keyboard_focus = view;
}

static bool check_vt_switch(wlr_session *session, uint32_t key, uint32_t mods)
{
    if (!session)
        return false;
    if (mods ^ (WLR_MODIFIER_ALT | WLR_MODIFIER_CTRL))
        return false;

    if (key < KEY_F1 || key > KEY_F10)
        return false;

    /* Somebody inhibited the output, most probably a lockscreen */
    if (is_output_inhibited(core->get_active_output()))
        return false;

    int target_vt = key - KEY_F1 + 1;
    wlr_session_change_vt(session, target_vt);
    return true;
}

static uint32_t mod_from_key(uint32_t key)
{
    if (key == KEY_LEFTALT || key == KEY_RIGHTALT)
        return WLR_MODIFIER_ALT;
    if (key == KEY_LEFTCTRL || key == KEY_RIGHTCTRL)
        return WLR_MODIFIER_CTRL;
    if (key == KEY_LEFTSHIFT || key == KEY_RIGHTSHIFT)
        return WLR_MODIFIER_SHIFT;
    if (key == KEY_LEFTMETA || key == KEY_RIGHTMETA)
        return WLR_MODIFIER_LOGO;

    return 0;
}

std::vector<std::function<void()>> input_manager::match_keys(uint32_t mod_state, uint32_t key, uint32_t mod_binding_key)
{
    std::vector<std::function<void()>> callbacks;

    for (auto& binding : bindings[WF_BINDING_KEY])
    {
        if (binding->value->as_cached_key().matches({mod_state, key}) &&
            binding->output == core->get_active_output())
        {
            /* We must be careful because the callback might be erased,
             * so force copy the callback into the lambda */
            auto callback = binding->call.key;
            callbacks.push_back([key, callback, mod_binding_key] () {
                (*callback) (key == 0 ? mod_binding_key : key);
            });
        }
    }

    for (auto& binding : bindings[WF_BINDING_ACTIVATOR])
    {
        if (binding->value->matches_key({mod_state, key}) &&
            binding->output == core->get_active_output())
        {
            /* We must be careful because the callback might be erased,
             * so force copy the callback into the lambda
             *
             * Also, do not send keys for modifier bindings */
            auto callback = binding->call.activator;
            callbacks.push_back([=] () {
                (*callback) (ACTIVATOR_SOURCE_KEYBINDING,
                    mod_from_key(key) ? 0 : key);
            });
        }
    }

    return callbacks;
}

bool input_manager::handle_keyboard_key(uint32_t key, uint32_t state)
{
    using namespace std::chrono;

    if (active_grab && active_grab->callbacks.keyboard.key)
        active_grab->callbacks.keyboard.key(key, state);

    auto mod = mod_from_key(key);
    if (mod)
        handle_keyboard_mod(mod, state);

    std::vector<std::function<void()>> callbacks;
    auto kbd = wlr_seat_get_keyboard(seat);

    if (state == WLR_KEY_PRESSED)
    {
        if (check_vt_switch(wlr_backend_get_session(core->backend), key, get_modifiers()))
            return true;

        /* as long as we have pressed only modifiers, we should check for modifier bindings on release */
        if (mod)
        {
            bool modifiers_only = !count_other_inputs;
            for (size_t i = 0; i < kbd->num_keycodes; i++)
                if (!mod_from_key(kbd->keycodes[i]))
                    modifiers_only = false;

            in_mod_binding = modifiers_only;

            if (in_mod_binding)
            {
                mod_binding_start = steady_clock::now();
                mod_binding_key = key;
            }
        } else
        {
            in_mod_binding = false;
        }

        callbacks = match_keys(get_modifiers(), key);
    } else
    {
        if (in_mod_binding)
        {
            auto section = core->config->get_section("input");
            auto timeout = section->get_option("modifier_binding_timeout", "0")->as_int();
            if (timeout <= 0 ||
                    duration_cast<milliseconds>(steady_clock::now() - mod_binding_start)
                    <= milliseconds(timeout))
                callbacks = match_keys(get_modifiers() | mod, 0, mod_binding_key);
        }

        in_mod_binding = false;
    }

    for (auto call : callbacks)
        call();

    auto iv = interactive_view_from_view(keyboard_focus.get());
    if (iv) iv->handle_key(key, state);

    return active_grab || !callbacks.empty();
}

void input_manager::handle_keyboard_mod(uint32_t modifier, uint32_t state)
{
    if (active_grab && active_grab->callbacks.keyboard.mod)
        active_grab->callbacks.keyboard.mod(modifier, state);
}

<commit_msg>mod_from_key: use xkbcommon to handle remapped modifiers<commit_after>#include <string.h>
#include <linux/input-event-codes.h>

extern "C"
{
#include <xkbcommon/xkbcommon.h>
#include <wlr/backend/session.h>
#include <wlr/backend/multi.h>
}

#include "keyboard.hpp"
#include "core.hpp"
#include "input-manager.hpp"
#include "compositor-view.hpp"
#include "input-inhibit.hpp"

static void handle_keyboard_key_cb(wl_listener* listener, void *data)
{
    auto ev = static_cast<wlr_event_keyboard_key*> (data);
    wf_keyboard::listeners *lss = wl_container_of(listener, lss, key);

    auto seat = core->get_current_seat();
    wlr_seat_set_keyboard(seat, lss->keyboard->device);

    if (!core->input->handle_keyboard_key(ev->keycode, ev->state))
    {
        wlr_seat_keyboard_notify_key(core->input->seat, ev->time_msec,
                                     ev->keycode, ev->state);
    }

    wlr_idle_notify_activity(core->protocols.idle, seat);
}

static void handle_keyboard_mod_cb(wl_listener* listener, void* data)
{
    auto kbd = static_cast<wlr_keyboard*> (data);
    wf_keyboard::listeners *lss = wl_container_of(listener, lss, modifier);

    auto seat = core->get_current_seat();
    wlr_seat_set_keyboard(seat, lss->keyboard->device);
    wlr_seat_keyboard_send_modifiers(core->input->seat, &kbd->modifiers);

    wlr_idle_notify_activity(core->protocols.idle, seat);
}

wf_keyboard::wf_keyboard(wlr_input_device *dev, wayfire_config *config)
    : handle(dev->keyboard), device(dev)
{
    auto section = config->get_section("input");

    model   = section->get_option("xkb_model", "");
    variant = section->get_option("xkb_variant", "");
    layout  = section->get_option("xkb_layout", "");
    options = section->get_option("xkb_option", "");
    rules   = section->get_option("xkb_rule", "");

    repeat_rate  = section->get_option("kb_repeat_rate", "40");
    repeat_delay = section->get_option("kb_repeat_delay", "400");

    lss.keyboard = this;
    lss.key.notify      = handle_keyboard_key_cb;
    lss.modifier.notify = handle_keyboard_mod_cb;

    wl_signal_add(&dev->keyboard->events.key,       &lss.key);
    wl_signal_add(&dev->keyboard->events.modifiers, &lss.modifier);

    reload_input_options();
    wlr_seat_set_keyboard(core->get_current_seat(), dev);
}

void wf_keyboard::reload_input_options()
{
    auto ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);

    auto rules = this->rules->as_string();
    auto model = this->model->as_string();
    auto layout = this->layout->as_string();
    auto variant = this->variant->as_string();
    auto options = this->options->as_string();

    xkb_rule_names names;
    names.rules   = rules.c_str();
    names.model   = model.c_str();
    names.layout  = layout.c_str();
    names.variant = variant.c_str();
    names.options = options.c_str();

    auto keymap = xkb_map_new_from_names(ctx, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);

    wlr_keyboard_set_keymap(handle, keymap);

    xkb_keymap_unref(keymap);
    xkb_context_unref(ctx);

    wlr_keyboard_set_repeat_info(handle, repeat_rate->as_int(),
                                 repeat_delay->as_int());
}

wf_keyboard::~wf_keyboard() { }

/* input manager things */

void input_manager::set_keyboard_focus(wayfire_view view, wlr_seat *seat)
{
    auto kbd = wlr_seat_get_keyboard(seat);

    auto surface = view ? view->get_keyboard_focus_surface() : NULL;
    auto iv = interactive_view_from_view(view.get());
    auto oiv = interactive_view_from_view(keyboard_focus.get());

    if (oiv)
        oiv->handle_keyboard_leave();
    if (iv)
        iv->handle_keyboard_enter();

    /* Don't focus if we have an active grab */
    if (kbd != NULL && !active_grab)
    {
        wlr_seat_keyboard_notify_enter(seat, surface, kbd->keycodes,
            kbd->num_keycodes, &kbd->modifiers);
    } else
    {
        wlr_seat_keyboard_notify_enter(seat, surface, NULL, 0, NULL);
    }

    keyboard_focus = view;
}

static bool check_vt_switch(wlr_session *session, uint32_t key, uint32_t mods)
{
    if (!session)
        return false;
    if (mods ^ (WLR_MODIFIER_ALT | WLR_MODIFIER_CTRL))
        return false;

    if (key < KEY_F1 || key > KEY_F10)
        return false;

    /* Somebody inhibited the output, most probably a lockscreen */
    if (is_output_inhibited(core->get_active_output()))
        return false;

    int target_vt = key - KEY_F1 + 1;
    wlr_session_change_vt(session, target_vt);
    return true;
}

static uint32_t mod_from_key(wlr_seat *seat, uint32_t key)
{
    xkb_keycode_t keycode = key + 8;
    auto keyboard = wlr_seat_get_keyboard(seat);
    const xkb_keysym_t *keysyms;
    auto keysyms_len = xkb_state_key_get_syms(keyboard->xkb_state, keycode, &keysyms);

    for (int i = 0; i < keysyms_len; i++)
    {
        auto key = keysyms[i];
        if (key == XKB_KEY_Alt_L || key == XKB_KEY_Alt_R)
            return WLR_MODIFIER_ALT;
        if (key == XKB_KEY_Control_L || key == XKB_KEY_Control_R)
            return WLR_MODIFIER_CTRL;
        if (key == XKB_KEY_Shift_L || key == XKB_KEY_Shift_R)
            return WLR_MODIFIER_SHIFT;
        if (key == XKB_KEY_Super_L || key == XKB_KEY_Super_R)
            return WLR_MODIFIER_LOGO;
    }

    return 0;
}

std::vector<std::function<void()>> input_manager::match_keys(uint32_t mod_state, uint32_t key, uint32_t mod_binding_key)
{
    std::vector<std::function<void()>> callbacks;

    for (auto& binding : bindings[WF_BINDING_KEY])
    {
        if (binding->value->as_cached_key().matches({mod_state, key}) &&
            binding->output == core->get_active_output())
        {
            /* We must be careful because the callback might be erased,
             * so force copy the callback into the lambda */
            auto callback = binding->call.key;
            callbacks.push_back([key, callback, mod_binding_key] () {
                (*callback) (key == 0 ? mod_binding_key : key);
            });
        }
    }

    for (auto& binding : bindings[WF_BINDING_ACTIVATOR])
    {
        if (binding->value->matches_key({mod_state, key}) &&
            binding->output == core->get_active_output())
        {
            /* We must be careful because the callback might be erased,
             * so force copy the callback into the lambda
             *
             * Also, do not send keys for modifier bindings */
            auto callback = binding->call.activator;
            callbacks.push_back([=] () {
                (*callback) (ACTIVATOR_SOURCE_KEYBINDING,
                    mod_from_key(seat, key) ? 0 : key);
            });
        }
    }

    return callbacks;
}

bool input_manager::handle_keyboard_key(uint32_t key, uint32_t state)
{
    using namespace std::chrono;

    if (active_grab && active_grab->callbacks.keyboard.key)
        active_grab->callbacks.keyboard.key(key, state);

    auto mod = mod_from_key(seat, key);
    if (mod)
        handle_keyboard_mod(mod, state);

    std::vector<std::function<void()>> callbacks;
    auto kbd = wlr_seat_get_keyboard(seat);

    if (state == WLR_KEY_PRESSED)
    {
        if (check_vt_switch(wlr_backend_get_session(core->backend), key, get_modifiers()))
            return true;

        /* as long as we have pressed only modifiers, we should check for modifier bindings on release */
        if (mod)
        {
            bool modifiers_only = !count_other_inputs;
            for (size_t i = 0; i < kbd->num_keycodes; i++)
                if (!mod_from_key(seat, kbd->keycodes[i]))
                    modifiers_only = false;

            in_mod_binding = modifiers_only;

            if (in_mod_binding)
            {
                mod_binding_start = steady_clock::now();
                mod_binding_key = key;
            }
        } else
        {
            in_mod_binding = false;
        }

        callbacks = match_keys(get_modifiers(), key);
    } else
    {
        if (in_mod_binding)
        {
            auto section = core->config->get_section("input");
            auto timeout = section->get_option("modifier_binding_timeout", "0")->as_int();
            if (timeout <= 0 ||
                    duration_cast<milliseconds>(steady_clock::now() - mod_binding_start)
                    <= milliseconds(timeout))
                callbacks = match_keys(get_modifiers() | mod, 0, mod_binding_key);
        }

        in_mod_binding = false;
    }

    for (auto call : callbacks)
        call();

    auto iv = interactive_view_from_view(keyboard_focus.get());
    if (iv) iv->handle_key(key, state);

    return active_grab || !callbacks.empty();
}

void input_manager::handle_keyboard_mod(uint32_t modifier, uint32_t state)
{
    if (active_grab && active_grab->callbacks.keyboard.mod)
        active_grab->callbacks.keyboard.mod(modifier, state);
}

<|endoftext|>


<commit_before>//
//  main.cpp
//  Unit Tests
//
//  Created by Evan McCartney-Melstad on 12/31/14.
//  Copyright (c) 2014 Evan McCartney-Melstad. All rights reserved.
//

#define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file
#include "../cPWP/generateSimulatedData.h"
#include "../cPWP/bamsToPWP.h"
#include "catch.hpp"
#include <string>

/*
TEST_CASE( "Simulated reads are generated", "[generateReads]" ) {
    // Make sure that the read simulation finishes
    REQUIRE( generateReadsAndMap(1, 0.01, "0.0", "300", "50", "1000000", "100", "1234", "scaffold_0.fasta") == 0);
}
 */

TEST_CASE( "Generate reference genome for simulation tests", "[generateReference]") {
    REQUIRE( createReferenceGenome(100000000, 0.42668722, "simulatedReferenceGenome.fasta") == 0 );
}

TEST_CASE( "Generate mutated reference genomes and simulate reads", "[genomeAndReadSim]") {
    REQUIRE( generateReadsAndMap(5, 0.01, "300", "25", "100", "100", "1234", "simulatedReferenceGenome.fasta", "25") == 0);
}

TEST_CASE( "Run ANGSD on simulated reads", "[runANGSD]" ) {
    REQUIRE( runANGSDforReadCounts("bamlist.txt", "angsdOut", "25", "angsdOutLog.txt") == 0);
}

TEST_CASE( "Convert ANGSD read counts to unsigned chars for major and minor counts", "[convertCountsToBinary]") {
    REQUIRE( convertANGSDcountsToBinary("angsdOut", "angsdOut.readCounts.binary", 6, 5000) == 0); // 3 individuals, not 2, because generateReadsAndMap actually generates n+1 individuals, since one individual is identical to the reference genome. And 5000 as a max because we don't want to exclude any loci for this test
}

TEST_CASE( "Calculate PWP from the binary representations of the ANGSD readcounts", "[calcPWP]") {
    REQUIRE( calcPWPfromBinaryFile ("angsdOut.readCounts.binary", 74963, 6) == 0);
}
<commit_msg>Minor change<commit_after>//
//  main.cpp
//  Unit Tests
//
//  Created by Evan McCartney-Melstad on 12/31/14.
//  Copyright (c) 2014 Evan McCartney-Melstad. All rights reserved.
//

#define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file
#include "../cPWP/generateSimulatedData.h"
#include "../cPWP/bamsToPWP.h"
#include "catch.hpp"
#include <string>

/*
TEST_CASE( "Simulated reads are generated", "[generateReads]" ) {
    // Make sure that the read simulation finishes
    REQUIRE( generateReadsAndMap(1, 0.01, "0.0", "300", "50", "1000000", "100", "1234", "scaffold_0.fasta") == 0);
}
 */

TEST_CASE( "Generate reference genome for simulation tests", "[generateReference]") {
    REQUIRE( createReferenceGenome(100000000, 0.42668722, "simulatedReferenceGenome.fasta") == 0 );
}

TEST_CASE( "Generate mutated reference genomes and simulate reads", "[genomeAndReadSim]") {
    REQUIRE( generateReadsAndMap(3, 0.01, "300", "25", "100", "100", "1234", "simulatedReferenceGenome.fasta", "25") == 0);
}

TEST_CASE( "Run ANGSD on simulated reads", "[runANGSD]" ) {
    REQUIRE( runANGSDforReadCounts("bamlist.txt", "angsdOut", "25", "angsdOutLog.txt") == 0);
}

TEST_CASE( "Convert ANGSD read counts to unsigned chars for major and minor counts", "[convertCountsToBinary]") {
    REQUIRE( convertANGSDcountsToBinary("angsdOut", "angsdOut.readCounts.binary", 4, 5000) == 0); // 3 individuals, not 2, because generateReadsAndMap actually generates n+1 individuals, since one individual is identical to the reference genome. And 5000 as a max because we don't want to exclude any loci for this test
}

TEST_CASE( "Calculate PWP from the binary representations of the ANGSD readcounts", "[calcPWP]") {
    REQUIRE( calcPWPfromBinaryFile ("angsdOut.readCounts.binary", 74963, 4) == 0);
}
<|endoftext|>