<commit_before>#include <ruby.h>
#include "hstcpcli.hpp"

typedef struct {
    dena::hstcpcli_i *ptr;
} HandlerSocket;

void parse_options(dena::config&, dena::socket_args&, VALUE);

VALUE hs_free(HandlerSocket* hs)
{
    if (hs) {
        if (hs->ptr) {
            hs->ptr->close();
            delete hs->ptr;
        }
        xfree(hs);
    }
}

VALUE hs_alloc(VALUE self)
{
    return Data_Wrap_Struct(self, NULL, hs_free, 0);
}

VALUE hs_initialize(VALUE self, VALUE options)
{
    HandlerSocket* hs;

    Data_Get_Struct(self, HandlerSocket, hs);
    if (!hs) {
        hs = (HandlerSocket*)xmalloc(sizeof(HandlerSocket));
        MEMZERO(hs, HandlerSocket, 1);
        DATA_PTR(self) = hs;
    }

    dena::config      conf;
    dena::socket_args args;
    parse_options(conf, args, options);

    dena::hstcpcli_ptr ptr = dena::hstcpcli_i::create(args);
    hs->ptr = ptr.get();
    ptr.release();

    return self;
}

VALUE hs_close(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    hs->ptr->close();
    return Qnil;
}

VALUE hs_reconnect(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    int retval = hs->ptr->reconnect();
    return INT2FIX(retval);
}

VALUE hs_stable_point(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    return hs->ptr->stable_point() ? Qtrue : Qfalse;
}

VALUE hs_error(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    VALUE val = Qnil;
    std::string error = hs->ptr->get_error();

    if (!error.empty()) {
        val = rb_str_new2(error.c_str());
    }
    return val;
}

VALUE hs_error_code(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    return INT2FIX(hs->ptr->get_error_code());
}

VALUE hs_open_index(VALUE self, VALUE id, VALUE db, VALUE table, VALUE index, VALUE fields)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);
    dena::hstcpcli_i *const ptr = hs->ptr;

    do {
        size_t pst_id = NUM2INT(id);
        ptr->request_buf_open_index(pst_id, StringValuePtr(db), StringValuePtr(table), StringValuePtr(index), StringValuePtr(fields));
        if (ptr->request_send() != 0) {
            break;
        }

        size_t nflds = 0;
        ptr->response_recv(nflds);
        const int e = ptr->get_error_code();
        if (e >= 0) {
            ptr->response_buf_remove();
        }
    } while(0);

    return INT2FIX(ptr->get_error_code());
}

VALUE ary_to_vector(VALUE ary, std::vector<dena::string_ref>& vec)
{
    VALUE ret, val;

    if (NIL_P(ary) || RARRAY_LEN(ary) == 0) {
        return ary;
    }

    ret = rb_ary_new2(RARRAY_LEN(ary));
    vec.reserve(RARRAY_LEN(ary));

    for (size_t i=0; i<RARRAY_LEN(ary); i++) {
        val = rb_ary_entry(ary, i);
        if (FIXNUM_P(val)) {
            val = rb_fix2str(val, 10);
        }
        StringValue(val);
        vec.push_back(dena::string_ref(RSTRING_PTR(val), RSTRING_LEN(val)));
        rb_ary_push(ret, val);
    }

    return ret;
}

VALUE hs_execute_single(int argc, VALUE *argv, VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);
    dena::hstcpcli_i *const ptr = hs->ptr;

    VALUE id, op, keys, limit, skip, modop, modvals;
    rb_scan_args(argc, argv, "52", &id, &op, &keys, &limit, &skip, &modop, &modvals);

    StringValue(op);
    Check_Type(keys, T_ARRAY);

    if (!NIL_P(modop)) {
        StringValue(modop);
    }

    dena::string_ref op_ref, modop_ref;
    std::vector<dena::string_ref> keyary, modary;

    op_ref = dena::string_ref(RSTRING_PTR(op), RSTRING_LEN(op));
    keys = ary_to_vector(keys, keyary);
    rb_gc_register_address(&keys);

    if (!NIL_P(modop)) {
        modop_ref = dena::string_ref(RSTRING_PTR(modop), RSTRING_LEN(modop));
        modvals = ary_to_vector(modvals, modary);
        rb_gc_register_address(&modvals);
    }

    ptr->request_buf_exec_generic(NUM2INT(id),
                                  op_ref,
                                  &keyary[0], keyary.size(),
                                  NUM2INT(limit), NUM2INT(skip),
                                  modop_ref,
                                  &modary[0], modary.size());

    if (ptr->request_send() != 0) {
        return Qnil;
    }

    rb_gc_unregister_address(&keys);

    if (!NIL_P(modop)) {
        rb_gc_unregister_address(&modvals);
    }

    size_t nflds = 0;
    ptr->response_recv(nflds);

    VALUE retval = rb_ary_new();

    const int e = ptr->get_error_code();
    rb_ary_push(retval, FIX2INT(e));

    if (e != 0) {
        const std::string s = ptr->get_error();
        rb_ary_push(retval, rb_str_new2(s.c_str()));
    } else {
        VALUE arys, ary, val;

        arys = rb_ary_new();
        const dena::string_ref *row = 0;
        while ((row = ptr->get_next_row()) != 0) {
            ary = rb_ary_new2(nflds);
            for (size_t i = 0; i < nflds; ++i) {
                const dena::string_ref& v = row[i];
                if (v.begin() != 0) {
                    val = rb_str_new(v.begin(), v.size());
                    rb_ary_push(ary, val);
                } else {
                    rb_ary_push(ary, Qnil);
                }
            }
            rb_ary_push(arys, ary);
        }
        rb_ary_push(retval, arys);
    }

    if (e >= 0) {
      ptr->response_buf_remove();
    }

    return retval;
}

VALUE hs_execute_multi(int argc, VALUE *argv, VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);
    dena::hstcpcli_i *const ptr = hs->ptr;

    VALUE exec_args, exec_arg;

    VALUE id, op, keys, limit, skip, modop, modvals;
    int arg = rb_scan_args(argc, argv, "16", &id, &op, &keys, &limit, &skip, &modop, &modvals);
    if (arg >= 5) {
        VALUE tmp = rb_ary_new3(id, op, keys, limit, skip, modop, modvals);
        exec_args = rb_ary_new3(tmp);
    } else if (arg == 1) {
        Check_Type(id, T_ARRAY);
        exec_args = id;
    } else {
        rb_raise(rb_eArgError, "wrong number of arguments");
    }

    for (size_t i=0; i<RARRAY_LEN(exec_args); i++) {
        exec_arg = rb_ary_entry(exec_args, i);
        Check_Type(exec_arg, T_ARRAY);

        id      = rb_ary_entry(exec_arg, 0);
        op      = rb_ary_entry(exec_arg, 1);
        keys    = rb_ary_entry(exec_arg, 2);
        limit   = rb_ary_entry(exec_arg, 3);
        skip    = rb_ary_entry(exec_arg, 4);
        modop   = rb_ary_entry(exec_arg, 5);
        modvals = rb_ary_entry(exec_arg, 6);

        StringValue(op);
        Check_Type(keys, T_ARRAY);

        if (!NIL_P(modop)) {
            StringValue(modop);
        }

        dena::string_ref op_ref, modop_ref;
        std::vector<dena::string_ref> keyary, modary;

        op_ref = dena::string_ref(RSTRING_PTR(op), RSTRING_LEN(op));
        keys = ary_to_vector(keys, keyary);
        rb_gc_register_address(&keys);

        if (!NIL_P(modop)) {
            modop_ref = dena::string_ref(RSTRING_PTR(modop), RSTRING_LEN(modop));
            modvals = ary_to_vector(modvals, modary);
            rb_gc_register_address(&modvals);
        }

        ptr->request_buf_exec_generic(NUM2INT(id),
                                      op_ref,
                                      &keyary[0], keyary.size(),
                                      NUM2INT(limit), NUM2INT(skip),
                                      modop_ref,
                                      &modary[0], modary.size());
    }

    VALUE retvals, retval;
    retvals = rb_ary_new();

    if (ptr->request_send() < 0) {
        retval = rb_ary_new();

        const int e = ptr->get_error_code();
        const std::string s = ptr->get_error();
        rb_ary_push(retval, FIX2INT(e));
        rb_ary_push(retval, rb_str_new2(s.c_str()));

        rb_ary_push(retvals, retval);
        return retvals;
    }

    for (size_t i=0; i<RARRAY_LEN(exec_args); i++) {
        retval = rb_ary_new();

        size_t nflds = 0;
        const int e = ptr->response_recv(nflds);
        rb_ary_push(retval, FIX2INT(e));
        if (e != 0) {
            const std::string s = ptr->get_error();
            rb_ary_push(retval, rb_str_new2(s.c_str()));
        } else {
            VALUE arys, ary, val;

            arys = rb_ary_new();
            const dena::string_ref *row = 0;
            while ((row = ptr->get_next_row()) != 0) {
                ary = rb_ary_new2(nflds);
                for (size_t i = 0; i < nflds; ++i) {
                    const dena::string_ref& v = row[i];
                    if (v.begin() != 0) {
                        val = rb_str_new(v.begin(), v.size());
                        rb_ary_push(ary, val);
                    } else {
                        rb_ary_push(ary, Qnil);
                    }
                }
                rb_ary_push(arys, ary);
            }
            rb_ary_push(retval, arys);
        }

        if (e >= 0) {
            ptr->response_buf_remove();
        }

        rb_ary_push(retvals, retval);

        if (e < 0) {
            return retvals;
        }
    }

    return retvals;
}

VALUE hs_execute_update(VALUE self, VALUE id, VALUE op, VALUE keys, VALUE limit, VALUE skip, VALUE modvals)
{
    VALUE argv[7] = {
        id, op, keys, limit, skip, rb_str_new2("U"), modvals,
    };
    return hs_execute_single(7, argv, self);
}

VALUE hs_execute_delete(VALUE self, VALUE id, VALUE op, VALUE keys, VALUE limit, VALUE skip)
{
    VALUE argv[7] = {
        id, op, keys, limit, skip, rb_str_new2("D"), Qnil,
    };
    return hs_execute_single(7, argv, self);
}

VALUE hs_execute_insert(VALUE self, VALUE id, VALUE fvals)
{
    VALUE argv[5] = {
        id, rb_str_new2("+"), fvals, 0, 0,
    };
    return hs_execute_single(5, argv, self);
}

void parse_options(dena::config& conf, dena::socket_args& args, VALUE options)
{
    VALUE val;

    Check_Type(options, T_HASH);

    val = rb_hash_aref(options, ID2SYM(rb_intern("host")));
    if(val != Qnil)
    {
        conf["host"] = std::string(StringValuePtr(val));
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("port")));
    if(val != Qnil)
    {
        conf["port"] = std::string(StringValuePtr(val));
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("timeout")));
    if(val != Qnil)
    {
        conf["timeout"] = std::string(StringValuePtr(val));
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("listen_backlog")));
    if(val != Qnil)
    {
        conf["listen_backlog"] = std::string(StringValuePtr(val));
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("sndbuf")));
    if(val != Qnil)
    {
        conf["sndbuf"] = std::string(StringValuePtr(val));
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("rcvbuf")));
    if(val != Qnil)
    {
        conf["rcvbuf"] = std::string(StringValuePtr(val));
    }

    args.set(conf);
}

extern "C" {
    void Init_handler_socket(void)
    {
        VALUE rb_cHandlerSocket = rb_define_class("HandlerSocket", rb_cObject);

        rb_define_alloc_func(rb_cHandlerSocket, hs_alloc);
        rb_define_private_method(rb_cHandlerSocket, "initialize", (VALUE(*)(...))hs_initialize, 1);

        rb_define_method(rb_cHandlerSocket, "close", (VALUE(*)(...))hs_close, 0);
        rb_define_method(rb_cHandlerSocket, "reconnect", (VALUE(*)(...))hs_reconnect, 0);
        rb_define_method(rb_cHandlerSocket, "stable_point", (VALUE(*)(...))hs_stable_point, 0);

        rb_define_method(rb_cHandlerSocket, "error", (VALUE(*)(...))hs_error, 0);
        rb_define_method(rb_cHandlerSocket, "error_code", (VALUE(*)(...))hs_error_code, 0);

        rb_define_method(rb_cHandlerSocket, "open_index", (VALUE(*)(...))hs_open_index, 5);
        rb_define_method(rb_cHandlerSocket, "execute_single", (VALUE(*)(...))hs_execute_single, -1);
        rb_define_method(rb_cHandlerSocket, "execute_multi", (VALUE(*)(...))hs_execute_multi, -1);
        rb_define_alias(rb_cHandlerSocket, "execute_find", "execute_single");
        rb_define_method(rb_cHandlerSocket, "execute_update", (VALUE(*)(...))hs_execute_update, 6);
        rb_define_method(rb_cHandlerSocket, "execute_delete", (VALUE(*)(...))hs_execute_delete, 5);
        rb_define_method(rb_cHandlerSocket, "execute_insert", (VALUE(*)(...))hs_execute_insert, 2);
    }
}
<commit_msg>add hs_mark<commit_after>#include <ruby.h>
#include "hstcpcli.hpp"

typedef struct {
    dena::hstcpcli_i *ptr;
} HandlerSocket;

void parse_options(dena::config&, dena::socket_args&, VALUE);

void hs_free(HandlerSocket* hs)
{
    if (hs) {
        if (hs->ptr) {
            hs->ptr->close();
            delete hs->ptr;
        }
        xfree(hs);
    }
}

void hs_mark(HandlerSocket* hs)
{
}

VALUE hs_alloc(VALUE self)
{
    return Data_Wrap_Struct(self, hs_mark, hs_free, 0);
}

VALUE hs_initialize(VALUE self, VALUE options)
{
    HandlerSocket* hs;

    Data_Get_Struct(self, HandlerSocket, hs);
    if (!hs) {
        hs = (HandlerSocket*)xmalloc(sizeof(HandlerSocket));
        MEMZERO(hs, HandlerSocket, 1);
        DATA_PTR(self) = hs;
    }

    dena::config      conf;
    dena::socket_args args;
    parse_options(conf, args, options);

    dena::hstcpcli_ptr ptr = dena::hstcpcli_i::create(args);
    hs->ptr = ptr.get();
    ptr.release();

    return self;
}

VALUE hs_close(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    hs->ptr->close();
    return Qnil;
}

VALUE hs_reconnect(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    int retval = hs->ptr->reconnect();
    return INT2FIX(retval);
}

VALUE hs_stable_point(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    return hs->ptr->stable_point() ? Qtrue : Qfalse;
}

VALUE hs_error(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    VALUE val = Qnil;
    std::string error = hs->ptr->get_error();

    if (!error.empty()) {
        val = rb_str_new2(error.c_str());
    }
    return val;
}

VALUE hs_error_code(VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);

    return INT2FIX(hs->ptr->get_error_code());
}

VALUE hs_open_index(VALUE self, VALUE id, VALUE db, VALUE table, VALUE index, VALUE fields)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);
    dena::hstcpcli_i *const ptr = hs->ptr;

    do {
        size_t pst_id = NUM2INT(id);
        ptr->request_buf_open_index(pst_id, StringValuePtr(db), StringValuePtr(table), StringValuePtr(index), StringValuePtr(fields));
        if (ptr->request_send() != 0) {
            break;
        }

        size_t nflds = 0;
        ptr->response_recv(nflds);
        const int e = ptr->get_error_code();
        if (e >= 0) {
            ptr->response_buf_remove();
        }
    } while(0);

    return INT2FIX(ptr->get_error_code());
}

VALUE ary_to_vector(VALUE ary, std::vector<dena::string_ref>& vec)
{
    VALUE ret, val;

    if (NIL_P(ary) || RARRAY_LEN(ary) == 0) {
        return ary;
    }

    ret = rb_ary_new2(RARRAY_LEN(ary));
    vec.reserve(RARRAY_LEN(ary));

    for (size_t i=0; i<RARRAY_LEN(ary); i++) {
        val = rb_ary_entry(ary, i);
        if (FIXNUM_P(val)) {
            val = rb_fix2str(val, 10);
        }
        StringValue(val);
        vec.push_back(dena::string_ref(RSTRING_PTR(val), RSTRING_LEN(val)));
        rb_ary_push(ret, val);
    }

    return ret;
}

VALUE hs_execute_single(int argc, VALUE *argv, VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);
    dena::hstcpcli_i *const ptr = hs->ptr;

    VALUE id, op, keys, limit, skip, modop, modvals;
    rb_scan_args(argc, argv, "52", &id, &op, &keys, &limit, &skip, &modop, &modvals);

    StringValue(op);
    Check_Type(keys, T_ARRAY);

    if (!NIL_P(modop)) {
        StringValue(modop);
    }

    dena::string_ref op_ref, modop_ref;
    std::vector<dena::string_ref> keyary, modary;

    op_ref = dena::string_ref(RSTRING_PTR(op), RSTRING_LEN(op));
    keys = ary_to_vector(keys, keyary);
    rb_gc_register_address(&keys);

    if (!NIL_P(modop)) {
        modop_ref = dena::string_ref(RSTRING_PTR(modop), RSTRING_LEN(modop));
        modvals = ary_to_vector(modvals, modary);
        rb_gc_register_address(&modvals);
    }

    ptr->request_buf_exec_generic(NUM2INT(id),
                                  op_ref,
                                  &keyary[0], keyary.size(),
                                  NUM2INT(limit), NUM2INT(skip),
                                  modop_ref,
                                  &modary[0], modary.size());

    if (ptr->request_send() != 0) {
        return Qnil;
    }

    rb_gc_unregister_address(&keys);

    if (!NIL_P(modop)) {
        rb_gc_unregister_address(&modvals);
    }

    size_t nflds = 0;
    ptr->response_recv(nflds);

    VALUE retval = rb_ary_new();

    const int e = ptr->get_error_code();
    rb_ary_push(retval, FIX2INT(e));

    if (e != 0) {
        const std::string s = ptr->get_error();
        rb_ary_push(retval, rb_str_new2(s.c_str()));
    } else {
        VALUE arys, ary, val;

        arys = rb_ary_new();
        const dena::string_ref *row = 0;
        while ((row = ptr->get_next_row()) != 0) {
            ary = rb_ary_new2(nflds);
            for (size_t i = 0; i < nflds; ++i) {
                const dena::string_ref& v = row[i];
                if (v.begin() != 0) {
                    val = rb_str_new(v.begin(), v.size());
                    rb_ary_push(ary, val);
                } else {
                    rb_ary_push(ary, Qnil);
                }
            }
            rb_ary_push(arys, ary);
        }
        rb_ary_push(retval, arys);
    }

    if (e >= 0) {
      ptr->response_buf_remove();
    }

    return retval;
}

VALUE hs_execute_multi(int argc, VALUE *argv, VALUE self)
{
    HandlerSocket* hs;
    Data_Get_Struct(self, HandlerSocket, hs);
    dena::hstcpcli_i *const ptr = hs->ptr;

    VALUE exec_args, exec_arg;

    VALUE id, op, keys, limit, skip, modop, modvals;
    int arg = rb_scan_args(argc, argv, "16", &id, &op, &keys, &limit, &skip, &modop, &modvals);
    if (arg >= 5) {
        VALUE tmp = rb_ary_new3(id, op, keys, limit, skip, modop, modvals);
        exec_args = rb_ary_new3(tmp);
    } else if (arg == 1) {
        Check_Type(id, T_ARRAY);
        exec_args = id;
    } else {
        rb_raise(rb_eArgError, "wrong number of arguments");
    }

    for (size_t i=0; i<RARRAY_LEN(exec_args); i++) {
        exec_arg = rb_ary_entry(exec_args, i);
        Check_Type(exec_arg, T_ARRAY);

        id      = rb_ary_entry(exec_arg, 0);
        op      = rb_ary_entry(exec_arg, 1);
        keys    = rb_ary_entry(exec_arg, 2);
        limit   = rb_ary_entry(exec_arg, 3);
        skip    = rb_ary_entry(exec_arg, 4);
        modop   = rb_ary_entry(exec_arg, 5);
        modvals = rb_ary_entry(exec_arg, 6);

        StringValue(op);
        Check_Type(keys, T_ARRAY);

        if (!NIL_P(modop)) {
            StringValue(modop);
        }

        dena::string_ref op_ref, modop_ref;
        std::vector<dena::string_ref> keyary, modary;

        op_ref = dena::string_ref(RSTRING_PTR(op), RSTRING_LEN(op));
        keys = ary_to_vector(keys, keyary);
        rb_gc_register_address(&keys);

        if (!NIL_P(modop)) {
            modop_ref = dena::string_ref(RSTRING_PTR(modop), RSTRING_LEN(modop));
            modvals = ary_to_vector(modvals, modary);
            rb_gc_register_address(&modvals);
        }

        ptr->request_buf_exec_generic(NUM2INT(id),
                                      op_ref,
                                      &keyary[0], keyary.size(),
                                      NUM2INT(limit), NUM2INT(skip),
                                      modop_ref,
                                      &modary[0], modary.size());
    }

    VALUE retvals, retval;
    retvals = rb_ary_new();

    if (ptr->request_send() < 0) {
        retval = rb_ary_new();

        const int e = ptr->get_error_code();
        const std::string s = ptr->get_error();
        rb_ary_push(retval, FIX2INT(e));
        rb_ary_push(retval, rb_str_new2(s.c_str()));

        rb_ary_push(retvals, retval);
        return retvals;
    }

    for (size_t i=0; i<RARRAY_LEN(exec_args); i++) {
        retval = rb_ary_new();

        size_t nflds = 0;
        const int e = ptr->response_recv(nflds);
        rb_ary_push(retval, FIX2INT(e));
        if (e != 0) {
            const std::string s = ptr->get_error();
            rb_ary_push(retval, rb_str_new2(s.c_str()));
        } else {
            VALUE arys, ary, val;

            arys = rb_ary_new();
            const dena::string_ref *row = 0;
            while ((row = ptr->get_next_row()) != 0) {
                ary = rb_ary_new2(nflds);
                for (size_t i = 0; i < nflds; ++i) {
                    const dena::string_ref& v = row[i];
                    if (v.begin() != 0) {
                        val = rb_str_new(v.begin(), v.size());
                        rb_ary_push(ary, val);
                    } else {
                        rb_ary_push(ary, Qnil);
                    }
                }
                rb_ary_push(arys, ary);
            }
            rb_ary_push(retval, arys);
        }

        if (e >= 0) {
            ptr->response_buf_remove();
        }

        rb_ary_push(retvals, retval);

        if (e < 0) {
            return retvals;
        }
    }

    return retvals;
}

VALUE hs_execute_update(VALUE self, VALUE id, VALUE op, VALUE keys, VALUE limit, VALUE skip, VALUE modvals)
{
    VALUE argv[7] = {
        id, op, keys, limit, skip, rb_str_new2("U"), modvals,
    };
    return hs_execute_single(7, argv, self);
}

VALUE hs_execute_delete(VALUE self, VALUE id, VALUE op, VALUE keys, VALUE limit, VALUE skip)
{
    VALUE argv[7] = {
        id, op, keys, limit, skip, rb_str_new2("D"), Qnil,
    };
    return hs_execute_single(7, argv, self);
}

VALUE hs_execute_insert(VALUE self, VALUE id, VALUE fvals)
{
    VALUE argv[5] = {
        id, rb_str_new2("+"), fvals, 0, 0,
    };
    return hs_execute_single(5, argv, self);
}

void parse_options(dena::config& conf, dena::socket_args& args, VALUE options)
{
    VALUE val;

    Check_Type(options, T_HASH);

    val = rb_hash_aref(options, ID2SYM(rb_intern("host")));
    if(val != Qnil)
    {
        conf["host"] = std::string(StringValuePtr(val));
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("port")));
    if(val != Qnil)
    {
        conf["port"] = std::string(StringValuePtr(val));
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("timeout")));
    if(val != Qnil)
    {
        conf["timeout"] = std::string(StringValuePtr(val));
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("listen_backlog")));
    if(val != Qnil)
    {
        conf["listen_backlog"] = std::string(StringValuePtr(val));
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("sndbuf")));
    if(val != Qnil)
    {
        conf["sndbuf"] = std::string(StringValuePtr(val));
    }

    val = rb_hash_aref(options, ID2SYM(rb_intern("rcvbuf")));
    if(val != Qnil)
    {
        conf["rcvbuf"] = std::string(StringValuePtr(val));
    }

    args.set(conf);
}

extern "C" {
    void Init_handler_socket(void)
    {
        VALUE rb_cHandlerSocket = rb_define_class("HandlerSocket", rb_cObject);

        rb_define_alloc_func(rb_cHandlerSocket, hs_alloc);
        rb_define_private_method(rb_cHandlerSocket, "initialize", (VALUE(*)(...))hs_initialize, 1);

        rb_define_method(rb_cHandlerSocket, "close", (VALUE(*)(...))hs_close, 0);
        rb_define_method(rb_cHandlerSocket, "reconnect", (VALUE(*)(...))hs_reconnect, 0);
        rb_define_method(rb_cHandlerSocket, "stable_point", (VALUE(*)(...))hs_stable_point, 0);

        rb_define_method(rb_cHandlerSocket, "error", (VALUE(*)(...))hs_error, 0);
        rb_define_method(rb_cHandlerSocket, "error_code", (VALUE(*)(...))hs_error_code, 0);

        rb_define_method(rb_cHandlerSocket, "open_index", (VALUE(*)(...))hs_open_index, 5);
        rb_define_method(rb_cHandlerSocket, "execute_single", (VALUE(*)(...))hs_execute_single, -1);
        rb_define_method(rb_cHandlerSocket, "execute_multi", (VALUE(*)(...))hs_execute_multi, -1);
        rb_define_alias(rb_cHandlerSocket, "execute_find", "execute_single");
        rb_define_method(rb_cHandlerSocket, "execute_update", (VALUE(*)(...))hs_execute_update, 6);
        rb_define_method(rb_cHandlerSocket, "execute_delete", (VALUE(*)(...))hs_execute_delete, 5);
        rb_define_method(rb_cHandlerSocket, "execute_insert", (VALUE(*)(...))hs_execute_insert, 2);
    }
}
<|endoftext|>


<commit_before>TEST_F(Parser, StoreParseValue)
{
	const char *input = " 123 ";
	int solution = 123;

	Store *result = StoreParse(input, &state);
	ASSERT_TRUE(result != NULL) << "StoreParse should not return NULL";
	ASSERT_EQ(result->type, STORE_INT) << "StoreParse should return a store of type int";
	ASSERT_EQ(result->content.intValue, solution) << "StoreParse should parse the correct int value";
	ASSERT_EQ(state.position.index, 5) << "state position index should have moved to end of input";
	ASSERT_EQ(state.position.column, 6) << "state position column should have moved to end of input";

	StoreFree(result);
}

TEST_F(Parser, StoreParseEntries)
{
	const char *input = " foo = bar; baz = 3.14159265359 ";
	const char *solution_key1 = "foo";
	const char *solution_value1 = "bar";
	const char *solution_key2 = "baz";
	double solution_value2 = 3.14159265359;

	Store *result = StoreParse(input, &state);
	ASSERT_TRUE(result != NULL) << "StoreParse should not return NULL";
	ASSERT_EQ(result->type, STORE_MAP) << "StoreParse should return a store of type map";
	ASSERT_EQ(StoreGetMapSize(result->content.mapValue), 2) << "parsed map should have two entries";
	ASSERT_EQ(state.position.index, 32) << "state position index should have moved to end of input";
	ASSERT_EQ(state.position.column, 33) << "state position column should have moved to end of input";

	StoreMapIterator iter = StoreCreateMapIterator(result->content.mapValue);
	ASSERT_TRUE(StoreIsMapIteratorValid(iter)) << "store map iterator should be valid";

	int hits = 0;
	for(; StoreIsMapIteratorValid(iter); StoreForwardMapIterator(iter)) {
		const char *key = StoreGetCurrentMapIteratorKey(iter);
		ASSERT_TRUE(key != NULL) << "StoreGetCurrentMapIteratorKey should not return NULL when iterator is still valid";
		Store *value = StoreGetCurrentMapIteratorValue(iter);
		ASSERT_TRUE(value != NULL) << "StoreGetCurrentMapIteratorValue should not return NULL when iterator is still valid";

		std::string stdStringKey(key);
		if(stdStringKey == solution_key1) {
			ASSERT_EQ(value->type, STORE_STRING) << "value of first map entry should be a store of type string";
			ASSERT_STREQ(value->content.stringValue, solution_value1) << "value of first map entry should have been parsed to the correct string value";
			hits++;
		} else if(stdStringKey == solution_key2) {
			ASSERT_EQ(value->type, STORE_FLOAT) << "value of second map entry should be a store of type float";
			ASSERT_EQ(value->content.floatValue, solution_value2) << "value of second map entry should have been parsed to the correct float value";
			hits++;
		} else {
			ASSERT_TRUE(false) << "invalid parsed entry with key: " << stdStringKey;
		}
	}
	StoreFreeMapIterator(iter);

	ASSERT_EQ(hits, 2) << "loop body should have hit two times";

	StoreFree(result);
}
<commit_msg>added invalid test to StoreParse<commit_after>TEST_F(Parser, StoreParseValue)
{
	const char *input = " 123 ";
	int solution = 123;

	Store *result = StoreParse(input, &state);
	ASSERT_TRUE(result != NULL) << "StoreParse should not return NULL";
	ASSERT_EQ(result->type, STORE_INT) << "StoreParse should return a store of type int";
	ASSERT_EQ(result->content.intValue, solution) << "StoreParse should parse the correct int value";
	ASSERT_EQ(state.position.index, 5) << "state position index should have moved to end of input";
	ASSERT_EQ(state.position.column, 6) << "state position column should have moved to end of input";

	StoreFree(result);
}

TEST_F(Parser, StoreParseEntries)
{
	const char *input = " foo = bar; baz = 3.14159265359 ";
	const char *solution_key1 = "foo";
	const char *solution_value1 = "bar";
	const char *solution_key2 = "baz";
	double solution_value2 = 3.14159265359;

	Store *result = StoreParse(input, &state);
	ASSERT_TRUE(result != NULL) << "StoreParse should not return NULL";
	ASSERT_EQ(result->type, STORE_MAP) << "StoreParse should return a store of type map";
	ASSERT_EQ(StoreGetMapSize(result->content.mapValue), 2) << "parsed map should have two entries";
	ASSERT_EQ(state.position.index, 32) << "state position index should have moved to end of input";
	ASSERT_EQ(state.position.column, 33) << "state position column should have moved to end of input";

	StoreMapIterator iter = StoreCreateMapIterator(result->content.mapValue);
	ASSERT_TRUE(StoreIsMapIteratorValid(iter)) << "store map iterator should be valid";

	int hits = 0;
	for(; StoreIsMapIteratorValid(iter); StoreForwardMapIterator(iter)) {
		const char *key = StoreGetCurrentMapIteratorKey(iter);
		ASSERT_TRUE(key != NULL) << "StoreGetCurrentMapIteratorKey should not return NULL when iterator is still valid";
		Store *value = StoreGetCurrentMapIteratorValue(iter);
		ASSERT_TRUE(value != NULL) << "StoreGetCurrentMapIteratorValue should not return NULL when iterator is still valid";

		std::string stdStringKey(key);
		if(stdStringKey == solution_key1) {
			ASSERT_EQ(value->type, STORE_STRING) << "value of first map entry should be a store of type string";
			ASSERT_STREQ(value->content.stringValue, solution_value1) << "value of first map entry should have been parsed to the correct string value";
			hits++;
		} else if(stdStringKey == solution_key2) {
			ASSERT_EQ(value->type, STORE_FLOAT) << "value of second map entry should be a store of type float";
			ASSERT_EQ(value->content.floatValue, solution_value2) << "value of second map entry should have been parsed to the correct float value";
			hits++;
		} else {
			ASSERT_TRUE(false) << "invalid parsed entry with key: " << stdStringKey;
		}
	}
	StoreFreeMapIterator(iter);

	ASSERT_EQ(hits, 2) << "loop body should have hit two times";

	StoreFree(result);
}

TEST_F(Parser, StoreParseInvalidElements)
{
	const char *input = " hello world ";
	Store *result = StoreParse(input, &state);
	ASSERT_TRUE(result == NULL) << "StoreParse should return NULL";
	ASSERT_EQ(state.position.index, 0) << "parse state index should not have changed";
	ASSERT_EQ(state.position.column, 1) << "parse state column should not have changed";
}
<|endoftext|>


<commit_before>#ifndef __WORKER_VERSION_
#define __WORKER_VERSION_

#define WORKER_PROGRAM_NAME  "Worker"
#define WORKER_MAJOR_VERSION 0
#define WORKER_MINOR_VERSION 3
#define WORKER_REVISION      0
#define WORKER_POSTSCRIPT    "(dev)"

#endif
<commit_msg>version bump: 0.4.0<commit_after>#ifndef __WORKER_VERSION_
#define __WORKER_VERSION_

#define WORKER_PROGRAM_NAME  "Worker"
#define WORKER_MAJOR_VERSION 0
#define WORKER_MINOR_VERSION 4
#define WORKER_REVISION      0
#define WORKER_POSTSCRIPT    "(dev)"

#endif
<|endoftext|>


<commit_before>// ===============================================================
// Computer Graphics Homework Solutions
// Copyright (C) 2017 by George Wolberg
//
// HW1a.cpp - HW1a class
//
// Written by: George Wolberg, 2017
// ===============================================================

#include "HW1a.h"

// init array of 16 vertices for letter 'P'
float Vertices[] = {
	-0.5f , -0.75f,
	-0.5f , -0.5f,
	-0.5f , -0.25f,
	-0.5f ,  0.0f,
	-0.5f ,  0.25f,
	-0.5f ,  0.5f,
	-0.25f,  0.75f,
	 0.0f ,  0.75f,
	 0.25f,  0.75f,
	 0.5f ,  0.75f,
	 0.75f,  0.5f,
	 0.75f,  0.25f,
	 0.5f ,  0.0f,
	 0.25f,  0.0f,
	 0.0f ,  0.0f,
	-0.25f,  0.0f
};

static int DrawModes[] = {
	GL_POINTS,
	GL_LINES,
	GL_LINE_STRIP,
	GL_LINE_LOOP,
	GL_TRIANGLES,
	GL_TRIANGLE_STRIP,
	GL_TRIANGLE_FAN,
	GL_QUADS,
	GL_POLYGON
};

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HW1a::HW1a:
//
// HW1a constructor.
//
HW1a::HW1a(const QGLFormat &glf, QWidget *parent)
	: HW(glf, parent)
{
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HW1a::initializeGL:
//
// Initialization routine before display loop.
// Gets called once before the first time resizeGL() or paintGL() is called.
//
void
HW1a::initializeGL()
{
	// PUT YOUR CODE HERE
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HW1a::resizeGL:
//
// Resize event handler.
// The input parameters are the window width (w) and height (h).
//
void
HW1a::resizeGL(int w, int h)
{
	// PUT YOUR CODE HERE
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HW1a::paintGL:
//
// Update GL scene.
//
void
HW1a::paintGL()
{
	// PUT YOUR CODE HERE
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HW1a::controlPanel:
//
// Create control panel groupbox.
//
QGroupBox*
HW1a::controlPanel()
{
	// init group box
	QGroupBox *groupBox = new QGroupBox("Homework 1a");
	groupBox->setStyleSheet(GroupBoxStyle);

	return(groupBox);
}
<commit_msg>Add background to HW1a.<commit_after>// ===============================================================
// Computer Graphics Homework Solutions
// Copyright (C) 2017 by George Wolberg
//
// HW1a.cpp - HW1a class
//
// Written by: George Wolberg, 2017
// ===============================================================

#include "HW1a.h"

// init array of 16 vertices for letter 'P'
float Vertices[] = {
	-0.5f , -0.75f,
	-0.5f , -0.5f,
	-0.5f , -0.25f,
	-0.5f ,  0.0f,
	-0.5f ,  0.25f,
	-0.5f ,  0.5f,
	-0.25f,  0.75f,
	 0.0f ,  0.75f,
	 0.25f,  0.75f,
	 0.5f ,  0.75f,
	 0.75f,  0.5f,
	 0.75f,  0.25f,
	 0.5f ,  0.0f,
	 0.25f,  0.0f,
	 0.0f ,  0.0f,
	-0.25f,  0.0f
};

static int DrawModes[] = {
	GL_POINTS,
	GL_LINES,
	GL_LINE_STRIP,
	GL_LINE_LOOP,
	GL_TRIANGLES,
	GL_TRIANGLE_STRIP,
	GL_TRIANGLE_FAN,
	GL_QUADS,
	GL_POLYGON
};

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HW1a::HW1a:
//
// HW1a constructor.
//
HW1a::HW1a(const QGLFormat &glf, QWidget *parent)
	: HW(glf, parent)
{
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HW1a::initializeGL:
//
// Initialization routine before display loop.
// Gets called once before the first time resizeGL() or paintGL() is called.
//
void
HW1a::initializeGL()
{
	// PUT YOUR CODE HERE
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glColor3f		(1.0, 1.0, 1.0);
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HW1a::resizeGL:
//
// Resize event handler.
// The input parameters are the window width (w) and height (h).
//
void
HW1a::resizeGL(int w, int h)
{
	// PUT YOUR CODE HERE
	glViewport(0, 0, w, h);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HW1a::paintGL:
//
// Update GL scene.
//
void
HW1a::paintGL()
{
	// PUT YOUR CODE HERE
	glClear(GL_COLOR_BUFFER_BIT);
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HW1a::controlPanel:
//
// Create control panel groupbox.
//
QGroupBox*
HW1a::controlPanel()
{
	// init group box
	QGroupBox *groupBox = new QGroupBox("Homework 1a");
	groupBox->setStyleSheet(GroupBoxStyle);

	return(groupBox);
}
<|endoftext|>


<commit_before><commit_msg>Make the eviction function faster by reading/writing 1MB blocks instead of 4k. Review URL: http://codereview.chromium.org/442011<commit_after><|endoftext|>


<commit_before>#include "connection.hpp"

#include "../helpers/filehelper.hpp"
#include "../helpers/stringhelper.hpp"

Connection *Connection::m_connection = NULL;

Connection::Connection(QObject *parent) : QObject(parent)
{
    QString db_filename = "db.sqlite3";
    if (!FileHelper::fileExists("db.sqlite3"))
    {
        Connection::m_db = QSqlDatabase::addDatabase("QSQLITE");
        m_db.setDatabaseName(db_filename);
        m_db.open();
        qDebug() << "Database created successfully!";
        QStringList qList = FileHelper::fileToString("../database.sql");
        foreach (QString q, qList) {
            //qDebug() << q;
            m_db.exec(q);
        }
        seed();
    }
    else {
        Connection::m_db = QSqlDatabase::addDatabase("QSQLITE");
        m_db.setDatabaseName(db_filename);
        m_db.open();
    }
}

void Connection::seed()
{
    QStringList qList = FileHelper::fileToString("../seeds.sql");
    foreach (QString q, qList) {
        //qDebug() << q;
        m_db.exec(q);
    }
}

Connection *Connection::getConnection()
{
    if (m_connection == NULL) {
        m_connection = new Connection;
    }
    return m_connection;
}

CityList Connection::getAllCities()
{
    QSqlQuery q;
    q.prepare("select * from cities");
    q.exec();
    CityList cities;
    while (q.next()) {
        City *c = new City();
        c->setId(q.value(0).toInt());
        c->setName(q.value(1).toString());
        cities.append(c);
    }
    return cities;
}

CustomerList Connection::getAllCustomers()
{
    QSqlQuery q;
    q.prepare("select * from customers");
    q.exec();
    CustomerList customers;
    while (q.next()) {
        Customer *c = new Customer();
        c->setId(q.value(0).toInt());
        c->setTc(q.value(1).toString());
        c->setName(q.value(2).toString());
        c->setSurname(q.value(3).toString());
        c->setPhone(q.value(4).toString());
        c->setCity(getCity(q.value(5).toInt()));
        c->setAddress(q.value(6).toString());
        customers.append(c);
    }
    return customers;
}

DistanceList Connection::getAllDistances()
{
    QSqlQuery q;
    q.prepare("select * from distances");
    q.exec();
    DistanceList distances;
    while (q.next()) {
        Distance *d = new Distance();
        d->setId(q.value(0).toInt());
        d->setFirstOffice(getOffice(q.value(1).toInt()));
        d->setSecondOffice(getOffice(q.value(2).toInt()));
        d->setValue(q.value(3).toDouble());
        distances.append(d);
    }
    return distances;
}

OfficeList Connection::getAllOffices()
{
    QSqlQuery q;
    q.prepare("select * from offices");
    q.exec();
    OfficeList offices;
    while (q.next()) {
        Office *o = new Office();
        o->setId(q.value(0).toInt());
        o->setName(q.value(1).toString());
        o->setCity(getCity(q.value(2).toInt()));
        o->setAddress(q.value(3).toString());
        offices.append(o);
    }
    return offices;
}

ShipmentList Connection::getAllShipments()
{
    QSqlQuery q;
    q.prepare("select * from shioments");
    q.exec();
    ShipmentList shipments;
    while (q.next()) {
        Shipment *s = new Shipment();
        s->setId(q.value(0).toInt());
        s->setLength(q.value(1).toInt());
        s->setWidth(q.value(2).toInt());
        s->setHeight(q.value(3).toInt());
        s->setWeight(q.value(4).toInt());
        s->setSendingCustomer(getCustomer(q.value(5).toInt()));
        s->setReceivingCustomer(getCustomer(q.value(6).toInt()));
        s->setPaymentType(q.value(7).toInt());
        s->setAmount(q.value(8).toDouble());
        s->setStatus(q.value(9).toString());
        s->setSendingOffice(getOffice(q.value(10).toInt()));
        s->setReceivingOffice(getOffice(q.value(11).toInt()));
        shipments.append(s);
    }
    return shipments;
}

City *Connection::getCity(int id)
{
    QSqlQuery q;
    q.prepare("select * from cities where id = ?");
    q.bindValue(0, id);
    q.exec();
    CityList cities;
    while (q.next()) {
        City *c = new City();
        c->setId(q.value(0).toInt());
        c->setName(q.value(1).toString());
        cities.append(c);
    }
    return cities.first();
}

Customer *Connection::getCustomer(int id)
{
    QSqlQuery q;
    q.prepare("select * from customers where id = ?");
    q.bindValue(0, id);
    q.exec();
    CustomerList customers;
    while (q.next()) {
        Customer *c = new Customer();
        c->setId(q.value(0).toInt());
        c->setTc(q.value(1).toString());
        c->setName(q.value(2).toString());
        c->setSurname(q.value(3).toString());
        c->setPhone(q.value(4).toString());
        c->setCity(getCity(q.value(5).toInt()));
        c->setAddress(q.value(6).toString());
        customers.append(c);
    }
    return customers.first();
}

Distance *Connection::getDistance(int id)
{
    QSqlQuery q;
    q.prepare("select * from distances where id = ?");
    q.bindValue(0, id);
    q.exec();
    DistanceList distances;
    while (q.next()) {
        Distance *d = new Distance();
        d->setId(q.value(0).toInt());
        d->setFirstOffice(getOffice(q.value(1).toInt()));
        d->setSecondOffice(getOffice(q.value(2).toInt()));
        d->setValue(q.value(3).toDouble());
        distances.append(d);
    }
    return distances.first();
}

Office *Connection::getOffice(int id)
{
    QSqlQuery q;
    q.prepare("select * from offices where id = ?");
    q.bindValue(0, id);
    q.exec();
    OfficeList offices;
    while (q.next()) {
        Office *o = new Office();
        o->setId(q.value(0).toInt());
        o->setName(q.value(1).toString());
        o->setCity(getCity(q.value(2).toInt()));
        o->setAddress(q.value(3).toString());
        offices.append(o);
    }
    return offices.first();
}

Shipment *Connection::getShipment(int id)
{
    QSqlQuery q;
    q.prepare("select * from shipments where id = ?");
    q.bindValue(0, id);
    q.exec();
    ShipmentList shipments;
    while (q.next()) {
        Shipment *s = new Shipment();
        s->setId(q.value(0).toInt());
        s->setLength(q.value(1).toInt());
        s->setWidth(q.value(2).toInt());
        s->setHeight(q.value(3).toInt());
        s->setWeight(q.value(4).toInt());
        s->setSendingCustomer(getCustomer(q.value(5).toInt()));
        s->setReceivingCustomer(getCustomer(q.value(6).toInt()));
        s->setPaymentType(q.value(7).toInt());
        s->setAmount(q.value(8).toDouble());
        s->setStatus(q.value(9).toString());
        s->setSendingOffice(getOffice(q.value(10).toInt()));
        s->setReceivingOffice(getOffice(q.value(11).toInt()));
        shipments.append(s);
    }
    if (shipments.isEmpty())
        return new Shipment();
    return shipments.first();
}

City *Connection::updateCity(City *c)
{
    QSqlQuery q;
    q.prepare("update cities set name = ? where id = ?");
    q.bindValue(0, c->getName());
    q.bindValue(1, c->getId());
    q.exec();
    return c;
}

Customer *Connection::updateCustomer(Customer *c)
{
    QSqlQuery q;
    q.prepare("update customers set tc = ?, name = ?, surname = ?,\
              phone = ?, city_id = ?, address = ? where id = ?"\
                                                              );
    q.bindValue(0, c->getTc());
    q.bindValue(1, c->getName());
    q.bindValue(2, c->getSurname());
    q.bindValue(3, c->getPhone());
    q.bindValue(4, c->getCity()->getId());
    q.bindValue(5, c->getAddress());
    q.bindValue(6, c->getId());
    q.exec();
    return c;
}

Distance *Connection::updateDistance(Distance *d)
{
    QSqlQuery q;
    q.prepare("update distances set first_office_id = ?, second_office_id = ?, \
              value = ? where id = ?"\
                                    );
    q.bindValue(0, d->getFirstOffice()->getId());
    q.bindValue(1, d->getSecondOffice()->getId());
    q.bindValue(2, d->getValue());
    q.bindValue(3, d->getId());
    q.exec();
    return d;
}

Office *Connection::updateOffice(Office *o)
{
    QSqlQuery q;
    q.prepare("update offices set name = ?, city_id = ?, address = ? where id = ?");
    q.bindValue(0, o->getName());
    q.bindValue(1, o->getCity()->getId());
    q.bindValue(2, o->getAddress());
    q.bindValue(3, o->getId());
    q.exec();
    return o;
}

Shipment *Connection::updateShipment(Shipment *s)
{
    QSqlQuery q;
    q.prepare("update shipments set length = ?, width = ?, height = ?,\
              weight = ?, sending_customer_id = ?, receiving_customer_id = ?,\
              payment_type = ?, amount = ?, status = ?, sending_office_id = ?, \
              receiving_office_id = ? where id = ?"\
                                                  );
    q.bindValue(0, s->getLength());
    q.bindValue(1, s->getWeight());
    q.bindValue(2, s->getHeight());
    q.bindValue(3, s->getWeight());
    q.bindValue(4, s->getSendingCustomer()->getId());
    q.bindValue(5, s->getReceivingCustomer()->getId());
    q.bindValue(6, s->getPaymentType());
    q.bindValue(7, s->getAmount());
    q.bindValue(8, s->getStatus());
    q.bindValue(9, s->getSendingOffice()->getId());
    q.bindValue(10, s->getReceivingOffice()->getId());
    q.bindValue(11, s->getId());
    q.exec();
    return s;
}

CityList Connection::getCities(QString value)
{
    QSqlQuery q;
    q.prepare("select * from cities where name like ?");
    q.bindValue(0, StringHelper::sqlHasLike(value));
    q.exec();
    CityList cities;
    while (q.next()) {
        City *c = new City();
        c->setId(q.value(0).toInt());
        c->setName(q.value(1).toString());
        cities.append(c);
    }
    if (cities.isEmpty())
        cities.append(new City);
    return cities;
}

CustomerList Connection::getCustomers(QString value)
{
    QSqlQuery q;
    q.prepare("select * from customers where id = ? or tc like ?\
              or name like ? or surname like ? or phone like ?\
              or city_id = ? or address like ?"\
                                 );
    q.bindValue(0, value.toInt()); // id
    q.bindValue(1, StringHelper::sqlHasLike(value)); // tc
    q.bindValue(2, StringHelper::sqlHasLike(value)); // name
    q.bindValue(3, StringHelper::sqlHasLike(value)); // surname
    q.bindValue(4, StringHelper::sqlHasLike(value)); // phone
    q.bindValue(5, StringHelper::sqlHasLike(value)); // city_id
    q.bindValue(6, StringHelper::sqlHasLike(value)); // address
    q.exec();
    qDebug() << q.lastQuery();
    CustomerList customers;
    while (q.next()) {
        Customer *c = new Customer();
        c->setId(q.value(0).toInt());
        c->setTc(q.value(1).toString());
        c->setName(q.value(2).toString());
        c->setSurname(q.value(3).toString());
        c->setPhone(q.value(4).toString());
        c->setCity(getCity(q.value(5).toInt()));
        c->setAddress(q.value(6).toString());
        customers.append(c);
    }
    if (customers.isEmpty())
        customers.append(new Customer);
    return customers;
}

DistanceList Connection::getDistances()
{

}

OfficeList Connection::getOffices(QString value)
{

}

ShipmentList Connection::getShipments(QString value)
{

}

City *Connection::createCity(City *c)
{

}

Customer *Connection::createCustomer(Customer *c)
{

}

Distance *Connection::createDistance(Distance *d)
{

}

Office *Connection::createOffice(Office *o)
{

}

Shipment *Connection::createShipment(Shipment *s)
{

}

<commit_msg>Connection::getOffices function created<commit_after>#include "connection.hpp"

#include "../helpers/filehelper.hpp"
#include "../helpers/stringhelper.hpp"

Connection *Connection::m_connection = NULL;

Connection::Connection(QObject *parent) : QObject(parent)
{
    QString db_filename = "db.sqlite3";
    if (!FileHelper::fileExists("db.sqlite3"))
    {
        Connection::m_db = QSqlDatabase::addDatabase("QSQLITE");
        m_db.setDatabaseName(db_filename);
        m_db.open();
        qDebug() << "Database created successfully!";
        QStringList qList = FileHelper::fileToString("../database.sql");
        foreach (QString q, qList) {
            //qDebug() << q;
            m_db.exec(q);
        }
        seed();
    }
    else {
        Connection::m_db = QSqlDatabase::addDatabase("QSQLITE");
        m_db.setDatabaseName(db_filename);
        m_db.open();
    }
}

void Connection::seed()
{
    QStringList qList = FileHelper::fileToString("../seeds.sql");
    foreach (QString q, qList) {
        //qDebug() << q;
        m_db.exec(q);
    }
}

Connection *Connection::getConnection()
{
    if (m_connection == NULL) {
        m_connection = new Connection;
    }
    return m_connection;
}

CityList Connection::getAllCities()
{
    QSqlQuery q;
    q.prepare("select * from cities");
    q.exec();
    CityList cities;
    while (q.next()) {
        City *c = new City();
        c->setId(q.value(0).toInt());
        c->setName(q.value(1).toString());
        cities.append(c);
    }
    return cities;
}

CustomerList Connection::getAllCustomers()
{
    QSqlQuery q;
    q.prepare("select * from customers");
    q.exec();
    CustomerList customers;
    while (q.next()) {
        Customer *c = new Customer();
        c->setId(q.value(0).toInt());
        c->setTc(q.value(1).toString());
        c->setName(q.value(2).toString());
        c->setSurname(q.value(3).toString());
        c->setPhone(q.value(4).toString());
        c->setCity(getCity(q.value(5).toInt()));
        c->setAddress(q.value(6).toString());
        customers.append(c);
    }
    return customers;
}

DistanceList Connection::getAllDistances()
{
    QSqlQuery q;
    q.prepare("select * from distances");
    q.exec();
    DistanceList distances;
    while (q.next()) {
        Distance *d = new Distance();
        d->setId(q.value(0).toInt());
        d->setFirstOffice(getOffice(q.value(1).toInt()));
        d->setSecondOffice(getOffice(q.value(2).toInt()));
        d->setValue(q.value(3).toDouble());
        distances.append(d);
    }
    return distances;
}

OfficeList Connection::getAllOffices()
{
    QSqlQuery q;
    q.prepare("select * from offices");
    q.exec();
    OfficeList offices;
    while (q.next()) {
        Office *o = new Office();
        o->setId(q.value(0).toInt());
        o->setName(q.value(1).toString());
        o->setCity(getCity(q.value(2).toInt()));
        o->setAddress(q.value(3).toString());
        offices.append(o);
    }
    return offices;
}

ShipmentList Connection::getAllShipments()
{
    QSqlQuery q;
    q.prepare("select * from shioments");
    q.exec();
    ShipmentList shipments;
    while (q.next()) {
        Shipment *s = new Shipment();
        s->setId(q.value(0).toInt());
        s->setLength(q.value(1).toInt());
        s->setWidth(q.value(2).toInt());
        s->setHeight(q.value(3).toInt());
        s->setWeight(q.value(4).toInt());
        s->setSendingCustomer(getCustomer(q.value(5).toInt()));
        s->setReceivingCustomer(getCustomer(q.value(6).toInt()));
        s->setPaymentType(q.value(7).toInt());
        s->setAmount(q.value(8).toDouble());
        s->setStatus(q.value(9).toString());
        s->setSendingOffice(getOffice(q.value(10).toInt()));
        s->setReceivingOffice(getOffice(q.value(11).toInt()));
        shipments.append(s);
    }
    return shipments;
}

City *Connection::getCity(int id)
{
    QSqlQuery q;
    q.prepare("select * from cities where id = ?");
    q.bindValue(0, id);
    q.exec();
    CityList cities;
    while (q.next()) {
        City *c = new City();
        c->setId(q.value(0).toInt());
        c->setName(q.value(1).toString());
        cities.append(c);
    }
    return cities.first();
}

Customer *Connection::getCustomer(int id)
{
    QSqlQuery q;
    q.prepare("select * from customers where id = ?");
    q.bindValue(0, id);
    q.exec();
    CustomerList customers;
    while (q.next()) {
        Customer *c = new Customer();
        c->setId(q.value(0).toInt());
        c->setTc(q.value(1).toString());
        c->setName(q.value(2).toString());
        c->setSurname(q.value(3).toString());
        c->setPhone(q.value(4).toString());
        c->setCity(getCity(q.value(5).toInt()));
        c->setAddress(q.value(6).toString());
        customers.append(c);
    }
    return customers.first();
}

Distance *Connection::getDistance(int id)
{
    QSqlQuery q;
    q.prepare("select * from distances where id = ?");
    q.bindValue(0, id);
    q.exec();
    DistanceList distances;
    while (q.next()) {
        Distance *d = new Distance();
        d->setId(q.value(0).toInt());
        d->setFirstOffice(getOffice(q.value(1).toInt()));
        d->setSecondOffice(getOffice(q.value(2).toInt()));
        d->setValue(q.value(3).toDouble());
        distances.append(d);
    }
    return distances.first();
}

Office *Connection::getOffice(int id)
{
    QSqlQuery q;
    q.prepare("select * from offices where id = ?");
    q.bindValue(0, id);
    q.exec();
    OfficeList offices;
    while (q.next()) {
        Office *o = new Office();
        o->setId(q.value(0).toInt());
        o->setName(q.value(1).toString());
        o->setCity(getCity(q.value(2).toInt()));
        o->setAddress(q.value(3).toString());
        offices.append(o);
    }
    return offices.first();
}

Shipment *Connection::getShipment(int id)
{
    QSqlQuery q;
    q.prepare("select * from shipments where id = ?");
    q.bindValue(0, id);
    q.exec();
    ShipmentList shipments;
    while (q.next()) {
        Shipment *s = new Shipment();
        s->setId(q.value(0).toInt());
        s->setLength(q.value(1).toInt());
        s->setWidth(q.value(2).toInt());
        s->setHeight(q.value(3).toInt());
        s->setWeight(q.value(4).toInt());
        s->setSendingCustomer(getCustomer(q.value(5).toInt()));
        s->setReceivingCustomer(getCustomer(q.value(6).toInt()));
        s->setPaymentType(q.value(7).toInt());
        s->setAmount(q.value(8).toDouble());
        s->setStatus(q.value(9).toString());
        s->setSendingOffice(getOffice(q.value(10).toInt()));
        s->setReceivingOffice(getOffice(q.value(11).toInt()));
        shipments.append(s);
    }
    if (shipments.isEmpty())
        return new Shipment();
    return shipments.first();
}

City *Connection::updateCity(City *c)
{
    QSqlQuery q;
    q.prepare("update cities set name = ? where id = ?");
    q.bindValue(0, c->getName());
    q.bindValue(1, c->getId());
    q.exec();
    return c;
}

Customer *Connection::updateCustomer(Customer *c)
{
    QSqlQuery q;
    q.prepare("update customers set tc = ?, name = ?, surname = ?,\
              phone = ?, city_id = ?, address = ? where id = ?"\
                                                              );
    q.bindValue(0, c->getTc());
    q.bindValue(1, c->getName());
    q.bindValue(2, c->getSurname());
    q.bindValue(3, c->getPhone());
    q.bindValue(4, c->getCity()->getId());
    q.bindValue(5, c->getAddress());
    q.bindValue(6, c->getId());
    q.exec();
    return c;
}

Distance *Connection::updateDistance(Distance *d)
{
    QSqlQuery q;
    q.prepare("update distances set first_office_id = ?, second_office_id = ?, \
              value = ? where id = ?"\
                                    );
    q.bindValue(0, d->getFirstOffice()->getId());
    q.bindValue(1, d->getSecondOffice()->getId());
    q.bindValue(2, d->getValue());
    q.bindValue(3, d->getId());
    q.exec();
    return d;
}

Office *Connection::updateOffice(Office *o)
{
    QSqlQuery q;
    q.prepare("update offices set name = ?, city_id = ?, address = ? where id = ?");
    q.bindValue(0, o->getName());
    q.bindValue(1, o->getCity()->getId());
    q.bindValue(2, o->getAddress());
    q.bindValue(3, o->getId());
    q.exec();
    return o;
}

Shipment *Connection::updateShipment(Shipment *s)
{
    QSqlQuery q;
    q.prepare("update shipments set length = ?, width = ?, height = ?,\
              weight = ?, sending_customer_id = ?, receiving_customer_id = ?,\
              payment_type = ?, amount = ?, status = ?, sending_office_id = ?, \
              receiving_office_id = ? where id = ?"\
                                                  );
    q.bindValue(0, s->getLength());
    q.bindValue(1, s->getWeight());
    q.bindValue(2, s->getHeight());
    q.bindValue(3, s->getWeight());
    q.bindValue(4, s->getSendingCustomer()->getId());
    q.bindValue(5, s->getReceivingCustomer()->getId());
    q.bindValue(6, s->getPaymentType());
    q.bindValue(7, s->getAmount());
    q.bindValue(8, s->getStatus());
    q.bindValue(9, s->getSendingOffice()->getId());
    q.bindValue(10, s->getReceivingOffice()->getId());
    q.bindValue(11, s->getId());
    q.exec();
    return s;
}

CityList Connection::getCities(QString value)
{
    QSqlQuery q;
    q.prepare("select * from cities where name like ?");
    q.bindValue(0, StringHelper::sqlHasLike(value));
    q.exec();
    CityList cities;
    while (q.next()) {
        City *c = new City();
        c->setId(q.value(0).toInt());
        c->setName(q.value(1).toString());
        cities.append(c);
    }
    if (cities.isEmpty())
        cities.append(new City);
    return cities;
}

CustomerList Connection::getCustomers(QString value)
{
    QSqlQuery q;
    q.prepare("select * from customers where id = ? or tc like ?\
              or name like ? or surname like ? or phone like ?\
              or city_id = ? or address like ?"\
                                 );
    q.bindValue(0, value.toInt()); // id
    q.bindValue(1, StringHelper::sqlHasLike(value)); // tc
    q.bindValue(2, StringHelper::sqlHasLike(value)); // name
    q.bindValue(3, StringHelper::sqlHasLike(value)); // surname
    q.bindValue(4, StringHelper::sqlHasLike(value)); // phone
    q.bindValue(5, StringHelper::sqlHasLike(value)); // city_id
    q.bindValue(6, StringHelper::sqlHasLike(value)); // address
    q.exec();
    qDebug() << q.lastQuery();
    CustomerList customers;
    while (q.next()) {
        Customer *c = new Customer();
        c->setId(q.value(0).toInt());
        c->setTc(q.value(1).toString());
        c->setName(q.value(2).toString());
        c->setSurname(q.value(3).toString());
        c->setPhone(q.value(4).toString());
        c->setCity(getCity(q.value(5).toInt()));
        c->setAddress(q.value(6).toString());
        customers.append(c);
    }
    if (customers.isEmpty())
        customers.append(new Customer);
    return customers;
}

DistanceList Connection::getDistances()
{

}

OfficeList Connection::getOffices(QString value)
{
    QSqlQuery q;
    q.prepare("select * from offices where name like ?");
    q.bindValue(0, StringHelper::sqlHasLike(value));
    q.exec();
    OfficeList offices;
    while (q.next()) {
        Office *o = new Office();
        o->setId(q.value(0).toInt());
        o->setName(q.value(1).toString());
        o->setCity(getCity(q.value(2).toInt()));
        o->setAddress(q.value(3).toString());
        offices.append(o);
    }
    if (offices.isEmpty())
        offices.append(new Office);
    return offices;
}

ShipmentList Connection::getShipments(QString value)
{

}

City *Connection::createCity(City *c)
{

}

Customer *Connection::createCustomer(Customer *c)
{

}

Distance *Connection::createDistance(Distance *d)
{

}

Office *Connection::createOffice(Office *o)
{

}

Shipment *Connection::createShipment(Shipment *s)
{

}

<|endoftext|>


<commit_before>//===========================================
//  Lumina-DE source code
//  Copyright (c) 2020, Ken Moore
//  Available under the 3-clause BSD license
//  See the LICENSE file for full details
//===========================================

#include <QApplication>
#include <QPixmap>
#include <QLabel>
#include <QDateTime>
#include <QPoint>
int main(int argc, char **argv){
  //Setup the application
  QApplication App(argc, argv);
    App.setAttribute(Qt::AA_UseHighDpiPixmaps);
  //Display the OSD
  QWidget splash(0, Qt::Window | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
     splash.setWindowTitle("");
     splash.setStyleSheet("background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 transparent, stop:0.52 transparent, stop:0.565 rgba(82, 121, 76, 33), stop:0.65 rgba(159, 235, 148, 64), stop:0.721925 rgba(255, 238, 150, 129), stop:0.77 rgba(255, 128, 128, 204), stop:0.89 rgba(191, 128, 255, 64), stop:1 transparent);");
     splash.setWindowOpacity(0);
     splash.resize(100,100);
  //Make sure it is centered on the current screen
  QPoint center = QCursor::pos();
  splash.move(center.x()-(splash.size().width()/2), center.y()-(splash.size().height()/2));
  splash.show();
  QDateTime end = QDateTime::currentDateTime().addMSecs(1000);
  while(QDateTime::currentDateTime() < end){ App.processEvents(); }
  splash.hide();
  return 0;
}
<commit_msg>Get the window transparency and ring animation finished up. All set now.<commit_after>//===========================================
//  Lumina-DE source code
//  Copyright (c) 2020, Ken Moore
//  Available under the 3-clause BSD license
//  See the LICENSE file for full details
//===========================================

#include <QApplication>
#include <QPixmap>
#include <QLabel>
#include <QDateTime>
#include <QPoint>
#include <QScreen>
#include <QDesktopWidget>
#include <QPropertyAnimation>

int main(int argc, char **argv){
  //Setup the application
  QApplication App(argc, argv);
    App.setAttribute(Qt::AA_UseHighDpiPixmaps);
  //Display the OSD
  QLabel splash(0, Qt::Window | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint | Qt::NoDropShadowWindowHint);
     splash.setWindowTitle("");
     splash.resize(100,100);
  QWidget overlay( &splash );
    overlay.setStyleSheet("margin: 0px; border: none; background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(0, 0, 0, 0), stop:0.52 rgba(0, 0, 0, 0), stop:0.565 rgba(82, 121, 76, 33), stop:0.65 rgba(159, 235, 148, 64), stop:0.721925 rgba(255, 238, 150, 129), stop:0.77 rgba(130, 205, 47, 204), stop:0.89 rgba(100, 128, 255, 64), stop:1 rgba(0, 0, 0, 0));");
    overlay.setGeometry(QRect(0,0,100,100));
  //Make sure it is centered on the current screen
  QPoint center = QCursor::pos();
  splash.move(center.x()-(splash.size().width()/2), center.y()-(splash.size().height()/2));
  splash.setPixmap(QApplication::screens().at(0)->grabWindow(QApplication::desktop()->winId(), splash.x(), splash.y(), 100,100) );
  splash.show();
  QPropertyAnimation anim(&splash,"windowOpacity");
  anim.setDuration(1500);
  anim.setStartValue(1);
  anim.setKeyValueAt(0.30, 0); anim.setKeyValueAt(0.31, 1);
  anim.setKeyValueAt(0.60, 0); anim.setKeyValueAt(0.61, 1);
  anim.setEndValue(0);
  anim.start();
  while(anim.state() != QAbstractAnimation::Stopped){ App.processEvents(); }
  splash.hide();
  return 0;
}
<|endoftext|>


<commit_before><commit_msg>handle failed bitmap storage allocation gracefully<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "istream_rubber.hxx"
#include "istream/istream.hxx"
#include "istream/Bucket.hxx"
#include "rubber.hxx"
#include "util/ConstBuffer.hxx"

#include <algorithm>

#include <assert.h>
#include <stdint.h>

class RubberIstream final : public Istream {
    Rubber &rubber;
    const unsigned id;
    const bool auto_remove;

    size_t position;
    const size_t end;

public:
    RubberIstream(struct pool &p, Rubber &_rubber, unsigned _id,
                  size_t start, size_t _end,
                  bool _auto_remove)
        :Istream(p), rubber(_rubber), id(_id), auto_remove(_auto_remove),
         position(start), end(_end) {}

    /* virtual methods from class Istream */

    off_t _GetAvailable(gcc_unused bool partial) override {
        return end - position;
    }

    off_t _Skip(off_t nbytes) override {
        assert(position <= end);

        const size_t remaining = end - position;
        if (nbytes > off_t(remaining))
            nbytes = remaining;

        position += nbytes;
        Consumed(nbytes);
        return nbytes;
    }

    void _Read() override {
        assert(position <= end);

        const uint8_t *data = (const uint8_t *)rubber.Read(id);
        const size_t remaining = end - position;

        if (remaining > 0) {
            size_t nbytes = InvokeData(data + position, remaining);
            if (nbytes == 0)
                return;

            position += nbytes;
        }

        if (position == end) {
            if (auto_remove)
                rubber.Remove(id);

            DestroyEof();
        }
    }

    void _FillBucketList(IstreamBucketList &list) override {
        const uint8_t *data = (const uint8_t *)rubber.Read(id);
        const size_t remaining = end - position;

        if (remaining > 0)
            list.Push(ConstBuffer<void>(data + position, remaining));
    }

    size_t _ConsumeBucketList(size_t nbytes) override {
        const size_t remaining = end - position;
        size_t consumed = std::min(nbytes, remaining);
        position += consumed;
        Consumed(consumed);
        return consumed;
    }

    void _Close() noexcept override {
        if (auto_remove)
            rubber.Remove(id);

        Istream::_Close();
    }
};

Istream *
istream_rubber_new(struct pool &pool, Rubber &rubber,
                   unsigned id, size_t start, size_t end,
                   bool auto_remove)
{
    assert(id > 0);
    assert(start <= end);

    return NewIstream<RubberIstream>(pool, rubber, id,
                                     start, end, auto_remove);
}
<commit_msg>istream_rubber: move Remove() call to destructor<commit_after>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "istream_rubber.hxx"
#include "istream/istream.hxx"
#include "istream/Bucket.hxx"
#include "rubber.hxx"
#include "util/ConstBuffer.hxx"

#include <algorithm>

#include <assert.h>
#include <stdint.h>

class RubberIstream final : public Istream {
    Rubber &rubber;
    const unsigned id;
    const bool auto_remove;

    size_t position;
    const size_t end;

public:
    RubberIstream(struct pool &p, Rubber &_rubber, unsigned _id,
                  size_t start, size_t _end,
                  bool _auto_remove)
        :Istream(p), rubber(_rubber), id(_id), auto_remove(_auto_remove),
         position(start), end(_end) {}

    ~RubberIstream() noexcept override {
        if (auto_remove)
            rubber.Remove(id);
    }

    /* virtual methods from class Istream */

    off_t _GetAvailable(gcc_unused bool partial) override {
        return end - position;
    }

    off_t _Skip(off_t nbytes) override {
        assert(position <= end);

        const size_t remaining = end - position;
        if (nbytes > off_t(remaining))
            nbytes = remaining;

        position += nbytes;
        Consumed(nbytes);
        return nbytes;
    }

    void _Read() override {
        assert(position <= end);

        const uint8_t *data = (const uint8_t *)rubber.Read(id);
        const size_t remaining = end - position;

        if (remaining > 0) {
            size_t nbytes = InvokeData(data + position, remaining);
            if (nbytes == 0)
                return;

            position += nbytes;
        }

        if (position == end)
            DestroyEof();
    }

    void _FillBucketList(IstreamBucketList &list) override {
        const uint8_t *data = (const uint8_t *)rubber.Read(id);
        const size_t remaining = end - position;

        if (remaining > 0)
            list.Push(ConstBuffer<void>(data + position, remaining));
    }

    size_t _ConsumeBucketList(size_t nbytes) override {
        const size_t remaining = end - position;
        size_t consumed = std::min(nbytes, remaining);
        position += consumed;
        Consumed(consumed);
        return consumed;
    }
};

Istream *
istream_rubber_new(struct pool &pool, Rubber &rubber,
                   unsigned id, size_t start, size_t end,
                   bool auto_remove)
{
    assert(id > 0);
    assert(start <= end);

    return NewIstream<RubberIstream>(pool, rubber, id,
                                     start, end, auto_remove);
}
<|endoftext|>


<commit_before>/*
    kopeteonlinestatus.cpp - Kopete Online Status

    Copyright (c) 2002-2004 by Olivier Goffart       <ogoffart@tiscalinet.be>
    Copyright (c) 2003      by Martijn Klingens      <klingens@kde.org>

    Kopete    (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program is free software; you can redistribute it and/or modify  *
    * it under the terms of the GNU General Public License as published by  *
    * the Free Software Foundation; either version 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/

#include <qpainter.h>

#include <klocale.h>
#include <kiconloader.h>
#include <kdebug.h>

#include "kopetecontactlistview.h"
#include "kopetegroupviewitem.h"
#include "kopetegroup.h"
#include "kopeteonlinestatus.h"
#include "kopeteprefs.h"
#include "kopetemetacontactlvi.h"
#include "kopetemetacontact.h"

#include <memory>

using namespace Kopete::UI;

class KopeteGroupViewItem::Private
{
public:
	ListView::ImageComponent *image;
	ListView::TextComponent *name;
	ListView::TextComponent *count;
	std::auto_ptr<ListView::ToolTipSource> toolTipSource;
};

namespace Kopete {
namespace UI {
namespace ListView {

class GroupToolTipSource : public ToolTipSource
{
public:
	GroupToolTipSource( KopeteGroupViewItem *gp )
	 : group( gp )
	{
	}
	QString operator()( ComponentBase *, const QPoint &, QRect & )
	{
		return group->toolTip();
	}
private:
	KopeteGroupViewItem *group;
};

} // END namespace ListView
} // END namespace UI
} // END namespace Kopete

KopeteGroupViewItem::KopeteGroupViewItem( KopeteGroup *group_, QListView *parent, const char *name )
: Kopete::UI::ListView::Item( parent, group_, name )
{
	m_group = group_;
	initLVI();
}

KopeteGroupViewItem::KopeteGroupViewItem( KopeteGroup *group_, QListViewItem *parent, const char *name )
 : Kopete::UI::ListView::Item( parent, group_, name )
{
	m_group = group_;
	initLVI();
}

KopeteGroupViewItem::~KopeteGroupViewItem()
{
	delete d;
}

void KopeteGroupViewItem::initLVI()
{
	d = new Private;

	d->toolTipSource.reset( new ListView::GroupToolTipSource( this ) );

	using namespace ListView;
	Component *hbox = new BoxComponent( this, BoxComponent::Horizontal );
	d->image = new ImageComponent( hbox );
	d->name = new TextComponent( hbox );
	d->count = new TextComponent( hbox );

	d->image->setToolTipSource( d->toolTipSource.get() );
	d->name->setToolTipSource( d->toolTipSource.get() );
	d->count->setToolTipSource( d->toolTipSource.get() );

	connect( m_group, SIGNAL( renamed( KopeteGroup*, const QString& ) ),
		this, SLOT( refreshDisplayName() ) );

	connect( KopetePrefs::prefs(), SIGNAL( contactListAppearanceChanged() ),
		SLOT( slotConfigChanged() ) );

	connect( m_group, SIGNAL( iconAppearanceChanged() ), SLOT( updateIcon() ) );

	refreshDisplayName();
	slotConfigChanged();
}

KopeteGroup* KopeteGroupViewItem::group() const
{
	return m_group;
}

QString KopeteGroupViewItem::toolTip() const
{
	// TODO: add icon, and some more information than that which
	// is already displayed in the list view item
	return "" + d->name->text() + " " + d->count->text();
}

void KopeteGroupViewItem::slotConfigChanged()
{
	updateIcon();
	updateVisibility();

	d->name->setColor( KopetePrefs::prefs()->contactListGroupNameColor() );

	QFont font = listView()->font();
	if ( KopetePrefs::prefs()->contactListUseCustomFonts() )
		font = KopetePrefs::prefs()->contactListCustomNormalFont();
	d->name->setFont( font );

	d->count->setFont( KopetePrefs::prefs()->contactListSmallFont() );
}

void KopeteGroupViewItem::refreshDisplayName()
{
	totalMemberCount = 0;
	onlineMemberCount = 0;

	for ( QListViewItem *lvi = firstChild(); lvi; lvi = lvi->nextSibling() )
	{
		if ( KopeteMetaContactLVI *kc = dynamic_cast<KopeteMetaContactLVI*>( lvi ) )
		{
			totalMemberCount++;
			if ( kc->metaContact()->isOnline() )
				onlineMemberCount++;
		}
	}

	d->name->setText( m_group->displayName() );
	d->count->setText( i18n( "(NUMBER OF ONLINE CONTACTS/NUMBER OF CONTACTS IN GROUP)", "(%1/%2)" )
	                  .arg( QString::number( onlineMemberCount ), QString::number( totalMemberCount ) ) );

	updateVisibility();

	// Sorting in this slot is extremely expensive as it's called dozens of times and
	// the sorting itself is rather slow. Therefore we call delayedSort, which tries
	// to group multiple sort requests into one.
	if ( KopeteContactListView *lv = dynamic_cast<KopeteContactListView *>( listView() ) )
		lv->delayedSort();
	else
		listView()->sort();
}

QString KopeteGroupViewItem::key( int, bool ) const
{
	//Groups are placed after topLevel contact.
	//Exepted Temporary group which is the first group
	if ( group()->type() != KopeteGroup::Normal )
		return "0" + d->name->text();
	return "M" + d->name->text();
}

void KopeteGroupViewItem::startRename( int col )
{
	//kdDebug(14000) << k_funcinfo << endl;
	KListViewItem::startRename( 0 );
}

void KopeteGroupViewItem::okRename( int col )
{
	//kdDebug(14000) << k_funcinfo << endl;
	KListViewItem::okRename(col);
	if ( col == 0 )
		group()->setDisplayName(text(0));
	setRenameEnabled( 0, false );
	refreshDisplayName();
}

void KopeteGroupViewItem::cancelRename( int col )
{
	//kdDebug(14000) << k_funcinfo << endl;
	KListViewItem::cancelRename(col);
	setRenameEnabled( 0, false );
}

void KopeteGroupViewItem::updateVisibility()
{
	//FIXME: A contact can ve visible if he has a unknwon status (it's not online)
	//       or if he has an event (blinking icon).  If such as contact is not with
	//       others inline contact in the group. the group will stay hidden.
	int visibleUsers = onlineMemberCount;
	if ( KopetePrefs::prefs()->showOffline() )
		visibleUsers = totalMemberCount;

	bool visible = KopetePrefs::prefs()->showEmptyGroups() || ( visibleUsers > 0 );

	if ( isVisible() != visible )
	{
		setTargetVisibility( visible );
		if ( visible )
		{
			// When calling setVisible(true) EVERY child item will be shown,
			// even if they should be hidden.
			// We just re-update the visibility of all child items
			for ( QListViewItem *lvi = firstChild(); lvi; lvi = lvi->nextSibling() )
			{
				if ( KopeteMetaContactLVI *kmc = dynamic_cast<KopeteMetaContactLVI *>( lvi ) )
					kmc->updateVisibility();
			}
		}
	}
}

void KopeteGroupViewItem::updateIcon()
{
	// TODO: clever caching
	if ( isOpen() )
	{
		if ( group()->useCustomIcon() && !group()->icon( KopetePluginDataObject::Open ).isEmpty() )
			open = SmallIcon( group()->icon( KopetePluginDataObject::Open ) );
		else
			open = SmallIcon( KOPETE_GROUP_DEFAULT_OPEN_ICON );

		d->image->setPixmap( open );
	}
	else
	{
		if ( group()->useCustomIcon() && !group()->icon( KopetePluginDataObject::Closed ).isEmpty() )
			closed = SmallIcon( group()->icon( KopetePluginDataObject::Closed ) );
		else
			closed = SmallIcon( KOPETE_GROUP_DEFAULT_CLOSED_ICON );

		d->image->setPixmap( closed );
	}
}

QString KopeteGroupViewItem::text( int column ) const
{
	if ( column == 0 )
		return d->name->text();
	else
		return KListViewItem::text( column );
}

void KopeteGroupViewItem::setText( int column, const QString &text )
{
	if ( column == 0 )
		d->name->setText( text );
	else
		KListViewItem::setText( column, text );
}

#include "kopetegroupviewitem.moc"
// vim: set noet ts=4 sts=4 sw=4:

<commit_msg>Added a FIXME<commit_after>/*
    kopeteonlinestatus.cpp - Kopete Online Status

    Copyright (c) 2002-2004 by Olivier Goffart       <ogoffart@tiscalinet.be>
    Copyright (c) 2003      by Martijn Klingens      <klingens@kde.org>

    Kopete    (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program is free software; you can redistribute it and/or modify  *
    * it under the terms of the GNU General Public License as published by  *
    * the Free Software Foundation; either version 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/

#include <qpainter.h>

#include <klocale.h>
#include <kiconloader.h>
#include <kdebug.h>

#include "kopetecontactlistview.h"
#include "kopetegroupviewitem.h"
#include "kopetegroup.h"
#include "kopeteonlinestatus.h"
#include "kopeteprefs.h"
#include "kopetemetacontactlvi.h"
#include "kopetemetacontact.h"

#include <memory>

using namespace Kopete::UI;

class KopeteGroupViewItem::Private
{
public:
	ListView::ImageComponent *image;
	ListView::TextComponent *name;
	ListView::TextComponent *count;
	std::auto_ptr<ListView::ToolTipSource> toolTipSource;
};

namespace Kopete {
namespace UI {
namespace ListView {

class GroupToolTipSource : public ToolTipSource
{
public:
	GroupToolTipSource( KopeteGroupViewItem *gp )
	 : group( gp )
	{
	}
	QString operator()( ComponentBase *, const QPoint &, QRect & )
	{
		return group->toolTip();
	}
private:
	KopeteGroupViewItem *group;
};

} // END namespace ListView
} // END namespace UI
} // END namespace Kopete

KopeteGroupViewItem::KopeteGroupViewItem( KopeteGroup *group_, QListView *parent, const char *name )
: Kopete::UI::ListView::Item( parent, group_, name )
{
	m_group = group_;
	initLVI();
}

KopeteGroupViewItem::KopeteGroupViewItem( KopeteGroup *group_, QListViewItem *parent, const char *name )
 : Kopete::UI::ListView::Item( parent, group_, name )
{
	m_group = group_;
	initLVI();
}

KopeteGroupViewItem::~KopeteGroupViewItem()
{
	delete d;
}

void KopeteGroupViewItem::initLVI()
{
	d = new Private;

	d->toolTipSource.reset( new ListView::GroupToolTipSource( this ) );

	using namespace ListView;
	Component *hbox = new BoxComponent( this, BoxComponent::Horizontal );
	d->image = new ImageComponent( hbox );
	d->name = new TextComponent( hbox );
	d->count = new TextComponent( hbox );

	d->image->setToolTipSource( d->toolTipSource.get() );
	d->name->setToolTipSource( d->toolTipSource.get() );
	d->count->setToolTipSource( d->toolTipSource.get() );

	connect( m_group, SIGNAL( renamed( KopeteGroup*, const QString& ) ),
		this, SLOT( refreshDisplayName() ) );

	connect( KopetePrefs::prefs(), SIGNAL( contactListAppearanceChanged() ),
		SLOT( slotConfigChanged() ) );

	connect( m_group, SIGNAL( iconAppearanceChanged() ), SLOT( updateIcon() ) );

	refreshDisplayName();
	slotConfigChanged();
}

KopeteGroup* KopeteGroupViewItem::group() const
{
	return m_group;
}

QString KopeteGroupViewItem::toolTip() const
{
	// TODO: add icon, and some more information than that which
	// is already displayed in the list view item
	// FIXME: post-KDE-3.3, make this better i18n-able
	//  currently it can't cause more problems than the contact list itself, at least.
	return "" + d->name->text() + " " + d->count->text();
}

void KopeteGroupViewItem::slotConfigChanged()
{
	updateIcon();
	updateVisibility();

	d->name->setColor( KopetePrefs::prefs()->contactListGroupNameColor() );

	QFont font = listView()->font();
	if ( KopetePrefs::prefs()->contactListUseCustomFonts() )
		font = KopetePrefs::prefs()->contactListCustomNormalFont();
	d->name->setFont( font );

	d->count->setFont( KopetePrefs::prefs()->contactListSmallFont() );
}

void KopeteGroupViewItem::refreshDisplayName()
{
	totalMemberCount = 0;
	onlineMemberCount = 0;

	for ( QListViewItem *lvi = firstChild(); lvi; lvi = lvi->nextSibling() )
	{
		if ( KopeteMetaContactLVI *kc = dynamic_cast<KopeteMetaContactLVI*>( lvi ) )
		{
			totalMemberCount++;
			if ( kc->metaContact()->isOnline() )
				onlineMemberCount++;
		}
	}

	d->name->setText( m_group->displayName() );
	d->count->setText( i18n( "(NUMBER OF ONLINE CONTACTS/NUMBER OF CONTACTS IN GROUP)", "(%1/%2)" )
	                  .arg( QString::number( onlineMemberCount ), QString::number( totalMemberCount ) ) );

	updateVisibility();

	// Sorting in this slot is extremely expensive as it's called dozens of times and
	// the sorting itself is rather slow. Therefore we call delayedSort, which tries
	// to group multiple sort requests into one.
	if ( KopeteContactListView *lv = dynamic_cast<KopeteContactListView *>( listView() ) )
		lv->delayedSort();
	else
		listView()->sort();
}

QString KopeteGroupViewItem::key( int, bool ) const
{
	//Groups are placed after topLevel contact.
	//Exepted Temporary group which is the first group
	if ( group()->type() != KopeteGroup::Normal )
		return "0" + d->name->text();
	return "M" + d->name->text();
}

void KopeteGroupViewItem::startRename( int col )
{
	//kdDebug(14000) << k_funcinfo << endl;
	KListViewItem::startRename( 0 );
}

void KopeteGroupViewItem::okRename( int col )
{
	//kdDebug(14000) << k_funcinfo << endl;
	KListViewItem::okRename(col);
	if ( col == 0 )
		group()->setDisplayName(text(0));
	setRenameEnabled( 0, false );
	refreshDisplayName();
}

void KopeteGroupViewItem::cancelRename( int col )
{
	//kdDebug(14000) << k_funcinfo << endl;
	KListViewItem::cancelRename(col);
	setRenameEnabled( 0, false );
}

void KopeteGroupViewItem::updateVisibility()
{
	//FIXME: A contact can ve visible if he has a unknwon status (it's not online)
	//       or if he has an event (blinking icon).  If such as contact is not with
	//       others inline contact in the group. the group will stay hidden.
	int visibleUsers = onlineMemberCount;
	if ( KopetePrefs::prefs()->showOffline() )
		visibleUsers = totalMemberCount;

	bool visible = KopetePrefs::prefs()->showEmptyGroups() || ( visibleUsers > 0 );

	if ( isVisible() != visible )
	{
		setTargetVisibility( visible );
		if ( visible )
		{
			// When calling setVisible(true) EVERY child item will be shown,
			// even if they should be hidden.
			// We just re-update the visibility of all child items
			for ( QListViewItem *lvi = firstChild(); lvi; lvi = lvi->nextSibling() )
			{
				if ( KopeteMetaContactLVI *kmc = dynamic_cast<KopeteMetaContactLVI *>( lvi ) )
					kmc->updateVisibility();
			}
		}
	}
}

void KopeteGroupViewItem::updateIcon()
{
	// TODO: clever caching
	if ( isOpen() )
	{
		if ( group()->useCustomIcon() && !group()->icon( KopetePluginDataObject::Open ).isEmpty() )
			open = SmallIcon( group()->icon( KopetePluginDataObject::Open ) );
		else
			open = SmallIcon( KOPETE_GROUP_DEFAULT_OPEN_ICON );

		d->image->setPixmap( open );
	}
	else
	{
		if ( group()->useCustomIcon() && !group()->icon( KopetePluginDataObject::Closed ).isEmpty() )
			closed = SmallIcon( group()->icon( KopetePluginDataObject::Closed ) );
		else
			closed = SmallIcon( KOPETE_GROUP_DEFAULT_CLOSED_ICON );

		d->image->setPixmap( closed );
	}
}

QString KopeteGroupViewItem::text( int column ) const
{
	if ( column == 0 )
		return d->name->text();
	else
		return KListViewItem::text( column );
}

void KopeteGroupViewItem::setText( int column, const QString &text )
{
	if ( column == 0 )
		d->name->setText( text );
	else
		KListViewItem::setText( column, text );
}

#include "kopetegroupviewitem.moc"
// vim: set noet ts=4 sts=4 sw=4:

<|endoftext|>


<commit_before><commit_msg>Replace for loop by std::advance + rename function parameter<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2011-2018 Branimir Karadzic. All rights reserved.
 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
 */

#include "bgfx_p.h"
#include "nvapi.h"

namespace bgfx
{
	/*
	 * NVAPI
	 *
	 * Reference:
	 * http://docs.nvidia.com/gameworks/content/gameworkslibrary/coresdk/nvapi/index.html
	 * https://github.com/jNizM/AHK_NVIDIA_NvAPI/blob/master/info/NvAPI_IDs.txt
	 */
	struct NvPhysicalGpuHandle;

#define NVAPI_MAX_PHYSICAL_GPUS 64

#if BX_PLATFORM_WINDOWS
#	define NVAPICALL __cdecl
#else
#	define NVAPICALL
#endif // BX_PLATFORM_WINDOWS

	enum NvApiStatus
	{
		NVAPI_OK    =  0,
		NVAPI_ERROR = -1,
	};

	struct NvMemoryInfoV2
	{
		NvMemoryInfoV2()
			: version(sizeof(NvMemoryInfoV2) | (2 << 16) )
		{
		}

		uint32_t version;
		uint32_t dedicatedVideoMemory;
		uint32_t availableDedicatedVideoMemory;
		uint32_t systemVideoMemory;
		uint32_t sharedSystemMemory;
		uint32_t curAvailableDedicatedVideoMemory;
	};

	typedef void*       (NVAPICALL* PFN_NVAPI_QUERYINTERFACE)(uint32_t _functionOffset);
	typedef NvApiStatus (NVAPICALL* PFN_NVAPI_INITIALIZE)();
	typedef NvApiStatus (NVAPICALL* PFN_NVAPI_UNLOAD)();
	typedef NvApiStatus (NVAPICALL* PFN_NVAPI_ENUMPHYSICALGPUS)(NvPhysicalGpuHandle* _handle[NVAPI_MAX_PHYSICAL_GPUS], uint32_t* _gpuCount);
	typedef NvApiStatus (NVAPICALL* PFN_NVAPI_GPUGETMEMORYINFO)(NvPhysicalGpuHandle* _handle, NvMemoryInfoV2* _memoryInfo);
	typedef NvApiStatus (NVAPICALL* PFN_NVAPI_GPUGETFULLNAME)(NvPhysicalGpuHandle* _physicalGpu, char _name[64]);

#define NVAPI_INITIALIZE                        UINT32_C(0x0150e828)
#define NVAPI_UNLOAD                            UINT32_C(0xd22bdd7e)
#define NVAPI_ENUMPHYSICALGPUS                  UINT32_C(0xe5ac921f)
#define NVAPI_GPUGETMEMORYINFO                  UINT32_C(0x07f9b368)
#define NVAPI_GPUGETFULLNAME                    UINT32_C(0xceee8e9f)
#define NVAPI_MULTIDRAWINSTANCEDINDIRECT        UINT32_C(0xd4e26bbf)
#define NVAPI_MULTIDRAWINDEXEDINSTANCEDINDIRECT UINT32_C(0x59e890f9)

	static PFN_NVAPI_QUERYINTERFACE   nvApiQueryInterface;
	static PFN_NVAPI_INITIALIZE       nvApiInitialize;
	static PFN_NVAPI_UNLOAD           nvApiUnload;
	static PFN_NVAPI_ENUMPHYSICALGPUS nvApiEnumPhysicalGPUs;
	static PFN_NVAPI_GPUGETMEMORYINFO nvApiGpuGetMemoryInfo;
	static PFN_NVAPI_GPUGETFULLNAME   nvApiGpuGetFullName;

	NvApi::NvApi()
		: m_nvApiDll(NULL)
		, m_nvGpu(NULL)
	{
	}

	void NvApi::init()
	{
		m_nvGpu = NULL;
		m_nvApiDll = bx::dlopen(
#if BX_ARCH_32BIT
			"nvapi.dll"
#else
			"nvapi64.dll"
#endif // BX_ARCH_32BIT
			);

		if (NULL != m_nvApiDll)
		{
			nvApiQueryInterface = (PFN_NVAPI_QUERYINTERFACE)bx::dlsym(m_nvApiDll, "nvapi_QueryInterface");

			bool initialized = NULL != nvApiQueryInterface;

			if (initialized)
			{
				nvApiInitialize       = (PFN_NVAPI_INITIALIZE       )nvApiQueryInterface(NVAPI_INITIALIZE);
				nvApiUnload           = (PFN_NVAPI_UNLOAD           )nvApiQueryInterface(NVAPI_UNLOAD);
				nvApiEnumPhysicalGPUs = (PFN_NVAPI_ENUMPHYSICALGPUS )nvApiQueryInterface(NVAPI_ENUMPHYSICALGPUS);
				nvApiGpuGetMemoryInfo = (PFN_NVAPI_GPUGETMEMORYINFO )nvApiQueryInterface(NVAPI_GPUGETMEMORYINFO);
				nvApiGpuGetFullName   = (PFN_NVAPI_GPUGETFULLNAME   )nvApiQueryInterface(NVAPI_GPUGETFULLNAME);

				nvApiD3D11MultiDrawInstancedIndirect        = (NvMultiDrawIndirectFn)nvApiQueryInterface(NVAPI_MULTIDRAWINSTANCEDINDIRECT);
				nvApiD3D11MultiDrawIndexedInstancedIndirect = (NvMultiDrawIndirectFn)nvApiQueryInterface(NVAPI_MULTIDRAWINDEXEDINSTANCEDINDIRECT);

				initialized = true
					&& NULL != nvApiInitialize
					&& NULL != nvApiUnload
					&& NULL != nvApiEnumPhysicalGPUs
					&& NULL != nvApiGpuGetMemoryInfo
					&& NULL != nvApiGpuGetFullName
					&& NVAPI_OK == nvApiInitialize()
					;

				if (initialized)
				{
					NvPhysicalGpuHandle* physicalGpus[NVAPI_MAX_PHYSICAL_GPUS];
					uint32_t numGpus = 0;
					nvApiEnumPhysicalGPUs(physicalGpus, &numGpus);

					initialized = 0 < numGpus;
					if (initialized)
					{
						m_nvGpu = physicalGpus[0];
					}

					char name[64];
					nvApiGpuGetFullName(m_nvGpu, name);
					BX_TRACE("%s", name);
				}

				initialized = NULL != m_nvGpu;

				if (!initialized)
				{
					nvApiUnload();
				}
			}

			if (!initialized)
			{
				bx::dlclose(m_nvApiDll);
				m_nvApiDll = NULL;
			}

			BX_WARN(!initialized, "NVAPI supported.");
		}
	}

	void NvApi::shutdown()
	{
		if (NULL != m_nvGpu)
		{
			nvApiUnload();
			m_nvGpu = NULL;
		}

		if (NULL != m_nvApiDll)
		{
			bx::dlclose(m_nvApiDll);
			m_nvApiDll = NULL;
		}
	}

	void NvApi::getMemoryInfo(int64_t& _gpuMemoryUsed, int64_t& _gpuMemoryMax)
	{
		if (NULL != m_nvGpu)
		{
			NvMemoryInfoV2 memInfo;
			NvApiStatus status = nvApiGpuGetMemoryInfo(m_nvGpu, &memInfo);
			if (NVAPI_OK == status)
			{
				_gpuMemoryMax  = 1024 *  memInfo.availableDedicatedVideoMemory;
				_gpuMemoryUsed = 1024 * (memInfo.availableDedicatedVideoMemory - memInfo.curAvailableDedicatedVideoMemory);
//				BX_TRACE("            dedicatedVideoMemory: %d KiB", memInfo.dedicatedVideoMemory);
//				BX_TRACE("   availableDedicatedVideoMemory: %d KiB", memInfo.availableDedicatedVideoMemory);
//				BX_TRACE("               systemVideoMemory: %d KiB", memInfo.systemVideoMemory);
//				BX_TRACE("              sharedSystemMemory: %d KiB", memInfo.sharedSystemMemory);
//				BX_TRACE("curAvailableDedicatedVideoMemory: %d KiB", memInfo.curAvailableDedicatedVideoMemory);
			}
		}
		else
		{
			_gpuMemoryMax  = -INT64_MAX;
			_gpuMemoryUsed = -INT64_MAX;
		}
	}

} // namespace bgfx
<commit_msg>NVAPI:  Don't truncate available memory to 4GiB (#1358)<commit_after>/*
 * Copyright 2011-2018 Branimir Karadzic. All rights reserved.
 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
 */

#include "bgfx_p.h"
#include "nvapi.h"

namespace bgfx
{
	/*
	 * NVAPI
	 *
	 * Reference:
	 * http://docs.nvidia.com/gameworks/content/gameworkslibrary/coresdk/nvapi/index.html
	 * https://github.com/jNizM/AHK_NVIDIA_NvAPI/blob/master/info/NvAPI_IDs.txt
	 */
	struct NvPhysicalGpuHandle;

#define NVAPI_MAX_PHYSICAL_GPUS 64

#if BX_PLATFORM_WINDOWS
#	define NVAPICALL __cdecl
#else
#	define NVAPICALL
#endif // BX_PLATFORM_WINDOWS

	enum NvApiStatus
	{
		NVAPI_OK    =  0,
		NVAPI_ERROR = -1,
	};

	struct NvMemoryInfoV2
	{
		NvMemoryInfoV2()
			: version(sizeof(NvMemoryInfoV2) | (2 << 16) )
		{
		}

		uint32_t version;
		uint32_t dedicatedVideoMemory;
		uint32_t availableDedicatedVideoMemory;
		uint32_t systemVideoMemory;
		uint32_t sharedSystemMemory;
		uint32_t curAvailableDedicatedVideoMemory;
	};

	typedef void*       (NVAPICALL* PFN_NVAPI_QUERYINTERFACE)(uint32_t _functionOffset);
	typedef NvApiStatus (NVAPICALL* PFN_NVAPI_INITIALIZE)();
	typedef NvApiStatus (NVAPICALL* PFN_NVAPI_UNLOAD)();
	typedef NvApiStatus (NVAPICALL* PFN_NVAPI_ENUMPHYSICALGPUS)(NvPhysicalGpuHandle* _handle[NVAPI_MAX_PHYSICAL_GPUS], uint32_t* _gpuCount);
	typedef NvApiStatus (NVAPICALL* PFN_NVAPI_GPUGETMEMORYINFO)(NvPhysicalGpuHandle* _handle, NvMemoryInfoV2* _memoryInfo);
	typedef NvApiStatus (NVAPICALL* PFN_NVAPI_GPUGETFULLNAME)(NvPhysicalGpuHandle* _physicalGpu, char _name[64]);

#define NVAPI_INITIALIZE                        UINT32_C(0x0150e828)
#define NVAPI_UNLOAD                            UINT32_C(0xd22bdd7e)
#define NVAPI_ENUMPHYSICALGPUS                  UINT32_C(0xe5ac921f)
#define NVAPI_GPUGETMEMORYINFO                  UINT32_C(0x07f9b368)
#define NVAPI_GPUGETFULLNAME                    UINT32_C(0xceee8e9f)
#define NVAPI_MULTIDRAWINSTANCEDINDIRECT        UINT32_C(0xd4e26bbf)
#define NVAPI_MULTIDRAWINDEXEDINSTANCEDINDIRECT UINT32_C(0x59e890f9)

	static PFN_NVAPI_QUERYINTERFACE   nvApiQueryInterface;
	static PFN_NVAPI_INITIALIZE       nvApiInitialize;
	static PFN_NVAPI_UNLOAD           nvApiUnload;
	static PFN_NVAPI_ENUMPHYSICALGPUS nvApiEnumPhysicalGPUs;
	static PFN_NVAPI_GPUGETMEMORYINFO nvApiGpuGetMemoryInfo;
	static PFN_NVAPI_GPUGETFULLNAME   nvApiGpuGetFullName;

	NvApi::NvApi()
		: m_nvApiDll(NULL)
		, m_nvGpu(NULL)
	{
	}

	void NvApi::init()
	{
		m_nvGpu = NULL;
		m_nvApiDll = bx::dlopen(
#if BX_ARCH_32BIT
			"nvapi.dll"
#else
			"nvapi64.dll"
#endif // BX_ARCH_32BIT
			);

		if (NULL != m_nvApiDll)
		{
			nvApiQueryInterface = (PFN_NVAPI_QUERYINTERFACE)bx::dlsym(m_nvApiDll, "nvapi_QueryInterface");

			bool initialized = NULL != nvApiQueryInterface;

			if (initialized)
			{
				nvApiInitialize       = (PFN_NVAPI_INITIALIZE       )nvApiQueryInterface(NVAPI_INITIALIZE);
				nvApiUnload           = (PFN_NVAPI_UNLOAD           )nvApiQueryInterface(NVAPI_UNLOAD);
				nvApiEnumPhysicalGPUs = (PFN_NVAPI_ENUMPHYSICALGPUS )nvApiQueryInterface(NVAPI_ENUMPHYSICALGPUS);
				nvApiGpuGetMemoryInfo = (PFN_NVAPI_GPUGETMEMORYINFO )nvApiQueryInterface(NVAPI_GPUGETMEMORYINFO);
				nvApiGpuGetFullName   = (PFN_NVAPI_GPUGETFULLNAME   )nvApiQueryInterface(NVAPI_GPUGETFULLNAME);

				nvApiD3D11MultiDrawInstancedIndirect        = (NvMultiDrawIndirectFn)nvApiQueryInterface(NVAPI_MULTIDRAWINSTANCEDINDIRECT);
				nvApiD3D11MultiDrawIndexedInstancedIndirect = (NvMultiDrawIndirectFn)nvApiQueryInterface(NVAPI_MULTIDRAWINDEXEDINSTANCEDINDIRECT);

				initialized = true
					&& NULL != nvApiInitialize
					&& NULL != nvApiUnload
					&& NULL != nvApiEnumPhysicalGPUs
					&& NULL != nvApiGpuGetMemoryInfo
					&& NULL != nvApiGpuGetFullName
					&& NVAPI_OK == nvApiInitialize()
					;

				if (initialized)
				{
					NvPhysicalGpuHandle* physicalGpus[NVAPI_MAX_PHYSICAL_GPUS];
					uint32_t numGpus = 0;
					nvApiEnumPhysicalGPUs(physicalGpus, &numGpus);

					initialized = 0 < numGpus;
					if (initialized)
					{
						m_nvGpu = physicalGpus[0];
					}

					char name[64];
					nvApiGpuGetFullName(m_nvGpu, name);
					BX_TRACE("%s", name);
				}

				initialized = NULL != m_nvGpu;

				if (!initialized)
				{
					nvApiUnload();
				}
			}

			if (!initialized)
			{
				bx::dlclose(m_nvApiDll);
				m_nvApiDll = NULL;
			}

			BX_WARN(!initialized, "NVAPI supported.");
		}
	}

	void NvApi::shutdown()
	{
		if (NULL != m_nvGpu)
		{
			nvApiUnload();
			m_nvGpu = NULL;
		}

		if (NULL != m_nvApiDll)
		{
			bx::dlclose(m_nvApiDll);
			m_nvApiDll = NULL;
		}
	}

	void NvApi::getMemoryInfo(int64_t& _gpuMemoryUsed, int64_t& _gpuMemoryMax)
	{
		if (NULL != m_nvGpu)
		{
			NvMemoryInfoV2 memInfo;
			NvApiStatus status = nvApiGpuGetMemoryInfo(m_nvGpu, &memInfo);
			if (NVAPI_OK == status)
			{
				_gpuMemoryMax  = 1024 * int64_t(memInfo.availableDedicatedVideoMemory);
				_gpuMemoryUsed = 1024 * int64_t(memInfo.availableDedicatedVideoMemory - memInfo.curAvailableDedicatedVideoMemory);
//				BX_TRACE("            dedicatedVideoMemory: %d KiB", memInfo.dedicatedVideoMemory);
//				BX_TRACE("   availableDedicatedVideoMemory: %d KiB", memInfo.availableDedicatedVideoMemory);
//				BX_TRACE("               systemVideoMemory: %d KiB", memInfo.systemVideoMemory);
//				BX_TRACE("              sharedSystemMemory: %d KiB", memInfo.sharedSystemMemory);
//				BX_TRACE("curAvailableDedicatedVideoMemory: %d KiB", memInfo.curAvailableDedicatedVideoMemory);
			}
		}
		else
		{
			_gpuMemoryMax  = -INT64_MAX;
			_gpuMemoryUsed = -INT64_MAX;
		}
	}

} // namespace bgfx
<|endoftext|>