<commit_before>/// @file config.cpp
///
/// @brief Implementation of config.hpp
///
/// @author Thomas Vanderbruggen <thomas@koheron.com>
/// @date 20/07/2015
///
/// (c) Koheron 2014-2015

#include <fstream>
#include <string>
#include <cstring>
#include <streambuf>

#include "config.hpp"

namespace kserver {

KServerConfig::KServerConfig()
: verbose(false),
  tcp_nodelay(false),
  syslog(false),
  daemon(true),
  tcp_port(TCP_DFLT_PORT),
  tcp_worker_connections(DFLT_WORKER_CONNECTIONS),
  websock_port(WEBSOCKET_DFLT_PORT),
  websock_worker_connections(DFLT_WORKER_CONNECTIONS),
  unixsock_worker_connections(DFLT_WORKER_CONNECTIONS),
  addr_limit_down(DFLT_ADDR_LIMIT_DOWN),
  addr_limit_up(DFLT_ADDR_LIMIT_UP)
//  interrupt(NULL)
   //sess_interrupt(NULL)
{
   memset(unixsock_path, 0, UNIX_SOCKET_PATH_LEN);
   strcpy(unixsock_path, DFLT_UNIX_SOCK_PATH);
}

char* KServerConfig::_get_source(char *filename)
{
    std::ifstream t(filename);

    if(!t) {
        fprintf(stderr, "Cannot open file %s\n", filename);
        return nullptr;
    }

    std::string config_str;

    t.seekg(0, std::ios::end);
    config_str.reserve(t.tellg());
    t.seekg(0, std::ios::beg);

    config_str.assign((std::istreambuf_iterator<char>(t)),
                       std::istreambuf_iterator<char>());

    t.close();

    char *source = new char[config_str.length() + 1];
    std::strcpy(source, config_str.c_str());
    return source;
}

// Check whether a field is set to "ON" or "OFF"
int is_on(JsonValue value)
{
    if(value.getTag() != JSON_STRING) {
        return -1;
    }

    if(strcmp(value.toString(), "ON") == 0) {
        return 1;
    }
    else if(strcmp(value.toString(), "OFF") == 0) {
        return 0;
    } else {
        return -1;
    }
}

int KServerConfig::_read_verbose(JsonValue value)
{
    int status = is_on(value);

    if(status < 0) {
        fprintf(stderr, "Invalid field verbose\n");
        return -1;
    }

    verbose = status;
    return 0;
}

int KServerConfig::_read_tcp_nodelay(JsonValue value)
{
    int status = is_on(value);

    if(status < 0) {
        fprintf(stderr, "Invalid field tcp_nodelay\n");
        return -1;
    }

    tcp_nodelay = status;
    return 0;
}

int KServerConfig::_read_daemon(JsonValue value)
{
    int status = is_on(value);

    if(status < 0) {
        fprintf(stderr, "Invalid field daemon\n");
        return -1;
    }

    daemon = status;
    return 0;
}

int KServerConfig::_read_log(JsonValue value)
{
    if(value.getTag() != JSON_OBJECT) {
        fprintf(stderr, "Invalid field log\n");
        return -1;
    }

    for(auto i : value) {
        if(strcmp(i->key, "system_log") == 0) {
            int status = is_on(i->value);

            if(status < 0) {
                fprintf(stderr, "Invalid field system_log\n");
                return -1;
            }

            syslog = status;
        } else {
            fprintf(stderr, "Invalid key in log\n");
            return -1;
        }
    }

    return 0;
}

int KServerConfig::_read_server(JsonValue value, server_t serv_type)
{
    if(value.getTag() != JSON_OBJECT) {
        fprintf(stderr, "Invalid TCP field\n");
        return -1;
    }

    for (auto i : value) {
        if(strcmp(i->key, "listen") == 0) {
            if(i->value.getTag() != JSON_NUMBER) {
                fprintf(stderr, "Invalid value in field listen\n");
                return -1;
            }

            if(serv_type == TCP_SERVER) {
                tcp_port = i->value.toNumber();
            }
            else if(serv_type == WEBSOCK_SERVER) {
                websock_port = i->value.toNumber();
            } else { // UNIXSOCK_SERVER
                fprintf(stderr, "Unix socket don't have a listen port\n");
                return -1;
            }
        }
        else if(strcmp(i->key, "path") == 0) {
            if(serv_type != UNIXSOCK_SERVER) {
                fprintf(stderr, "Field path only valid for Unix socket\n");
                return -1;
            }

            if(i->value.getTag() != JSON_STRING) {
                fprintf(stderr, "Invalid value in field path\n");
                return -1;
            }

            memset(unixsock_path, 0, UNIX_SOCKET_PATH_LEN);
            strcpy(unixsock_path, i->value.toString());
        }
        else if(strcmp(i->key, "worker_connections") == 0) {
            if(i->value.getTag() != JSON_NUMBER) {
                fprintf(stderr, "Invalid value in field worker_connections\n");
                return -1;
            }

            if(serv_type == TCP_SERVER) {
                tcp_worker_connections = i->value.toNumber();
            }
            else if(serv_type == WEBSOCK_SERVER) {
                websock_worker_connections = i->value.toNumber();
            }
            else if(serv_type == UNIXSOCK_SERVER) {
                unixsock_worker_connections = i->value.toNumber();
            }
        } else {
            fprintf(stderr, "Unknown server key %s\n", i->key);
            return -1;
        }
    }

    return 0;
}

int KServerConfig::_read_tcp(JsonValue value)
{
    return _read_server(value, TCP_SERVER);
}

int KServerConfig::_read_websocket(JsonValue value)
{
    return _read_server(value, WEBSOCK_SERVER);
}

int KServerConfig::_read_unixsocket(JsonValue value)
{
    return _read_server(value, UNIXSOCK_SERVER);
}

int KServerConfig::_read_addr_limits(JsonValue value)
{
    if(value.getTag() != JSON_OBJECT) {
        fprintf(stderr, "Invalid addr_limits field\n");
        return -1;
    }

    for (auto i : value) {
        if(strcmp(i->key, "up") == 0) {
            if(i->value.getTag() != JSON_STRING) {
                fprintf(stderr, "Address limit up must be a string "
                                "of the hexadecimal address number\n");
                return -1;
            }

            addr_limit_up = (intptr_t)strtol(i->value.toString(), NULL, 0);
        }
        else if(strcmp(i->key, "down") == 0) {
            if(i->value.getTag() != JSON_STRING) {
                fprintf(stderr, "Address limit down must be a string "
                                "of the hexadecimal address number\n");
                return -1;
            }

            addr_limit_down = (intptr_t)strtol(i->value.toString(), NULL, 0);
        }
        else {
            fprintf(stderr, "Unknown addr_limits key %s\n", i->key);
            return -1;
        }
    }

    return 0;
}

void KServerConfig::_check_config()
{
    if(daemon) {
        // Desactivate verbose if run as a daemon
        // since stdout is not available
        verbose = false;

        // In daemon mode it is advisable to
        // activate the syslog since this is the
        // main output for the program
        if(!syslog) {
            printf("NOTICE: You should consider to activate "
                   "the syslog when running KServer as a daemon\n");
        }
    }
}

#define TEST_KEY(key_name)          \
    strcmp(i->key, key_name) == 0

#define IS_VERBOSE      TEST_KEY("verbose")
#define IS_TCP_NODELAY  TEST_KEY("tcp_nodelay")
#define IS_DAEMON       TEST_KEY("daemon")
#define IS_LOGS         TEST_KEY("logs")
#define IS_TCP          TEST_KEY("TCP")
#define IS_WEBSOCKET    TEST_KEY("websocket")
#define IS_UNIX         TEST_KEY("unix")
#define IS_ADDR_LIMITS  TEST_KEY("addr_limits")

int KServerConfig::load_file(char *filename)
{
    char *source = _get_source(filename);

    if(source == nullptr) {
        return -1;
    }

    char *endptr;
    JsonValue value;
    JsonAllocator allocator;

    int status = jsonParse(source, &endptr, &value, allocator);

    if (status != JSON_OK) {
        fprintf(stderr, "JSON Error: %s at %zd\n",
                jsonStrError(status), endptr - source);
        return -1;
    }

    if(value.getTag() != JSON_OBJECT) {
        fprintf(stderr, "Invalid configuration file\n");
        return -1;
    }

    for(auto i : value) {
        if(IS_VERBOSE) {
            if(_read_verbose(i->value) < 0)
                return -1;
        }
        else if(IS_TCP_NODELAY) {
            if(_read_tcp_nodelay(i->value) < 0)
                return -1;
        }
        else if(IS_DAEMON) {
            if(_read_daemon(i->value) < 0)
                return -1;
        }
        else if(IS_LOGS) {
            if(_read_log(i->value) < 0)
                return -1;
        }
        else if(IS_TCP) {
            if(_read_tcp(i->value) < 0)
                return -1;
        }
        else if(IS_WEBSOCKET) {
            if(_read_websocket(i->value) < 0)
                return -1;
        }
        else if(IS_UNIX) {
            if(_read_unixsocket(i->value) < 0)
                return -1;
        }
        else if(IS_ADDR_LIMITS) {
            if(_read_addr_limits(i->value) < 0)
                return -1;
        }
        else {
            fprintf(stderr, "Unknown field %s in configuration file\n", i->key);
            return -1;
        }
    }

    if(verbose) {
        show();
    }

    _check_config();

    delete[] source;

    return 0;
}

void KServerConfig::show()
{
    printf("\n==================\n");
    printf("  KServer config  \n");
    printf("==================\n\n");

    printf("Verbose: %s\n\n", verbose ? "ON": "OFF");
    printf("System log: %s\n\n", syslog ? "ON": "OFF");

    printf("TCP listen: %u\n", tcp_port);
    printf("TCP workers: %u\n\n", tcp_worker_connections);

    printf("Websocket listen: %u\n", websock_port);
    printf("Websocket workers: %u\n\n", websock_worker_connections);

    printf("Addr limit down: %lu\n", addr_limit_down);
    printf("Addr limit up: %lu\n\n", addr_limit_up);
    printf("\n====================================\n\n");
}

} // namespace kserver

<commit_msg>Fix formatting for intptr_t<commit_after>/// @file config.cpp
///
/// @brief Implementation of config.hpp
///
/// @author Thomas Vanderbruggen <thomas@koheron.com>
/// @date 20/07/2015
///
/// (c) Koheron 2014-2015

#include <fstream>
#include <string>
#include <cstring>
#include <streambuf>

#include "config.hpp"

namespace kserver {

KServerConfig::KServerConfig()
: verbose(false),
  tcp_nodelay(false),
  syslog(false),
  daemon(true),
  tcp_port(TCP_DFLT_PORT),
  tcp_worker_connections(DFLT_WORKER_CONNECTIONS),
  websock_port(WEBSOCKET_DFLT_PORT),
  websock_worker_connections(DFLT_WORKER_CONNECTIONS),
  unixsock_worker_connections(DFLT_WORKER_CONNECTIONS),
  addr_limit_down(DFLT_ADDR_LIMIT_DOWN),
  addr_limit_up(DFLT_ADDR_LIMIT_UP)
//  interrupt(NULL)
   //sess_interrupt(NULL)
{
   memset(unixsock_path, 0, UNIX_SOCKET_PATH_LEN);
   strcpy(unixsock_path, DFLT_UNIX_SOCK_PATH);
}

char* KServerConfig::_get_source(char *filename)
{
    std::ifstream t(filename);

    if(!t) {
        fprintf(stderr, "Cannot open file %s\n", filename);
        return nullptr;
    }

    std::string config_str;

    t.seekg(0, std::ios::end);
    config_str.reserve(t.tellg());
    t.seekg(0, std::ios::beg);

    config_str.assign((std::istreambuf_iterator<char>(t)),
                       std::istreambuf_iterator<char>());

    t.close();

    char *source = new char[config_str.length() + 1];
    std::strcpy(source, config_str.c_str());
    return source;
}

// Check whether a field is set to "ON" or "OFF"
int is_on(JsonValue value)
{
    if(value.getTag() != JSON_STRING) {
        return -1;
    }

    if(strcmp(value.toString(), "ON") == 0) {
        return 1;
    }
    else if(strcmp(value.toString(), "OFF") == 0) {
        return 0;
    } else {
        return -1;
    }
}

int KServerConfig::_read_verbose(JsonValue value)
{
    int status = is_on(value);

    if(status < 0) {
        fprintf(stderr, "Invalid field verbose\n");
        return -1;
    }

    verbose = status;
    return 0;
}

int KServerConfig::_read_tcp_nodelay(JsonValue value)
{
    int status = is_on(value);

    if(status < 0) {
        fprintf(stderr, "Invalid field tcp_nodelay\n");
        return -1;
    }

    tcp_nodelay = status;
    return 0;
}

int KServerConfig::_read_daemon(JsonValue value)
{
    int status = is_on(value);

    if(status < 0) {
        fprintf(stderr, "Invalid field daemon\n");
        return -1;
    }

    daemon = status;
    return 0;
}

int KServerConfig::_read_log(JsonValue value)
{
    if(value.getTag() != JSON_OBJECT) {
        fprintf(stderr, "Invalid field log\n");
        return -1;
    }

    for(auto i : value) {
        if(strcmp(i->key, "system_log") == 0) {
            int status = is_on(i->value);

            if(status < 0) {
                fprintf(stderr, "Invalid field system_log\n");
                return -1;
            }

            syslog = status;
        } else {
            fprintf(stderr, "Invalid key in log\n");
            return -1;
        }
    }

    return 0;
}

int KServerConfig::_read_server(JsonValue value, server_t serv_type)
{
    if(value.getTag() != JSON_OBJECT) {
        fprintf(stderr, "Invalid TCP field\n");
        return -1;
    }

    for (auto i : value) {
        if(strcmp(i->key, "listen") == 0) {
            if(i->value.getTag() != JSON_NUMBER) {
                fprintf(stderr, "Invalid value in field listen\n");
                return -1;
            }

            if(serv_type == TCP_SERVER) {
                tcp_port = i->value.toNumber();
            }
            else if(serv_type == WEBSOCK_SERVER) {
                websock_port = i->value.toNumber();
            } else { // UNIXSOCK_SERVER
                fprintf(stderr, "Unix socket don't have a listen port\n");
                return -1;
            }
        }
        else if(strcmp(i->key, "path") == 0) {
            if(serv_type != UNIXSOCK_SERVER) {
                fprintf(stderr, "Field path only valid for Unix socket\n");
                return -1;
            }

            if(i->value.getTag() != JSON_STRING) {
                fprintf(stderr, "Invalid value in field path\n");
                return -1;
            }

            memset(unixsock_path, 0, UNIX_SOCKET_PATH_LEN);
            strcpy(unixsock_path, i->value.toString());
        }
        else if(strcmp(i->key, "worker_connections") == 0) {
            if(i->value.getTag() != JSON_NUMBER) {
                fprintf(stderr, "Invalid value in field worker_connections\n");
                return -1;
            }

            if(serv_type == TCP_SERVER) {
                tcp_worker_connections = i->value.toNumber();
            }
            else if(serv_type == WEBSOCK_SERVER) {
                websock_worker_connections = i->value.toNumber();
            }
            else if(serv_type == UNIXSOCK_SERVER) {
                unixsock_worker_connections = i->value.toNumber();
            }
        } else {
            fprintf(stderr, "Unknown server key %s\n", i->key);
            return -1;
        }
    }

    return 0;
}

int KServerConfig::_read_tcp(JsonValue value)
{
    return _read_server(value, TCP_SERVER);
}

int KServerConfig::_read_websocket(JsonValue value)
{
    return _read_server(value, WEBSOCK_SERVER);
}

int KServerConfig::_read_unixsocket(JsonValue value)
{
    return _read_server(value, UNIXSOCK_SERVER);
}

int KServerConfig::_read_addr_limits(JsonValue value)
{
    if(value.getTag() != JSON_OBJECT) {
        fprintf(stderr, "Invalid addr_limits field\n");
        return -1;
    }

    for (auto i : value) {
        if(strcmp(i->key, "up") == 0) {
            if(i->value.getTag() != JSON_STRING) {
                fprintf(stderr, "Address limit up must be a string "
                                "of the hexadecimal address number\n");
                return -1;
            }

            addr_limit_up = (intptr_t)strtol(i->value.toString(), NULL, 0);
        }
        else if(strcmp(i->key, "down") == 0) {
            if(i->value.getTag() != JSON_STRING) {
                fprintf(stderr, "Address limit down must be a string "
                                "of the hexadecimal address number\n");
                return -1;
            }

            addr_limit_down = (intptr_t)strtol(i->value.toString(), NULL, 0);
        }
        else {
            fprintf(stderr, "Unknown addr_limits key %s\n", i->key);
            return -1;
        }
    }

    return 0;
}

void KServerConfig::_check_config()
{
    if(daemon) {
        // Desactivate verbose if run as a daemon
        // since stdout is not available
        verbose = false;

        // In daemon mode it is advisable to
        // activate the syslog since this is the
        // main output for the program
        if(!syslog) {
            printf("NOTICE: You should consider to activate "
                   "the syslog when running KServer as a daemon\n");
        }
    }
}

#define TEST_KEY(key_name)          \
    strcmp(i->key, key_name) == 0

#define IS_VERBOSE      TEST_KEY("verbose")
#define IS_TCP_NODELAY  TEST_KEY("tcp_nodelay")
#define IS_DAEMON       TEST_KEY("daemon")
#define IS_LOGS         TEST_KEY("logs")
#define IS_TCP          TEST_KEY("TCP")
#define IS_WEBSOCKET    TEST_KEY("websocket")
#define IS_UNIX         TEST_KEY("unix")
#define IS_ADDR_LIMITS  TEST_KEY("addr_limits")

int KServerConfig::load_file(char *filename)
{
    char *source = _get_source(filename);

    if(source == nullptr) {
        return -1;
    }

    char *endptr;
    JsonValue value;
    JsonAllocator allocator;

    int status = jsonParse(source, &endptr, &value, allocator);

    if (status != JSON_OK) {
        fprintf(stderr, "JSON Error: %s at %zd\n",
                jsonStrError(status), endptr - source);
        return -1;
    }

    if(value.getTag() != JSON_OBJECT) {
        fprintf(stderr, "Invalid configuration file\n");
        return -1;
    }

    for(auto i : value) {
        if(IS_VERBOSE) {
            if(_read_verbose(i->value) < 0)
                return -1;
        }
        else if(IS_TCP_NODELAY) {
            if(_read_tcp_nodelay(i->value) < 0)
                return -1;
        }
        else if(IS_DAEMON) {
            if(_read_daemon(i->value) < 0)
                return -1;
        }
        else if(IS_LOGS) {
            if(_read_log(i->value) < 0)
                return -1;
        }
        else if(IS_TCP) {
            if(_read_tcp(i->value) < 0)
                return -1;
        }
        else if(IS_WEBSOCKET) {
            if(_read_websocket(i->value) < 0)
                return -1;
        }
        else if(IS_UNIX) {
            if(_read_unixsocket(i->value) < 0)
                return -1;
        }
        else if(IS_ADDR_LIMITS) {
            if(_read_addr_limits(i->value) < 0)
                return -1;
        }
        else {
            fprintf(stderr, "Unknown field %s in configuration file\n", i->key);
            return -1;
        }
    }

    if(verbose) {
        show();
    }

    _check_config();

    delete[] source;

    return 0;
}

void KServerConfig::show()
{
    printf("\n==================\n");
    printf("  KServer config  \n");
    printf("==================\n\n");

    printf("Verbose: %s\n\n", verbose ? "ON": "OFF");
    printf("System log: %s\n\n", syslog ? "ON": "OFF");

    printf("TCP listen: %u\n", tcp_port);
    printf("TCP workers: %u\n\n", tcp_worker_connections);

    printf("Websocket listen: %u\n", websock_port);
    printf("Websocket workers: %u\n\n", websock_worker_connections);

    // http://stackoverflow.com/questions/5795978/string-format-for-intptr-t-and-uintptr-t
    printf("Addr limit down: %" PRIxPTR "\n", addr_limit_down);
    printf("Addr limit up: %" PRIxPTR "\n\n", addr_limit_up);
    printf("\n====================================\n\n");
}

} // namespace kserver

<|endoftext|>


<commit_before>/**
    @file    change_sorted_array_solution1.cpp
    @author  Altantur Bayarsaikhan (altantur)
    @purpose Find out if only value changed then array can be sorted
    @version 1.0 25/10/17
*/
#include <iostream>
#include <fstream>
using namespace std;

int main(){
    // ifstream test_file;

    // Read from test files
    // test_file.open ("../test/test1.txt");
    // test_file.close();

    // Getting user input
    int n, changes = 0;
    cin >> n;
    int a[n];

    for(int i = 0; i < n; i ++)
        cin >> a[i];

    // To try to mandotary change
    for (int i = 1; i < n; i ++){
        if (i - 1 == 0 && a[i-1] > a[i]){
            a[i-1] = a[i];
            changes ++;
        }
        if (i + 1 == n - 1 && a[i+1] < a[i]){
            a[i+1] = a[i];
            changes ++;
        }
        if (a[i-1] > a[i]){
            a[i] = a[i-1] + a[i+1];
            a[i] /= 2;
            changes ++;
        }
    }

    // Then check lefted change
    for (int i = 1; i < n; i ++){
        if(a[i-1] > a[i])
            changes ++;
    }

    changes > 1 ? cout << "No" << endl : cout << "Yes" << endl;

    return 0;
}

<commit_msg>space vs tab<commit_after>/**
    @file    change_sorted_array_solution1.cpp
    @author  Altantur Bayarsaikhan (altantur)
    @purpose Find out if only value changed then array can be sorted
    @version 1.0 25/10/17
*/
#include <iostream>
#include <fstream>
using namespace std;

int main(){
    // ifstream test_file;

    // Read from test files
    // test_file.open ("../test/test1.txt");
    // test_file.close();

    // Getting user input
    int n, changes = 0;
    cin >> n;
    int a[n];

    for (int i = 0; i < n; i ++)
        cin >> a[i];

    // To try to find at least one change
    for (int i = 1; i < n; i ++){
        if (i - 1 == 0 && a[i-1] > a[i]){
            a[i-1] = a[i];
            changes ++;
        }
        if (i + 1 == n - 1 && a[i+1] < a[i]){
            a[i+1] = a[i];
            changes ++;
        }
        if (a[i-1] > a[i]){
            a[i] = a[i-1] + a[i+1];
            a[i] /= 2;
            changes ++;
        }
    }

    // After above only made mandotary change
    // Then check lefted change
    for (int i = 1; i < n; i ++){
        if(a[i-1] > a[i])
            changes ++;
    }

    changes > 1 ? cout << "No" << endl : cout << "Yes" << endl;

    return 0;
}
<|endoftext|>


<commit_before>#include "runjs.hpp"

/* Structure of JSFunc Python objects */
typedef struct {
    // Required header fields
    PyObject_HEAD
    // The pointer to a compiled SpiderMonkey Function object.
    JS::HandleFunction js_func;
} JSFunc;

static void
JSFunc_dealloc(JSFunc* self) {
    Py_TYPE(self)->tp_free((PyObject*)self);
}

static PyObject *
JSFunc_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
    JSFunc *self;

    self = (JSFunc *)type->tp_alloc(type, 0);
    if (self != NULL) {
        self->js_func = nullptr;
    }

    return (PyObject *)self;
}

static int
JSFunc_init(JSFunc *self, PyObject *args, PyObject *kwds) {
    PyObject* module = PyImport_ImportModule(runjs_module_name);
    if (!module) {
        return -1;
    }

    RunJSModuleState* module_state = (RunJSModuleState*) PyModule_GetState(module);

    // TODO
    const char * function_name = "add";
    const char * file_name = "js.py";
    const int line_no = 17;
    const char * code = "return JSON.stringify(a + b)";
    const unsigned nargs = 2;
    const char *argnames[2] = {"a", "b"};
    JS::HandleFunction compiled_function;
    try {
        compiled_function = compile_js_func(
            module_state, function_name, file_name, line_no,
            nargs, argnames, code
        );
    } catch (const char * err_msg) {
        // TODO set exception info
        PyErr_SetString(PyExc_RuntimeError, err_msg);
        Py_XDECREF(module);
        return -1;
    }
    Py_XDECREF(module);
    self->js_func = compiled_function;
    return 0;
}

static PyObject *
JSFunc_call(PyObject* _self, PyObject *args, PyObject *kwds) {
    // TODO
    const char * arguments_json_cstring = "[2, 3]";
    const unsigned arg_count = 2;

    JSFunc * self = (JSFunc*) _self;

    PyObject* module = PyImport_ImportModule(runjs_module_name);
    if (!module) {
        return NULL;
    }

    RunJSModuleState* module_state = (RunJSModuleState*) PyModule_GetState(module);

    const char * result_cstring;
    try {
        result_cstring = run_js_func(
            module_state, self->js_func, arg_count, arguments_json_cstring
        );
    } catch (const char * err_msg) {
        PyErr_SetString(PyExc_RuntimeError, err_msg);
        return NULL;
    }

    PyObject *result = PyUnicode_FromString(result_cstring);
    delete result_cstring;
    return result;
}

/* Methods of JSFunc */
static PyMethodDef JSFunc_methods[] = {
    {NULL}  /* Sentinel */
};

/* Members of JSFunc */
static PyMemberDef JSFunc_members[] = {
    {NULL}  /* Sentinel */
};

/* Definition of the JSFunc type. */
PyTypeObject JSFuncType = {
    PyVarObject_HEAD_INIT(NULL, 0)
    "runjs.JSFunc",            /* tp_name */
    sizeof(JSFunc),            /* tp_basicsize */
    0,                         /* tp_itemsize */
    (destructor)JSFunc_dealloc,/* tp_dealloc */
    0,                         /* tp_print */
    0,                         /* tp_getattr */
    0,                         /* tp_setattr */
    0,                         /* tp_reserved */
    0,                         /* tp_repr */
    0,                         /* tp_as_number */
    0,                         /* tp_as_sequence */
    0,                         /* tp_as_mapping */
    0,                         /* tp_hash  */
    JSFunc_call,               /* tp_call */
    0,                         /* tp_str */
    0,                         /* tp_getattro */
    0,                         /* tp_setattro */
    0,                         /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
    "JavaScript function",     /* tp_doc */
    0,                         /* tp_traverse */
    0,                         /* tp_clear */
    0,                         /* tp_richcompare */
    0,                         /* tp_weaklistoffset */
    0,                         /* tp_iter */
    0,                         /* tp_iternext */
    JSFunc_methods,            /* tp_methods */
    JSFunc_members,            /* tp_members */
    0,                         /* tp_getset */
    0,                         /* tp_base */
    0,                         /* tp_dict */
    0,                         /* tp_descr_get */
    0,                         /* tp_descr_set */
    0,                         /* tp_dictoffset */
    (initproc)JSFunc_init,     /* tp_init */
    0,                         /* tp_alloc */
    JSFunc_new,                /* tp_new */
};
<commit_msg>working on splitting into separate files<commit_after>#include "runjs.hpp"

/* Structure of JSFunc Python objects */
typedef struct {
    // Required header fields
    PyObject_HEAD
    // The pointer to a compiled SpiderMonkey Function object.
    JS::MutableHandleFunction js_func;
} JSFunc;

static void
JSFunc_dealloc(JSFunc* self) {
    self->js_func.set(NULL);
    Py_TYPE(self)->tp_free((PyObject*)self);
}

static PyObject *
JSFunc_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
    JSFunc *self;

    self = (JSFunc *)type->tp_alloc(type, 0);

    return (PyObject *)self;
}

static int
JSFunc_init(JSFunc *self, PyObject *args, PyObject *kwds) {
    PyObject* module = PyImport_ImportModule(runjs_module_name);
    if (!module) {
        return -1;
    }

    RunJSModuleState* module_state = (RunJSModuleState*) PyModule_GetState(module);

    // TODO
    const char * function_name = "add";
    const char * file_name = "js.py";
    const int line_no = 17;
    const char * code = "return JSON.stringify(a + b)";
    const unsigned nargs = 2;
    const char *argnames[2] = {"a", "b"};
    try {
        JS::HandleFunction compiled_function = compile_js_func(
            module_state, function_name, file_name, line_no,
            nargs, argnames, code
        );
        self->js_func.set(compiled_function);
    } catch (const char * err_msg) {
        // TODO set exception info
        PyErr_SetString(PyExc_RuntimeError, err_msg);
        Py_XDECREF(module);
        return -1;
    }
    Py_XDECREF(module);
    return 0;
}

static PyObject *
JSFunc_call(PyObject* _self, PyObject *args, PyObject *kwds) {
    // TODO
    const char * arguments_json_cstring = "[2, 3]";
    const unsigned arg_count = 2;

    JSFunc * self = (JSFunc*) _self;

    PyObject* module = PyImport_ImportModule(runjs_module_name);
    if (!module) {
        return NULL;
    }

    RunJSModuleState* module_state = (RunJSModuleState*) PyModule_GetState(module);

    const char * result_cstring;
    try {
        result_cstring = run_js_func(
            module_state, self->js_func, arg_count, arguments_json_cstring
        );
    } catch (const char * err_msg) {
        PyErr_SetString(PyExc_RuntimeError, err_msg);
        return NULL;
    }

    PyObject *result = PyUnicode_FromString(result_cstring);
    delete result_cstring;
    return result;
}

/* Methods of JSFunc */
static PyMethodDef JSFunc_methods[] = {
    {NULL}  /* Sentinel */
};

/* Members of JSFunc */
static PyMemberDef JSFunc_members[] = {
    {NULL}  /* Sentinel */
};

/* Definition of the JSFunc type. */
PyTypeObject JSFuncType = {
    PyVarObject_HEAD_INIT(NULL, 0)
    "runjs.JSFunc",            /* tp_name */
    sizeof(JSFunc),            /* tp_basicsize */
    0,                         /* tp_itemsize */
    (destructor)JSFunc_dealloc,/* tp_dealloc */
    0,                         /* tp_print */
    0,                         /* tp_getattr */
    0,                         /* tp_setattr */
    0,                         /* tp_reserved */
    0,                         /* tp_repr */
    0,                         /* tp_as_number */
    0,                         /* tp_as_sequence */
    0,                         /* tp_as_mapping */
    0,                         /* tp_hash  */
    JSFunc_call,               /* tp_call */
    0,                         /* tp_str */
    0,                         /* tp_getattro */
    0,                         /* tp_setattro */
    0,                         /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
    "JavaScript function",     /* tp_doc */
    0,                         /* tp_traverse */
    0,                         /* tp_clear */
    0,                         /* tp_richcompare */
    0,                         /* tp_weaklistoffset */
    0,                         /* tp_iter */
    0,                         /* tp_iternext */
    JSFunc_methods,            /* tp_methods */
    JSFunc_members,            /* tp_members */
    0,                         /* tp_getset */
    0,                         /* tp_base */
    0,                         /* tp_dict */
    0,                         /* tp_descr_get */
    0,                         /* tp_descr_set */
    0,                         /* tp_dictoffset */
    (initproc)JSFunc_init,     /* tp_init */
    0,                         /* tp_alloc */
    JSFunc_new,                /* tp_new */
};
<|endoftext|>


<commit_before>#include "game/states/skirmishstate.hpp"

#include <SFML/Graphics/Sprite.hpp>

#include "game/skirmish/gui/victorydialog.hpp"
#include "game/skirmish/gui/squaredetailwindow.hpp"
#include "game/states/deploystate.hpp"
#include "game/path.hpp"

#include "engine/pathfinding/astar.hpp"
#include "engine/pathfinding/path.hpp"
#include "engine/player.hpp"

#include "gui/texturemanager.hpp"
#include "gui/ng/label.hpp"
#include "gui/ng/spritewidget.hpp"
#include "gui/ng/button.hpp"
#include "gui/cursor.hpp"
#include "gui/squaremarker.hpp"

#include "eventsystem/inputevents.hpp"

namespace qrw
{

SkirmishState::SkirmishState(sf::RenderWindow* renderWindow)
	: SceneState(renderWindow, EGameStateId::EGSID_SKIRMISH_STATE),
	  _selectedUnit(nullptr),
	  m_victoryGui(new namelessgui::Gui(renderWindow))
{
    _squareDetailWindow = new SquareDetailWindow();
    _guiUptr->addWidget(_squareDetailWindow);

	_squareMarker = new SquareMarker();
	_squareMarker->setVisible(false);
	g_scene.addGameObject(_squareMarker);

	_playerNameText = new namelessgui::Text();
	_playerNameText->setText("Player Name");
	_playerNameText->setParentAnchor({0.5, 0});
	_playerNameText->setAnchor({0.5, 0});
	_toolBar->addWidget(_playerNameText);

	namelessgui::Button* endTurnButton = new namelessgui::Button();
	endTurnButton->setText("End Turn");
	endTurnButton->setSize({140, 30});
	endTurnButton->setParentAnchor({0.5, 1});
	endTurnButton->setAnchor({0.5, 1.0});
	endTurnButton->setRelativePosition({0.0f, -5.0f});
	endTurnButton->signalClicked.connect(std::bind(&SkirmishState::endTurn, this));
	_toolBar->addWidget(endTurnButton);

	m_victoryDialog = new VictoryDialog();
	m_victoryDialog->signalCloseClicked.connect(std::bind(&SceneState::slotBackToMainMenu, this));
	m_victoryGui->addWidget(m_victoryDialog);
	m_victoryGui->setVisible(false);
}

void SkirmishState::init(GameState *previousState)
{
    SceneState::init(previousState);

	assert(previousState->getId() == EGameStateId::EGSID_DEPLOY_STATE);

    DeployState* deployState = static_cast<DeployState*>(previousState);

    _board = deployState->getBoard();
	g_scene.setBoard(_board);

	_players = deployState->getPlayers();
	_currentPlayer = 0;
	_playerNameText->setText(_players[_currentPlayer]->getName());

    // Initialize square detail window.
	const Coordinates& cursorPosition = g_scene.findSingleGameObject<Cursor>()->getBoardPosition();
	_squareDetailWindow->display(cursorPosition, *_board, *_players[_currentPlayer]);
}

void SkirmishState::draw()
{
	SceneState::draw();
	m_victoryGui->render(*_renderWindow);
}

bool SkirmishState::handleEvent(const IEvent &event)
{
	SceneState::handleEvent(event);

	if(event.getName() == RightMouseButtonPressedEvent::name)
		deselectSquare();

	return false;
}

EGameStateId SkirmishState::update()
{
    if(_backToMainMenu)
        return EGameStateId::EGSID_MAIN_MENU_STATE;

    return EGameStateId::EGSID_NO_CHANGE;
}

void SkirmishState::slotCursorMoved(const Coordinates &boardPosition)
{
	bool isAbilityApplicable = false;
	if(UnitAbility* selectedAbility = _squareDetailWindow->getSelectedUnitAbility())
	{
		selectedAbility->updateActiveVisualization(boardPosition);
		isAbilityApplicable = selectedAbility->canBeExecutedOn(boardPosition);
	}
	else if(_board->isOnBoard(boardPosition) && _selectedUnit)
	{
		UnitAbility* ability = _selectedUnit->updateAbilitiesToTarget(boardPosition);
		isAbilityApplicable = ability != nullptr;
	}

	Cursor* cursor = g_scene.findSingleGameObject<Cursor>();
	if(!_selectedUnit || isAbilityApplicable) cursor->markValid();
	else cursor->markInvalid();
}

void SkirmishState::slotCursorLeftClicked(const Coordinates& boardPosition)
{
	Unit* unitUnderCursor = _board->getUnit(boardPosition);

	if(_selectedUnit)
	{
		bool abilityExecuted = false;

		if(UnitAbility* selectedAbility = _squareDetailWindow->getSelectedUnitAbility())
		{
			if(selectedAbility->canBeExecutedOn(boardPosition))
			{
				selectedAbility->executeOn(boardPosition);
				abilityExecuted = true;
			}
		}
		else
		{
			abilityExecuted = _selectedUnit->tryExecuteAbility(boardPosition);
		}

		_squareMarker->setBoardPosition(_selectedUnit->getPosition());

		if(_selectedUnit->getCurrentHp() == 0)
			deselectSquare();

		if(abilityExecuted)
			checkVictory();
	}

	if(unitUnderCursor && unitUnderCursor->getPlayer() == _players[_currentPlayer])
	{
		// Select unit
		_selectedUnit = unitUnderCursor;
		_squareMarker->setBoardPosition(boardPosition);
		_squareMarker->setVisible(true);
	}

	if(_selectedUnit)
		_squareDetailWindow->display(_selectedUnit->getPosition(), *_board, *_players[_currentPlayer]);
	else
		_squareDetailWindow->display(boardPosition, *_board, *_players[_currentPlayer]);
}

void SkirmishState::checkVictory()
{
	bool playersHaveUnits[] = {false, false};

	for(auto unitIter : _board->getUnits())
	{
		playersHaveUnits[unitIter.second->getPlayer()->getId() - 1] = true;
	}

	bool gameEnded = !playersHaveUnits[0] || !playersHaveUnits[1];
	if(gameEnded)
	{
		m_victoryDialog->setLoserName(!playersHaveUnits[0] ? _players[0]->getName() : _players[1]->getName());
		m_victoryDialog->setWinnerName(!playersHaveUnits[0] ? _players[1]->getName() : _players[0]->getName());
		m_victoryGui->setVisible(true);
		_guiUptr->setVisible(false);
	}
}

void SkirmishState::replenishTroops()
{
	Unit* unit;
	for(auto unitIter : _board->getUnits())
	{
		unit = unitIter.second;
		unit->setCurrentMovement(unit->getMovement());
	}
}

void SkirmishState::endTurn()
{
	_currentPlayer = (_currentPlayer + 1) % _players.size();
	_playerNameText->setText(_players[_currentPlayer]->getName());

	deselectSquare();
	replenishTroops();
}

void SkirmishState::deselectSquare()
{
	if(_selectedUnit) _selectedUnit->deactivateAllAbilities();

	_selectedUnit = nullptr;
	_squareMarker->setVisible(false);
	g_scene.findSingleGameObject<Cursor>()->markValid();
	_squareDetailWindow->clear();
}

} // namespace qrw
<commit_msg>Activate ability visualization on button click<commit_after>#include "game/states/skirmishstate.hpp"

#include <SFML/Graphics/Sprite.hpp>

#include "game/skirmish/gui/victorydialog.hpp"
#include "game/skirmish/gui/squaredetailwindow.hpp"
#include "game/states/deploystate.hpp"
#include "game/path.hpp"

#include "engine/pathfinding/astar.hpp"
#include "engine/pathfinding/path.hpp"
#include "engine/player.hpp"

#include "gui/texturemanager.hpp"
#include "gui/ng/label.hpp"
#include "gui/ng/spritewidget.hpp"
#include "gui/ng/button.hpp"
#include "gui/cursor.hpp"
#include "gui/squaremarker.hpp"

#include "eventsystem/inputevents.hpp"

namespace qrw
{

SkirmishState::SkirmishState(sf::RenderWindow* renderWindow)
	: SceneState(renderWindow, EGameStateId::EGSID_SKIRMISH_STATE),
	  _selectedUnit(nullptr),
	  m_victoryGui(new namelessgui::Gui(renderWindow))
{
    _squareDetailWindow = new SquareDetailWindow();
    _guiUptr->addWidget(_squareDetailWindow);

	_squareMarker = new SquareMarker();
	_squareMarker->setVisible(false);
	g_scene.addGameObject(_squareMarker);

	_playerNameText = new namelessgui::Text();
	_playerNameText->setText("Player Name");
	_playerNameText->setParentAnchor({0.5, 0});
	_playerNameText->setAnchor({0.5, 0});
	_toolBar->addWidget(_playerNameText);

	namelessgui::Button* endTurnButton = new namelessgui::Button();
	endTurnButton->setText("End Turn");
	endTurnButton->setSize({140, 30});
	endTurnButton->setParentAnchor({0.5, 1});
	endTurnButton->setAnchor({0.5, 1.0});
	endTurnButton->setRelativePosition({0.0f, -5.0f});
	endTurnButton->signalClicked.connect(std::bind(&SkirmishState::endTurn, this));
	_toolBar->addWidget(endTurnButton);

	m_victoryDialog = new VictoryDialog();
	m_victoryDialog->signalCloseClicked.connect(std::bind(&SceneState::slotBackToMainMenu, this));
	m_victoryGui->addWidget(m_victoryDialog);
	m_victoryGui->setVisible(false);
}

void SkirmishState::init(GameState *previousState)
{
    SceneState::init(previousState);

	assert(previousState->getId() == EGameStateId::EGSID_DEPLOY_STATE);

    DeployState* deployState = static_cast<DeployState*>(previousState);

    _board = deployState->getBoard();
	g_scene.setBoard(_board);

	_players = deployState->getPlayers();
	_currentPlayer = 0;
	_playerNameText->setText(_players[_currentPlayer]->getName());

    // Initialize square detail window.
	const Coordinates& cursorPosition = g_scene.findSingleGameObject<Cursor>()->getBoardPosition();
	_squareDetailWindow->display(cursorPosition, *_board, *_players[_currentPlayer]);
}

void SkirmishState::draw()
{
	SceneState::draw();
	m_victoryGui->render(*_renderWindow);
}

bool SkirmishState::handleEvent(const IEvent &event)
{
	SceneState::handleEvent(event);

	if(event.getName() == RightMouseButtonPressedEvent::name)
		deselectSquare();

	return false;
}

EGameStateId SkirmishState::update()
{
    if(_backToMainMenu)
        return EGameStateId::EGSID_MAIN_MENU_STATE;

    return EGameStateId::EGSID_NO_CHANGE;
}

void SkirmishState::slotCursorMoved(const Coordinates &boardPosition)
{
	bool isAbilityApplicable = false;
	if(UnitAbility* selectedAbility = _squareDetailWindow->getSelectedUnitAbility())
	{
		selectedAbility->activate();
		selectedAbility->updateActiveVisualization(boardPosition);
		isAbilityApplicable = selectedAbility->canBeExecutedOn(boardPosition);
	}
	else if(_board->isOnBoard(boardPosition) && _selectedUnit)
	{
		UnitAbility* ability = _selectedUnit->updateAbilitiesToTarget(boardPosition);
		isAbilityApplicable = ability != nullptr;
	}

	Cursor* cursor = g_scene.findSingleGameObject<Cursor>();
	if(!_selectedUnit || isAbilityApplicable) cursor->markValid();
	else cursor->markInvalid();
}

void SkirmishState::slotCursorLeftClicked(const Coordinates& boardPosition)
{
	Unit* unitUnderCursor = _board->getUnit(boardPosition);

	if(_selectedUnit)
	{
		bool abilityExecuted = false;

		if(UnitAbility* selectedAbility = _squareDetailWindow->getSelectedUnitAbility())
		{
			if(selectedAbility->canBeExecutedOn(boardPosition))
			{
				selectedAbility->executeOn(boardPosition);
				abilityExecuted = true;
			}
		}
		else
		{
			abilityExecuted = _selectedUnit->tryExecuteAbility(boardPosition);
		}

		_squareMarker->setBoardPosition(_selectedUnit->getPosition());

		if(_selectedUnit->getCurrentHp() == 0)
			deselectSquare();

		if(abilityExecuted)
			checkVictory();
	}

	if(unitUnderCursor && unitUnderCursor->getPlayer() == _players[_currentPlayer])
	{
		// Select unit
		_selectedUnit = unitUnderCursor;
		_squareMarker->setBoardPosition(boardPosition);
		_squareMarker->setVisible(true);
	}

	if(_selectedUnit)
		_squareDetailWindow->display(_selectedUnit->getPosition(), *_board, *_players[_currentPlayer]);
	else
		_squareDetailWindow->display(boardPosition, *_board, *_players[_currentPlayer]);
}

void SkirmishState::checkVictory()
{
	bool playersHaveUnits[] = {false, false};

	for(auto unitIter : _board->getUnits())
	{
		playersHaveUnits[unitIter.second->getPlayer()->getId() - 1] = true;
	}

	bool gameEnded = !playersHaveUnits[0] || !playersHaveUnits[1];
	if(gameEnded)
	{
		m_victoryDialog->setLoserName(!playersHaveUnits[0] ? _players[0]->getName() : _players[1]->getName());
		m_victoryDialog->setWinnerName(!playersHaveUnits[0] ? _players[1]->getName() : _players[0]->getName());
		m_victoryGui->setVisible(true);
		_guiUptr->setVisible(false);
	}
}

void SkirmishState::replenishTroops()
{
	Unit* unit;
	for(auto unitIter : _board->getUnits())
	{
		unit = unitIter.second;
		unit->setCurrentMovement(unit->getMovement());
	}
}

void SkirmishState::endTurn()
{
	_currentPlayer = (_currentPlayer + 1) % _players.size();
	_playerNameText->setText(_players[_currentPlayer]->getName());

	deselectSquare();
	replenishTroops();
}

void SkirmishState::deselectSquare()
{
	if(_selectedUnit) _selectedUnit->deactivateAllAbilities();

	_selectedUnit = nullptr;
	_squareMarker->setVisible(false);
	g_scene.findSingleGameObject<Cursor>()->markValid();
	_squareDetailWindow->clear();
}

} // namespace qrw
<|endoftext|>


<commit_before>#include "chainerx/cuda/memory_pool.h"

#include <algorithm>
#include <iterator>
#include <mutex>
#include <unordered_map>
#include <vector>

#include "chainerx/cuda/cuda_runtime.h"
#include "chainerx/cuda/cuda_set_device_scope.h"
#include "chainerx/macro.h"

namespace chainerx {
namespace cuda {

MallocStatus DeviceMemoryAllocator::Malloc(void** ptr, size_t bytesize) {
    cudaError_t status = cudaMallocManaged(ptr, bytesize, cudaMemAttachGlobal);
    switch (status) {
        case cudaSuccess:
            return MallocStatus::kSuccess;
        case cudaErrorMemoryAllocation:
            return MallocStatus::kErrorMemoryAllocation;
        default:
            Throw(status);
    }
    CHAINERX_NEVER_REACH();
}

MallocStatus PinnedMemoryAllocator::Malloc(void** ptr, size_t bytesize) {
    cudaError_t status = cudaHostAlloc(ptr, bytesize, cudaHostAllocWriteCombined);
    switch (status) {
        case cudaSuccess:
            return MallocStatus::kSuccess;
        case cudaErrorMemoryAllocation:
            return MallocStatus::kErrorMemoryAllocation;
        default:
            Throw(status);
    }
    CHAINERX_NEVER_REACH();
}

std::unique_ptr<Chunk> Chunk::Split(size_t bytesize) {
    CHAINERX_ASSERT(bytesize_ >= bytesize);
    if (bytesize_ == bytesize) {
        return nullptr;
    }

    std::unique_ptr<Chunk> remaining = std::make_unique<Chunk>(ptr(), bytesize, bytesize_ - bytesize);
    bytesize_ = bytesize;

    if (next_ != nullptr) {
        remaining->SetNext(next_);
        remaining->next()->SetPrev(remaining.get());
    }
    next_ = remaining.get();
    remaining->SetPrev(this);

    return remaining;
}

void Chunk::MergeWithNext() {
    CHAINERX_ASSERT(next_ != nullptr);
    bytesize_ += next_->bytesize();
    if (next_->next() != nullptr) {
        next_->next()->SetPrev(this);
    }
    next_ = next_->next();
}

// Pushes a chunk into an appropriate free list
//
// Not thread-safe
void MemoryPool::PushIntoFreeList(std::unique_ptr<Chunk> chunk) {
    FreeList& free_list = free_bins_[chunk->bytesize()];
    free_list.emplace_back(std::move(chunk));
}

void MemoryPool::CompactFreeBins(std::map<size_t, FreeList>::iterator it_start, std::map<size_t, FreeList>::iterator it_end) {
    auto it_start_rev = std::make_reverse_iterator(it_start);
    it_start = std::find_if(it_start_rev, free_bins_.rend(), [](const auto& p) { return !p.second.empty(); }).base();
    it_end = std::find_if(it_end, free_bins_.end(), [](const auto& p) { return !p.second.empty(); });
    free_bins_.erase(it_start, it_end);
}

// Finds best-fit, or a smallest larger allocation if available
//
// Not thread-safe
std::unique_ptr<Chunk> MemoryPool::PopFromFreeList(size_t allocation_size) {
    auto it_start = free_bins_.lower_bound(allocation_size);
    size_t distance{0};
    for (auto it = it_start; it != free_bins_.end(); ++it, ++distance) {
        FreeList& free_list = it->second;
        if (free_list.empty()) {
            continue;
        }
        std::unique_ptr<Chunk> chunk = std::move(free_list.back());
        CHAINERX_ASSERT(chunk != nullptr);
        free_list.pop_back();
        if (distance > kCompactionThreashold) {
            CompactFreeBins(it_start, it);
        }
        return chunk;
    }

    return nullptr;
}

// Removes a chunk from an appropriate free list, and returns the removed chunk
//
// Not thread-safe
std::unique_ptr<Chunk> MemoryPool::RemoveChunkFromFreeList(Chunk* chunk) {
    CHAINERX_ASSERT(chunk != nullptr);

    // Find an appropriate free list
    auto free_bins_it = free_bins_.find(chunk->bytesize());
    if (free_bins_it == free_bins_.end()) {
        return nullptr;
    }
    FreeList& free_list = free_bins_it->second;

    // Remove the given chunk from the found free list
    auto it = std::find_if(free_list.begin(), free_list.end(), [chunk](const auto& ptr) { return ptr.get() == chunk; });
    if (it == free_list.end()) return nullptr;
    std::unique_ptr<Chunk> chunk_uniq_ptr = std::move(*it);
    CHAINERX_ASSERT(chunk_uniq_ptr != nullptr);
    free_list.erase(it);
    return chunk_uniq_ptr;
}

MemoryPool::~MemoryPool() {
    // NOTE: CudaSetDeviceScope is not available at dtor because it may throw
    int orig_device_index{0};
    cudaGetDevice(&orig_device_index);
    cudaSetDevice(device_index_);

    for (std::pair<const size_t, FreeList>& item : free_bins_) {
        FreeList& free_list = item.second;
        for (const std::unique_ptr<Chunk>& chunk : free_list) {
            if (chunk->prev() == nullptr) {
                allocator_->Free(chunk->ptr());
            }
        }
    }
    // Ideally, in_use_ should be empty, but it could happen that shared ptrs to memories allocated
    // by this memory pool are released after this memory pool is destructed.
    // Our approach is that we anyway free CUDA memories held by this memory pool here in such case.
    // Operators of arrays holding such memories will be broken, but are not supported.
    for (const std::pair<void* const, std::unique_ptr<Chunk>>& item : in_use_) {
        const std::unique_ptr<Chunk>& chunk = item.second;
        if (chunk->prev() == nullptr) {
            allocator_->Free(chunk->ptr());
        }
    }

    cudaSetDevice(orig_device_index);
}

void MemoryPool::FreeUnusedBlocks() {
    CudaSetDeviceScope scope{device_index_};

    // Frees unused memory blocks
    for (std::pair<const size_t, FreeList>& pair : free_bins_) {
        FreeList& free_list = pair.second;
        for (std::unique_ptr<Chunk>& chunk : free_list) {
            if (chunk->next() == nullptr && chunk->prev() == nullptr) {
                allocator_->Free(chunk->ptr());
                chunk.reset();
            }
        }
        free_list.erase(std::remove(free_list.begin(), free_list.end(), nullptr), free_list.end());
    }

    // Erase empty free lists from free bins.
    for (auto free_bins_it = free_bins_.begin(); free_bins_it != free_bins_.end();) {
        if (free_bins_it->second.empty()) {
            free_bins_it = free_bins_.erase(free_bins_it);
        } else {
            free_bins_it++;
        }
    }
}

void* MemoryPool::Malloc(size_t bytesize) {
    if (bytesize == 0) {
        return nullptr;
    }

    // TODO(niboshi): Currently the deleter of allocated memory assumes that
    // the memory is stored in the memory pool (in `in_use_`), but this may not hold if some exception is thrown before it is stored.
    // `std::lock_guard` and `in_use_.emplace` are the sources of possible exceptions.

    size_t allocation_size = GetAllocationSize(bytesize);
    std::unique_ptr<Chunk> chunk{nullptr};

    {
        std::lock_guard<std::mutex> lock{free_bins_mutex_};
        chunk = PopFromFreeList(allocation_size);
    }

    if (chunk != nullptr) {
        std::unique_ptr<Chunk> remaining = chunk->Split(allocation_size);
        if (remaining != nullptr) {
            std::lock_guard<std::mutex> lock{free_bins_mutex_};
            PushIntoFreeList(std::move(remaining));
        }
    } else {
        void* ptr{nullptr};
        CudaSetDeviceScope scope{device_index_};
        MallocStatus status = allocator_->Malloc(&ptr, allocation_size);
        if (status == MallocStatus::kErrorMemoryAllocation) {
            FreeUnusedBlocks();
            status = allocator_->Malloc(&ptr, allocation_size);
            if (status == MallocStatus::kErrorMemoryAllocation) {
                // TODO(sonots): Include total pooled bytes in the error message
                throw OutOfMemoryError{bytesize};
            }
        }
        chunk = std::make_unique<Chunk>(ptr, 0, allocation_size);
    }

    CHAINERX_ASSERT(chunk != nullptr);
    void* ptr = chunk->ptr();
    {
        std::lock_guard<std::mutex> lock{in_use_mutex_};
        in_use_.emplace(ptr, std::move(chunk));
    }
    return ptr;
}

void MemoryPool::Free(void* ptr) {
    if (ptr == nullptr) {
        return;
    }
    std::unique_ptr<Chunk> chunk{nullptr};

    {
        std::lock_guard<std::mutex> lock{in_use_mutex_};
        auto it = in_use_.find(ptr);
        if (it == in_use_.end()) {
            throw ChainerxError{"Cannot free out-of-pool memory"};
        }
        chunk = std::move(it->second);
        in_use_.erase(it);
    }

    CHAINERX_ASSERT(chunk != nullptr);
    {
        std::lock_guard<std::mutex> lock{free_bins_mutex_};

        // If the next chunk is free, merges it with them.
        if (chunk->next() != nullptr) {
            std::unique_ptr<Chunk> chunk_next = RemoveChunkFromFreeList(chunk->next());
            if (chunk_next != nullptr) {
                chunk->MergeWithNext();
            }
        }

        // If the previous chunk is free, merges it with them.
        if (chunk->prev() != nullptr) {
            std::unique_ptr<Chunk> chunk_prev = RemoveChunkFromFreeList(chunk->prev());
            if (chunk_prev != nullptr) {
                chunk_prev->MergeWithNext();
                chunk = std::move(chunk_prev);
            }
        }

        PushIntoFreeList(std::move(chunk));
    }
}

void MemoryPool::FreeNoExcept(void* ptr) noexcept {
    try {
        Free(ptr);
    } catch (...) {
        CHAINERX_NEVER_REACH();
    }
}

}  // namespace cuda
}  // namespace chainerx
<commit_msg>cosmetics<commit_after>#include "chainerx/cuda/memory_pool.h"

#include <algorithm>
#include <iterator>
#include <mutex>
#include <unordered_map>
#include <vector>

#include "chainerx/cuda/cuda_runtime.h"
#include "chainerx/cuda/cuda_set_device_scope.h"
#include "chainerx/macro.h"

namespace chainerx {
namespace cuda {

MallocStatus DeviceMemoryAllocator::Malloc(void** ptr, size_t bytesize) {
    cudaError_t status = cudaMallocManaged(ptr, bytesize, cudaMemAttachGlobal);
    switch (status) {
        case cudaSuccess:
            return MallocStatus::kSuccess;
        case cudaErrorMemoryAllocation:
            return MallocStatus::kErrorMemoryAllocation;
        default:
            Throw(status);
    }
    CHAINERX_NEVER_REACH();
}

MallocStatus PinnedMemoryAllocator::Malloc(void** ptr, size_t bytesize) {
    cudaError_t status = cudaHostAlloc(ptr, bytesize, cudaHostAllocWriteCombined);
    switch (status) {
        case cudaSuccess:
            return MallocStatus::kSuccess;
        case cudaErrorMemoryAllocation:
            return MallocStatus::kErrorMemoryAllocation;
        default:
            Throw(status);
    }
    CHAINERX_NEVER_REACH();
}

std::unique_ptr<Chunk> Chunk::Split(size_t bytesize) {
    CHAINERX_ASSERT(bytesize_ >= bytesize);
    if (bytesize_ == bytesize) {
        return nullptr;
    }

    std::unique_ptr<Chunk> remaining = std::make_unique<Chunk>(ptr(), bytesize, bytesize_ - bytesize);
    bytesize_ = bytesize;

    if (next_ != nullptr) {
        remaining->SetNext(next_);
        remaining->next()->SetPrev(remaining.get());
    }
    next_ = remaining.get();
    remaining->SetPrev(this);

    return remaining;
}

void Chunk::MergeWithNext() {
    CHAINERX_ASSERT(next_ != nullptr);
    bytesize_ += next_->bytesize();
    if (next_->next() != nullptr) {
        next_->next()->SetPrev(this);
    }
    next_ = next_->next();
}

// Pushes a chunk into an appropriate free list
//
// Not thread-safe
void MemoryPool::PushIntoFreeList(std::unique_ptr<Chunk> chunk) {
    FreeList& free_list = free_bins_[chunk->bytesize()];
    free_list.emplace_back(std::move(chunk));
}

void MemoryPool::CompactFreeBins(std::map<size_t, FreeList>::iterator it_start, std::map<size_t, FreeList>::iterator it_end) {
    auto it_start_rev = std::make_reverse_iterator(it_start);
    it_start = std::find_if(it_start_rev, free_bins_.rend(), [](const auto& p) { return !p.second.empty(); }).base();
    it_end = std::find_if(it_end, free_bins_.end(), [](const auto& p) { return !p.second.empty(); });
    free_bins_.erase(it_start, it_end);
}

// Finds best-fit, or a smallest larger allocation if available
//
// Not thread-safe
std::unique_ptr<Chunk> MemoryPool::PopFromFreeList(size_t allocation_size) {
    auto it_start = free_bins_.lower_bound(allocation_size);
    auto non_empty_it = std::find_if(it_start, free_bins_.end(), [](const auto& pair) { return !pair.second.empty(); });
    if (non_empty_it == free_bins_.end()) {
        return nullptr;
    }
    FreeList& free_list = non_empty_it->second;
    std::unique_ptr<Chunk> chunk = std::move(free_list.back());
    CHAINERX_ASSERT(chunk != nullptr);
    free_list.pop_back();
    if (static_cast<size_t>(std::distance(it_start, non_empty_it)) > kCompactionThreashold) {
        CompactFreeBins(it_start, non_empty_it);
    }
    return chunk;
}

// Removes a chunk from an appropriate free list, and returns the removed chunk
//
// Not thread-safe
std::unique_ptr<Chunk> MemoryPool::RemoveChunkFromFreeList(Chunk* chunk) {
    CHAINERX_ASSERT(chunk != nullptr);

    // Find an appropriate free list
    auto free_bins_it = free_bins_.find(chunk->bytesize());
    if (free_bins_it == free_bins_.end()) {
        return nullptr;
    }
    FreeList& free_list = free_bins_it->second;

    // Remove the given chunk from the found free list
    auto it = std::find_if(free_list.begin(), free_list.end(), [chunk](const auto& ptr) { return ptr.get() == chunk; });
    if (it == free_list.end()) return nullptr;
    std::unique_ptr<Chunk> removed_chunk = std::move(*it);
    CHAINERX_ASSERT(removed_chunk != nullptr);
    free_list.erase(it);
    return removed_chunk;
}

MemoryPool::~MemoryPool() {
    // NOTE: CudaSetDeviceScope is not available at dtor because it may throw
    int orig_device_index{0};
    cudaGetDevice(&orig_device_index);
    cudaSetDevice(device_index_);

    for (std::pair<const size_t, FreeList>& item : free_bins_) {
        FreeList& free_list = item.second;
        for (const std::unique_ptr<Chunk>& chunk : free_list) {
            if (chunk->prev() == nullptr) {
                allocator_->Free(chunk->ptr());
            }
        }
    }
    // Ideally, in_use_ should be empty, but it could happen that shared ptrs to memories allocated
    // by this memory pool are released after this memory pool is destructed.
    // Our approach is that we anyway free CUDA memories held by this memory pool here in such case.
    // Operators of arrays holding such memories will be broken, but are not supported.
    for (const std::pair<void* const, std::unique_ptr<Chunk>>& item : in_use_) {
        const std::unique_ptr<Chunk>& chunk = item.second;
        if (chunk->prev() == nullptr) {
            allocator_->Free(chunk->ptr());
        }
    }

    cudaSetDevice(orig_device_index);
}

void MemoryPool::FreeUnusedBlocks() {
    CudaSetDeviceScope scope{device_index_};

    // Frees unused memory blocks
    for (std::pair<const size_t, FreeList>& pair : free_bins_) {
        FreeList& free_list = pair.second;
        for (std::unique_ptr<Chunk>& chunk : free_list) {
            if (chunk->next() == nullptr && chunk->prev() == nullptr) {
                allocator_->Free(chunk->ptr());
                chunk.reset();
            }
        }
        free_list.erase(std::remove(free_list.begin(), free_list.end(), nullptr), free_list.end());
    }

    // Erase empty free lists from free bins.
    for (auto free_bins_it = free_bins_.begin(); free_bins_it != free_bins_.end();) {
        if (free_bins_it->second.empty()) {
            free_bins_it = free_bins_.erase(free_bins_it);
        } else {
            free_bins_it++;
        }
    }
}

void* MemoryPool::Malloc(size_t bytesize) {
    if (bytesize == 0) {
        return nullptr;
    }

    // TODO(niboshi): Currently the deleter of allocated memory assumes that
    // the memory is stored in the memory pool (in `in_use_`), but this may not hold if some exception is thrown before it is stored.
    // `std::lock_guard` and `in_use_.emplace` are the sources of possible exceptions.

    size_t allocation_size = GetAllocationSize(bytesize);
    std::unique_ptr<Chunk> chunk{nullptr};

    {
        std::lock_guard<std::mutex> lock{free_bins_mutex_};
        chunk = PopFromFreeList(allocation_size);
    }

    if (chunk != nullptr) {
        std::unique_ptr<Chunk> remaining = chunk->Split(allocation_size);
        if (remaining != nullptr) {
            std::lock_guard<std::mutex> lock{free_bins_mutex_};
            PushIntoFreeList(std::move(remaining));
        }
    } else {
        void* ptr{nullptr};
        CudaSetDeviceScope scope{device_index_};
        MallocStatus status = allocator_->Malloc(&ptr, allocation_size);
        if (status == MallocStatus::kErrorMemoryAllocation) {
            FreeUnusedBlocks();
            status = allocator_->Malloc(&ptr, allocation_size);
            if (status == MallocStatus::kErrorMemoryAllocation) {
                // TODO(sonots): Include total pooled bytes in the error message
                throw OutOfMemoryError{bytesize};
            }
        }
        chunk = std::make_unique<Chunk>(ptr, 0, allocation_size);
    }

    CHAINERX_ASSERT(chunk != nullptr);
    void* ptr = chunk->ptr();
    {
        std::lock_guard<std::mutex> lock{in_use_mutex_};
        in_use_.emplace(ptr, std::move(chunk));
    }
    return ptr;
}

void MemoryPool::Free(void* ptr) {
    if (ptr == nullptr) {
        return;
    }
    std::unique_ptr<Chunk> chunk{nullptr};

    {
        std::lock_guard<std::mutex> lock{in_use_mutex_};
        auto it = in_use_.find(ptr);
        if (it == in_use_.end()) {
            throw ChainerxError{"Cannot free out-of-pool memory"};
        }
        chunk = std::move(it->second);
        in_use_.erase(it);
    }

    CHAINERX_ASSERT(chunk != nullptr);
    {
        std::lock_guard<std::mutex> lock{free_bins_mutex_};

        // If the next chunk is free, merges it with them.
        if (chunk->next() != nullptr) {
            std::unique_ptr<Chunk> chunk_next = RemoveChunkFromFreeList(chunk->next());
            if (chunk_next != nullptr) {
                chunk->MergeWithNext();
            }
        }

        // If the previous chunk is free, merges it with them.
        if (chunk->prev() != nullptr) {
            std::unique_ptr<Chunk> chunk_prev = RemoveChunkFromFreeList(chunk->prev());
            if (chunk_prev != nullptr) {
                chunk_prev->MergeWithNext();
                chunk = std::move(chunk_prev);
            }
        }

        PushIntoFreeList(std::move(chunk));
    }
}

void MemoryPool::FreeNoExcept(void* ptr) noexcept {
    try {
        Free(ptr);
    } catch (...) {
        CHAINERX_NEVER_REACH();
    }
}

}  // namespace cuda
}  // namespace chainerx
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/focus/accelerator_handler.h"

#include <bitset>
#include <gtk/gtk.h>
#if defined(HAVE_XINPUT2)
#include <X11/extensions/XInput2.h>
#else
#include <X11/Xlib.h>
#endif

#include "views/accelerator.h"
#include "views/event.h"
#include "views/focus/focus_manager.h"
#include "views/widget/root_view.h"
#include "views/widget/widget_gtk.h"

namespace views {

#if defined(HAVE_XINPUT2)
// Functions related to determining touch devices.
class TouchFactory {
 public:
  // Keep a list of touch devices so that it is possible to determine if a
  // pointer event is a touch-event or a mouse-event.
  static void SetTouchDeviceListInternal(
      const std::vector<unsigned int>& devices) {
    for (std::vector<unsigned int>::const_iterator iter = devices.begin();
        iter != devices.end(); ++iter) {
      DCHECK(*iter < touch_devices.size());
      touch_devices[*iter] = true;
    }
  }

  // Is the device a touch-device?
  static bool IsTouchDevice(unsigned int deviceid) {
    return deviceid < touch_devices.size() ? touch_devices[deviceid] : false;
  }

 private:
  // A quick lookup table for determining if a device is a touch device.
  static std::bitset<128> touch_devices;

  DISALLOW_COPY_AND_ASSIGN(TouchFactory);
};

std::bitset<128> TouchFactory::touch_devices;
#endif

namespace {

RootView* FindRootViewForGdkWindow(GdkWindow* gdk_window) {
  gpointer data = NULL;
  gdk_window_get_user_data(gdk_window, &data);
  GtkWidget* gtk_widget = reinterpret_cast<GtkWidget*>(data);
  if (!gtk_widget || !GTK_IS_WIDGET(gtk_widget)) {
    DLOG(WARNING) << "no GtkWidget found for that GdkWindow";
    return NULL;
  }
  WidgetGtk* widget_gtk = WidgetGtk::GetViewForNative(gtk_widget);

  if (!widget_gtk) {
    DLOG(WARNING) << "no WidgetGtk found for that GtkWidget";
    return NULL;
  }
  return widget_gtk->GetRootView();
}

#if defined(HAVE_XINPUT2)
bool X2EventIsTouchEvent(XEvent* xev) {
  // TODO(sad): Determine if the captured event is a touch-event.
  XGenericEventCookie* cookie = &xev->xcookie;
  switch (cookie->evtype) {
    case XI_ButtonPress:
    case XI_ButtonRelease:
    case XI_Motion: {
      // Is the event coming from a touch device?
      return TouchFactory::IsTouchDevice(
          static_cast<XIDeviceEvent*>(cookie->data)->sourceid);
    }
    default:
      return false;
  }
}
#endif  // HAVE_XINPUT2

}  // namespace

#if defined(HAVE_XINPUT2)
bool DispatchX2Event(RootView* root, XEvent* xev) {
  if (X2EventIsTouchEvent(xev)) {
    // Create a TouchEvent, and send it off to |root|. If the event
    // is processed by |root|, then return. Otherwise let it fall through so it
    // can be used (if desired) as a mouse event.

    TouchEvent touch(xev);
    if (root->OnTouchEvent(touch))
      return true;
  }

  XGenericEventCookie* cookie = &xev->xcookie;

  switch (cookie->evtype) {
    case XI_KeyPress:
    case XI_KeyRelease: {
      // TODO(sad): We don't capture XInput2 events from keyboard yet.
      break;
    }
    case XI_ButtonPress:
    case XI_ButtonRelease: {
      MouseEvent mouseev(xev);
      if (cookie->evtype == XI_ButtonPress) {
        return root->OnMousePressed(mouseev);
      } else {
        root->OnMouseReleased(mouseev, false);
        return true;
      }
    }

    case XI_Motion: {
      MouseEvent mouseev(xev);
      if (mouseev.GetType() == Event::ET_MOUSE_DRAGGED) {
        return root->OnMouseDragged(mouseev);
      } else {
        root->OnMouseMoved(mouseev);
        return true;
      }
      break;
    }
  }

  return false;
}

#endif  // HAVE_XINPUT2

bool DispatchXEvent(XEvent* xev) {
  GdkDisplay* gdisp = gdk_display_get_default();
  XID xwindow = xev->xany.window;

#if defined(HAVE_XINPUT2)
  if (xev->type == GenericEvent) {
    XGenericEventCookie* cookie = &xev->xcookie;
    XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(cookie->data);
    xwindow = xiev->event;
  }
#endif

  GdkWindow* gwind = gdk_window_lookup_for_display(gdisp, xwindow);

  if (RootView* root = FindRootViewForGdkWindow(gwind)) {
    switch (xev->type) {
      case KeyPress: {
        // If Tab is pressed, then the RootView needs to process it first,
        // because the focus-manager will move the focus to the next focusable
        // view, without letting the currently focused view process it (which
        // means, for example, tab-ing to move focus between fields/links in a
        // RenderWidgetHostViewViews won't work). For all other keys, let the
        // focus manager process it first so that the keyboard accelerators can
        // be triggered.
        KeyEvent keyev(xev);
        FocusManager* focus_manager = root->GetFocusManager();
        if (FocusManager::IsTabTraversalKeyEvent(keyev)) {
          return root->ProcessKeyEvent(keyev) ||
              (focus_manager && !focus_manager->OnKeyEvent(keyev));
        } else {
          return (focus_manager && !focus_manager->OnKeyEvent(keyev)) ||
              root->ProcessKeyEvent(keyev);
        }
      }

      case KeyRelease:
        return root->ProcessKeyEvent(KeyEvent(xev));

      case ButtonPress:
      case ButtonRelease: {
        if (xev->xbutton.button == 4 || xev->xbutton.button == 5) {
          // Scrolling the wheel triggers button press/release events.
          MouseWheelEvent wheelev(xev);
          return root->ProcessMouseWheelEvent(wheelev);
        } else {
          MouseEvent mouseev(xev);
          if (xev->type == ButtonPress) {
            return root->OnMousePressed(mouseev);
          } else {
            root->OnMouseReleased(mouseev, false);
            return true;  // Assume the event has been processed to make sure we
                          // don't process it twice.
          }
        }
      }

      case MotionNotify: {
        MouseEvent mouseev(xev);
        if (mouseev.GetType() == Event::ET_MOUSE_DRAGGED) {
          return root->OnMouseDragged(mouseev);
        } else {
          root->OnMouseMoved(mouseev);
          return true;
        }
      }

#if defined(HAVE_XINPUT2)
      case GenericEvent: {
        return DispatchX2Event(root, xev);
      }
#endif
    }
  }

  return false;
}

#if defined(HAVE_XINPUT2)
void SetTouchDeviceList(std::vector<unsigned int>& devices) {
  TouchFactory::SetTouchDeviceListInternal(devices);
}
#endif

AcceleratorHandler::AcceleratorHandler() {}

bool AcceleratorHandler::Dispatch(GdkEvent* event) {
  gtk_main_do_event(event);
  return true;
}

base::MessagePumpGlibXDispatcher::DispatchStatus AcceleratorHandler::Dispatch(
    XEvent* xev) {
  return DispatchXEvent(xev) ?
      base::MessagePumpGlibXDispatcher::EVENT_PROCESSED :
      base::MessagePumpGlibXDispatcher::EVENT_IGNORED;
}

}  // namespace views
<commit_msg>touch: Fix buildbot.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/focus/accelerator_handler.h"

#include <bitset>
#include <gtk/gtk.h>
#if defined(HAVE_XINPUT2)
#include <X11/extensions/XInput2.h>
#else
#include <X11/Xlib.h>
#endif

#include "views/accelerator.h"
#include "views/event.h"
#include "views/focus/focus_manager.h"
#include "views/widget/root_view.h"
#include "views/widget/widget_gtk.h"

namespace views {

#if defined(HAVE_XINPUT2)
// Functions related to determining touch devices.
class TouchFactory {
 public:
  // Keep a list of touch devices so that it is possible to determine if a
  // pointer event is a touch-event or a mouse-event.
  static void SetTouchDeviceListInternal(
      const std::vector<unsigned int>& devices) {
    for (std::vector<unsigned int>::const_iterator iter = devices.begin();
        iter != devices.end(); ++iter) {
      DCHECK(*iter < touch_devices.size());
      touch_devices[*iter] = true;
    }
  }

  // Is the device a touch-device?
  static bool IsTouchDevice(unsigned int deviceid) {
    return deviceid < touch_devices.size() ? touch_devices[deviceid] : false;
  }

 private:
  // A quick lookup table for determining if a device is a touch device.
  static std::bitset<128> touch_devices;

  DISALLOW_COPY_AND_ASSIGN(TouchFactory);
};

std::bitset<128> TouchFactory::touch_devices;
#endif

namespace {

RootView* FindRootViewForGdkWindow(GdkWindow* gdk_window) {
  gpointer data = NULL;
  gdk_window_get_user_data(gdk_window, &data);
  GtkWidget* gtk_widget = reinterpret_cast<GtkWidget*>(data);
  if (!gtk_widget || !GTK_IS_WIDGET(gtk_widget)) {
    DLOG(WARNING) << "no GtkWidget found for that GdkWindow";
    return NULL;
  }
  WidgetGtk* widget_gtk = WidgetGtk::GetViewForNative(gtk_widget);

  if (!widget_gtk) {
    DLOG(WARNING) << "no WidgetGtk found for that GtkWidget";
    return NULL;
  }
  return widget_gtk->GetRootView();
}

#if defined(HAVE_XINPUT2)
bool X2EventIsTouchEvent(XEvent* xev) {
  // TODO(sad): Determine if the captured event is a touch-event.
  XGenericEventCookie* cookie = &xev->xcookie;
  switch (cookie->evtype) {
    case XI_ButtonPress:
    case XI_ButtonRelease:
    case XI_Motion: {
      // Is the event coming from a touch device?
      return TouchFactory::IsTouchDevice(
          static_cast<XIDeviceEvent*>(cookie->data)->sourceid);
    }
    default:
      return false;
  }
}
#endif  // HAVE_XINPUT2

}  // namespace

#if defined(HAVE_XINPUT2)
bool DispatchX2Event(RootView* root, XEvent* xev) {
  if (X2EventIsTouchEvent(xev)) {
    // Create a TouchEvent, and send it off to |root|. If the event
    // is processed by |root|, then return. Otherwise let it fall through so it
    // can be used (if desired) as a mouse event.

    TouchEvent touch(xev);
    if (root->OnTouchEvent(touch))
      return true;
  }

  XGenericEventCookie* cookie = &xev->xcookie;

  switch (cookie->evtype) {
    case XI_KeyPress:
    case XI_KeyRelease: {
      // TODO(sad): We don't capture XInput2 events from keyboard yet.
      break;
    }
    case XI_ButtonPress:
    case XI_ButtonRelease: {
      MouseEvent mouseev(xev);
      if (cookie->evtype == XI_ButtonPress) {
        return root->OnMousePressed(mouseev);
      } else {
        root->OnMouseReleased(mouseev, false);
        return true;
      }
    }

    case XI_Motion: {
      MouseEvent mouseev(xev);
      if (mouseev.GetType() == Event::ET_MOUSE_DRAGGED) {
        return root->OnMouseDragged(mouseev);
      } else {
        root->OnMouseMoved(mouseev);
        return true;
      }
      break;
    }
  }

  return false;
}

#endif  // HAVE_XINPUT2

bool DispatchXEvent(XEvent* xev) {
  GdkDisplay* gdisp = gdk_display_get_default();
  XID xwindow = xev->xany.window;

#if defined(HAVE_XINPUT2)
  if (xev->type == GenericEvent) {
    XGenericEventCookie* cookie = &xev->xcookie;
    XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(cookie->data);
    xwindow = xiev->event;
  }
#endif

  GdkWindow* gwind = gdk_window_lookup_for_display(gdisp, xwindow);

  if (RootView* root = FindRootViewForGdkWindow(gwind)) {
    switch (xev->type) {
      case KeyPress: {
        // If Tab is pressed, then the RootView needs to process it first,
        // because the focus-manager will move the focus to the next focusable
        // view, without letting the currently focused view process it (which
        // means, for example, tab-ing to move focus between fields/links in a
        // RenderWidgetHostViewViews won't work). For all other keys, let the
        // focus manager process it first so that the keyboard accelerators can
        // be triggered.
        KeyEvent keyev(xev);
        FocusManager* focus_manager = root->GetFocusManager();
        if (FocusManager::IsTabTraversalKeyEvent(keyev)) {
          return root->ProcessKeyEvent(keyev) ||
              (focus_manager && !focus_manager->OnKeyEvent(keyev));
        } else {
          return (focus_manager && !focus_manager->OnKeyEvent(keyev)) ||
              root->ProcessKeyEvent(keyev);
        }
      }

      case KeyRelease: {
        KeyEvent keyev(xev);
        return root->ProcessKeyEvent(keyev);
      }

      case ButtonPress:
      case ButtonRelease: {
        if (xev->xbutton.button == 4 || xev->xbutton.button == 5) {
          // Scrolling the wheel triggers button press/release events.
          MouseWheelEvent wheelev(xev);
          return root->ProcessMouseWheelEvent(wheelev);
        } else {
          MouseEvent mouseev(xev);
          if (xev->type == ButtonPress) {
            return root->OnMousePressed(mouseev);
          } else {
            root->OnMouseReleased(mouseev, false);
            return true;  // Assume the event has been processed to make sure we
                          // don't process it twice.
          }
        }
      }

      case MotionNotify: {
        MouseEvent mouseev(xev);
        if (mouseev.GetType() == Event::ET_MOUSE_DRAGGED) {
          return root->OnMouseDragged(mouseev);
        } else {
          root->OnMouseMoved(mouseev);
          return true;
        }
      }

#if defined(HAVE_XINPUT2)
      case GenericEvent: {
        return DispatchX2Event(root, xev);
      }
#endif
    }
  }

  return false;
}

#if defined(HAVE_XINPUT2)
void SetTouchDeviceList(std::vector<unsigned int>& devices) {
  TouchFactory::SetTouchDeviceListInternal(devices);
}
#endif

AcceleratorHandler::AcceleratorHandler() {}

bool AcceleratorHandler::Dispatch(GdkEvent* event) {
  gtk_main_do_event(event);
  return true;
}

base::MessagePumpGlibXDispatcher::DispatchStatus AcceleratorHandler::Dispatch(
    XEvent* xev) {
  return DispatchXEvent(xev) ?
      base::MessagePumpGlibXDispatcher::EVENT_PROCESSED :
      base::MessagePumpGlibXDispatcher::EVENT_IGNORED;
}

}  // namespace views
<|endoftext|>


<commit_before>
#include "Generic.hpp"

using namespace cv;
using namespace std;

namespace thymio_tracker
{

void readCalibrationFromFileStorage(cv::FileStorage &fs, IntrinsicCalibration &calibration)
{
    fs["camera_matrix"] >> calibration.cameraMatrix;
    fs["distortion_coefficients"] >> calibration.distCoeffs;
    calibration.imageSize.width = (int) fs["image_width"];
    calibration.imageSize.height = (int) fs["image_height"];
}

void writeCalibrationToFileStorage(IntrinsicCalibration &calibration,cv::FileStorage &fs)
{
    cv::write(fs,"camera_matrix", calibration.cameraMatrix);
    cv::write(fs,"distortion_coefficients", calibration.distCoeffs);
    cv::write(fs,"image_width", calibration.imageSize.width);
    cv::write(fs,"image_height", calibration.imageSize.height);
    fs.release();
}

void resizeCameraMatrix(Mat& _cameraMatrix, const Size& sFrom, const Size& sTo)
{
    float ratiox=(float)sTo.width/sFrom.width;
    float ratioy=(float)sTo.height/sFrom.height;
    for(int j=0; j<3; j++)
    {
        _cameraMatrix.at<double>(0,j)=_cameraMatrix.at<double>(0,j)*ratiox;
        _cameraMatrix.at<double>(1,j)=_cameraMatrix.at<double>(1,j)*ratioy;
    }
}

void rescaleCalibration(IntrinsicCalibration &calibration, const cv::Size& sTo)
{
    resizeCameraMatrix(calibration.cameraMatrix, calibration.imageSize, sTo);
    calibration.imageSize=sTo;
}

Point2f toPixels(const Mat& _cameraMatrix, const Point2f& _m)
{
    Point2f px;
    px.x=_cameraMatrix.at<double>(0,0)*_m.x+_cameraMatrix.at<double>(0,2);
    px.y=_cameraMatrix.at<double>(1,1)*_m.y+_cameraMatrix.at<double>(1,2);
    return px;
}

Point2f toMeters(const Mat& _cameraMatrix, const Point2f& _x)
{
    Point2f pm;
    pm.x=(_x.x-_cameraMatrix.at<double>(0,2))/_cameraMatrix.at<double>(0,0);
    pm.y=(_x.y-_cameraMatrix.at<double>(1,2))/_cameraMatrix.at<double>(1,1);
    return pm;
}

Point2f toMeters(const Mat& _cameraMatrix, const Point2i& _x)
{
    Point2f pm;
    pm.x=((float)_x.x-_cameraMatrix.at<double>(0,2))/_cameraMatrix.at<double>(0,0);
    pm.y=((float)_x.y-_cameraMatrix.at<double>(1,2))/_cameraMatrix.at<double>(1,1);
    return pm;
}

Point2f toImagePlane(const Point3f& _x)
{
    return Point2f(_x.x/_x.z,_x.y/_x.z);
}

Mat ProjectZ1_Jac_Dp(const Point3f& mvLastDistCam)
{
    Mat res(2, 6, DataType<float>::type);
    float invZ=1./mvLastDistCam.z;
    float x=mvLastDistCam.x*invZ;
    float y=mvLastDistCam.y*invZ;

    res.at<float>(0,0)= invZ;   res.at<float>(0,1)= 0.;         res.at<float>(0,2)= -x*invZ;
    res.at<float>(0,3)= -x*y;   res.at<float>(0,4)= (1+x*x);    res.at<float>(0,5)= -y;
    res.at<float>(1,0)= 0.;     res.at<float>(1,1)= invZ;       res.at<float>(1,2)= -y*invZ;
    res.at<float>(1,3)= -(1+y*y);res.at<float>(1,4)= x*y;       res.at<float>(1,5)= x;
    return res;
}

cv::Point2f Pointxy(const cv::Point3f& _m){return cv::Point2f(_m.x,_m.y);}

bool testDirectionBasis(Point2f basis1,Point2f basis2)
{
    float crossProd=basis1.x*basis2.y-basis1.y*basis2.x;
    return crossProd>0;
}
bool testDirectionGroup(cv::Point2f v1,cv::Point2f v2,cv::Point2f v3)
{
    return testDirectionBasis(v2-v1,v3-v1);
}

}
<commit_msg>don't release calibration output filestorage object<commit_after>
#include "Generic.hpp"

using namespace cv;
using namespace std;

namespace thymio_tracker
{

void readCalibrationFromFileStorage(cv::FileStorage &fs, IntrinsicCalibration &calibration)
{
    fs["camera_matrix"] >> calibration.cameraMatrix;
    fs["distortion_coefficients"] >> calibration.distCoeffs;
    calibration.imageSize.width = (int) fs["image_width"];
    calibration.imageSize.height = (int) fs["image_height"];
}

void writeCalibrationToFileStorage(IntrinsicCalibration &calibration,cv::FileStorage &fs)
{
    cv::write(fs,"camera_matrix", calibration.cameraMatrix);
    cv::write(fs,"distortion_coefficients", calibration.distCoeffs);
    cv::write(fs,"image_width", calibration.imageSize.width);
    cv::write(fs,"image_height", calibration.imageSize.height);
}

void resizeCameraMatrix(Mat& _cameraMatrix, const Size& sFrom, const Size& sTo)
{
    float ratiox=(float)sTo.width/sFrom.width;
    float ratioy=(float)sTo.height/sFrom.height;
    for(int j=0; j<3; j++)
    {
        _cameraMatrix.at<double>(0,j)=_cameraMatrix.at<double>(0,j)*ratiox;
        _cameraMatrix.at<double>(1,j)=_cameraMatrix.at<double>(1,j)*ratioy;
    }
}

void rescaleCalibration(IntrinsicCalibration &calibration, const cv::Size& sTo)
{
    resizeCameraMatrix(calibration.cameraMatrix, calibration.imageSize, sTo);
    calibration.imageSize=sTo;
}

Point2f toPixels(const Mat& _cameraMatrix, const Point2f& _m)
{
    Point2f px;
    px.x=_cameraMatrix.at<double>(0,0)*_m.x+_cameraMatrix.at<double>(0,2);
    px.y=_cameraMatrix.at<double>(1,1)*_m.y+_cameraMatrix.at<double>(1,2);
    return px;
}

Point2f toMeters(const Mat& _cameraMatrix, const Point2f& _x)
{
    Point2f pm;
    pm.x=(_x.x-_cameraMatrix.at<double>(0,2))/_cameraMatrix.at<double>(0,0);
    pm.y=(_x.y-_cameraMatrix.at<double>(1,2))/_cameraMatrix.at<double>(1,1);
    return pm;
}

Point2f toMeters(const Mat& _cameraMatrix, const Point2i& _x)
{
    Point2f pm;
    pm.x=((float)_x.x-_cameraMatrix.at<double>(0,2))/_cameraMatrix.at<double>(0,0);
    pm.y=((float)_x.y-_cameraMatrix.at<double>(1,2))/_cameraMatrix.at<double>(1,1);
    return pm;
}

Point2f toImagePlane(const Point3f& _x)
{
    return Point2f(_x.x/_x.z,_x.y/_x.z);
}

Mat ProjectZ1_Jac_Dp(const Point3f& mvLastDistCam)
{
    Mat res(2, 6, DataType<float>::type);
    float invZ=1./mvLastDistCam.z;
    float x=mvLastDistCam.x*invZ;
    float y=mvLastDistCam.y*invZ;

    res.at<float>(0,0)= invZ;   res.at<float>(0,1)= 0.;         res.at<float>(0,2)= -x*invZ;
    res.at<float>(0,3)= -x*y;   res.at<float>(0,4)= (1+x*x);    res.at<float>(0,5)= -y;
    res.at<float>(1,0)= 0.;     res.at<float>(1,1)= invZ;       res.at<float>(1,2)= -y*invZ;
    res.at<float>(1,3)= -(1+y*y);res.at<float>(1,4)= x*y;       res.at<float>(1,5)= x;
    return res;
}

cv::Point2f Pointxy(const cv::Point3f& _m){return cv::Point2f(_m.x,_m.y);}

bool testDirectionBasis(Point2f basis1,Point2f basis2)
{
    float crossProd=basis1.x*basis2.y-basis1.y*basis2.x;
    return crossProd>0;
}
bool testDirectionGroup(cv::Point2f v1,cv::Point2f v2,cv::Point2f v3)
{
    return testDirectionBasis(v2-v1,v3-v1);
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/platform_util.h"

#include "base/bind.h"
#include "base/callback.h"
#include "base/file_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/extensions/file_manager_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "content/public/browser/browser_thread.h"
#include "googleurl/src/gurl.h"

using content::BrowserThread;

class Profile;

namespace {

const char kGmailComposeUrl[] =
    "https://mail.google.com/mail/?extsrc=mailto&url=";

void OpenItemOnFileThread(const FilePath& full_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  base::Closure callback;
  if (file_util::DirectoryExists(full_path))
    callback = base::Bind(&file_manager_util::ViewFolder, full_path);
  else
    callback = base::Bind(&file_manager_util::ViewFile, full_path);
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
}

void OpenURL(const std::string& url) {
  Browser* browser = BrowserList::GetLastActive();
  browser->AddSelectedTabWithURL(GURL(url), content::PAGE_TRANSITION_LINK);
}

}  // namespace

namespace platform_util {

void ShowItemInFolder(const FilePath& full_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  file_manager_util::ShowFileInFolder(full_path);
}

void OpenItem(const FilePath& full_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
      base::Bind(&OpenItemOnFileThread, full_path));
}

void OpenExternal(const GURL& url) {
  // This code should be obsolete since we have default handlers in ChromeOS
  // which should handle this. However - there are two things which make it
  // necessary to keep it in:
  // a.) The user might have deleted the default handler in this session.
  //     In this case we would need to have this in place.
  // b.) There are several code paths which are not clear if they would call
  //     this function directly and which would therefore break (e.g.
  //     "Browser::EmailPageLocation" (to name only one).
  // As such we should keep this code here.
  if (url.SchemeIs("mailto")) {
    std::string string_url = kGmailComposeUrl;
    string_url.append(url.spec());
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                            base::Bind(OpenURL, string_url));
  }
}

}  // namespace platform_util
<commit_msg>Replace BrowserList::GetLastActive() usage in platform_util_chromeos with browser::Navigate().<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/platform_util.h"

#include "base/bind.h"
#include "base/callback.h"
#include "base/file_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/extensions/file_manager_util.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "content/public/browser/browser_thread.h"
#include "googleurl/src/gurl.h"

using content::BrowserThread;

class Profile;

namespace {

const char kGmailComposeUrl[] =
    "https://mail.google.com/mail/?extsrc=mailto&url=";

void OpenItemOnFileThread(const FilePath& full_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  base::Closure callback;
  if (file_util::DirectoryExists(full_path))
    callback = base::Bind(&file_manager_util::ViewFolder, full_path);
  else
    callback = base::Bind(&file_manager_util::ViewFile, full_path);
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
}

void OpenURL(const std::string& url) {
  // TODO(beng): improve this to locate context from call stack.
  browser::NavigateParams params(NULL,
                                 GURL(url),
                                 content::PAGE_TRANSITION_LINK);
  params.disposition = NEW_FOREGROUND_TAB;
  params.profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
  browser::Navigate(&params);
}

}  // namespace

namespace platform_util {

void ShowItemInFolder(const FilePath& full_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  file_manager_util::ShowFileInFolder(full_path);
}

void OpenItem(const FilePath& full_path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
      base::Bind(&OpenItemOnFileThread, full_path));
}

void OpenExternal(const GURL& url) {
  // This code should be obsolete since we have default handlers in ChromeOS
  // which should handle this. However - there are two things which make it
  // necessary to keep it in:
  // a.) The user might have deleted the default handler in this session.
  //     In this case we would need to have this in place.
  // b.) There are several code paths which are not clear if they would call
  //     this function directly and which would therefore break (e.g.
  //     "Browser::EmailPageLocation" (to name only one).
  // As such we should keep this code here.
  if (url.SchemeIs("mailto")) {
    std::string string_url = kGmailComposeUrl;
    string_url.append(url.spec());
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                            base::Bind(OpenURL, string_url));
  }
}

}  // namespace platform_util
<|endoftext|>