<commit_before>
/*
 * Copyright (C) 2010, Directed Edge, Inc. | Licensed under the MPL and LGPL
 */

#include "QActiveResource.h"
#include <QDateTime>
#include <QDebug>
#include <ruby.h>

typedef VALUE(*ARGS)(...);
typedef int(*ITERATOR)(...);

/*
 * Modules
 */

static VALUE rb_mQAR;
static VALUE rb_mActiveResource;

/*
 * Classes
 */

static VALUE rb_cActiveResourceBase;
static VALUE rb_cQARParamList;
static VALUE rb_cQARResource;
static VALUE rb_cQARResponse;

/*
 * Exceptions
 */

static VALUE rb_eActiveResourceConnectionError;
static VALUE rb_eActiveResourceTimeoutError;
static VALUE rb_eActiveResourceSSLError;
static VALUE rb_eActiveResourceRedirection;
static VALUE rb_eActiveResourceClientError;
static VALUE rb_eActiveResourceBadRequest;
static VALUE rb_eActiveResourceUnauthorizedAccess;
static VALUE rb_eActiveResourceForbiddenAccess;
static VALUE rb_eActiveResourceResourceNotFound;
static VALUE rb_eActiveResourceMethodNotAllowed;
static VALUE rb_eActiveResourceResourceConflict;
static VALUE rb_eActiveResourceResourceGone;
static VALUE rb_eActiveResourceServerError;

/*
 * Symbols
 */

static const ID _all = rb_intern("all");
static const ID _allocate = rb_intern("allocate");
static const ID _at = rb_intern("at");
static const ID _code = rb_intern("code");
static const ID _body = rb_intern("body");
static const ID _collection_name = rb_intern("collection_name");
static const ID _element_name = rb_intern("element_name");
static const ID _extend = rb_intern("extend");
static const ID _first = rb_intern("first");
static const ID _from = rb_intern("from");
static const ID _headers = rb_intern("headers");
static const ID _new = rb_intern("new");
static const ID _one = rb_intern("one");
static const ID _params = rb_intern("params");
static const ID _raise = rb_intern("raise");
static const ID _site = rb_intern("site");
static const ID _to_s = rb_intern("to_s");
static const ID _last = rb_intern("last");

/*
 * Instance variable symbols
 */

static const ID __attributes = rb_intern("@attributes");
static const ID __code = rb_intern("@code");
static const ID __body = rb_intern("@body");
static const ID __headers = rb_intern("@headers");
static const ID __prefix_options = rb_intern("@prefix_options");
static const ID __response = rb_intern("@response");

/*
 * Class variable symbols
 */

static const ID ___qar_resource = rb_intern("@@qar_resource");

static QString to_s(VALUE value)
{
    VALUE s = rb_funcall(value, _to_s, 0);
    return QString::fromUtf8(StringValuePtr(s));
}

static VALUE to_value(const QString &s)
{
    return rb_str_new2(s.toUtf8());
}

static VALUE to_value(const QVariant &v, VALUE base, bool isChild = false)
{
    switch(v.type())
    {
    case QVariant::Hash:
    {
        QActiveResource::Record record = v;

        VALUE attributes = rb_hash_new();

        if(record.isEmpty())
        {
            return attributes;
        }

        VALUE klass = base;

        if(isChild)
        {
            QString name = record.className();
            klass = rb_define_class_under(base, name.toUtf8(), rb_cActiveResourceBase);
        }

        for(QActiveResource::Record::ConstIterator it = record.begin(); it != record.end(); ++it)
        {
            VALUE key = to_value(it.key());
            VALUE value = to_value(it.value(), base, true);
            rb_hash_aset(attributes, key, value);
        }

        VALUE value = rb_funcall(klass, _allocate, 0);
        rb_ivar_set(value, __attributes, attributes);
        rb_ivar_set(value, __prefix_options, rb_hash_new());
        return value;
    }
    case QVariant::List:
    {
        VALUE value = rb_ary_new();

        foreach(QVariant element, v.toList())
        {
            rb_ary_push(value, to_value(element, base, isChild));
        }

        return value;
    }
    case QVariant::Invalid:
        return Qnil;
    case QVariant::Bool:
        return v.toBool() ? Qtrue : Qfalse;
    case QVariant::Int:
        return rb_int_new(v.toInt());
    case QVariant::Double:
        return rb_float_new(v.toDouble());
    case QVariant::DateTime:
    {
        return rb_funcall(rb_cTime, _at, 1, rb_int_new(v.toDateTime().toTime_t()));
    }
    default:
        return to_value(v.toString());
    }
}

static VALUE to_value(const QHash<QString, QString> &hash)
{
    VALUE values = rb_hash_new();

    for(QHash<QString, QString>::ConstIterator it = hash.begin(); it != hash.end(); ++it)
    {
        rb_hash_aset(values, to_value(it.key()), to_value(it.value()));
    }

    return values;
}

/*
 * Resource
 */

static void resource_mark(QActiveResource::Resource *) {}
static void resource_free(QActiveResource::Resource *resource)
{
    delete resource;
}

static VALUE resource_allocate(VALUE klass)
{
    QActiveResource::Resource *resource = new QActiveResource::Resource;
    return Data_Wrap_Struct(klass, resource_mark, resource_free, resource);
}

/*
 * ParamList
 */

static VALUE param_list_mark(QActiveResource::ParamList *) {}
static VALUE param_list_free(QActiveResource::ParamList *params)
{
    delete params;
}

static VALUE param_list_allocate(VALUE klass)
{
    QActiveResource::ParamList *params = new QActiveResource::ParamList();
    return Data_Wrap_Struct(klass, param_list_mark, param_list_free, params);
}

static int params_hash_iterator(VALUE key, VALUE value, VALUE params)
{
    QActiveResource::ParamList *params_pointer;
    Data_Get_Struct(params, QActiveResource::ParamList, params_pointer);
    params_pointer->append(QActiveResource::Param(to_s(key), to_s(value)));
}

/*
 * Response
 */

static VALUE response_initialize(VALUE self, VALUE code, VALUE headers, VALUE body)
{
    rb_ivar_set(self, __code, code);
    rb_ivar_set(self, __headers, headers);
    rb_ivar_set(self, __body, body);
}

static VALUE response_index_operator(VALUE self, VALUE index)
{
    return rb_hash_aref(rb_ivar_get(self, __headers), index);
}

/*
 * QAR
 */

static QActiveResource::Resource *get_resource(VALUE self)
{
    VALUE member = rb_cvar_get(self, ___qar_resource);
    QActiveResource::Resource *resource = 0;
    Data_Get_Struct(member, QActiveResource::Resource, resource);
    return resource;
}

static VALUE qar_find(int argc, VALUE *argv, VALUE self)
{
    QActiveResource::Resource *resource = get_resource(self);
    resource->setBase(to_s(rb_funcall(self, _site, 0)));

    QString from;
    VALUE params = param_list_allocate(rb_cData);

    if(argc >= 2 && TYPE(argv[1]) == T_HASH)
    {
        VALUE params_hash = rb_hash_aref(argv[1], ID2SYM(_params));

        if(params_hash != Qnil && TYPE(params_hash) == T_HASH)
        {
            rb_hash_foreach(params_hash, (ITERATOR) params_hash_iterator, params);
        }

        from = to_s(rb_hash_aref(argv[1], ID2SYM(_from)));
    }

    QActiveResource::ParamList *params_pointer;
    Data_Get_Struct(params, QActiveResource::ParamList, params_pointer);
    resource->setResource(to_s(rb_funcall(self, _collection_name, 0)));

    try
    {
        if(argc >= 1)
        {
            ID current = SYM2ID(argv[0]);

            if(current == _one)
            {
                resource->setResource(to_s(rb_funcall(self, _element_name, 0)));
                QVariant v = resource->find(QActiveResource::FindOne, from, *params_pointer);
                return to_value(v, self);
            }
            else if(current == _first)
            {
                QVariant v = resource->find(QActiveResource::FindFirst, from, *params_pointer);
                return to_value(v, self);
            }
            else if(current == _last)
            {
                QVariant v = resource->find(QActiveResource::FindLast, from, *params_pointer);
                return to_value(v, self);
            }
            else if(current != _all)
            {
                return to_value(resource->find(to_s(argv[0])), self);
            }
        }

        QActiveResource::RecordList records =
            resource->find(QActiveResource::FindAll, from, *params_pointer);
        VALUE array = rb_ary_new2(records.length());

        for(int i = 0; i < records.length(); i++)
        {
            rb_ary_store(array, i, to_value(records[i], self));
        }

        return array;
    }
    catch(QActiveResource::Exception ex)
    {
        VALUE code = rb_int_new(ex.response().code());
        VALUE response = rb_funcall(rb_cQARResponse, _new, 3,
                                    code,
                                    to_value(ex.response().headers()),
                                    rb_str_new2(ex.response().data()));

        #define AR_TEST_EXCEPTION(name)                                 \
            if(ex.type() == QActiveResource::Exception::name)           \
            {                                                           \
                VALUE e = rb_funcall(                                   \
                    rb_eActiveResource##name, _allocate, 0);            \
                rb_ivar_set(e, __code, code);                           \
                rb_ivar_set(e, __response, response);                   \
                rb_exc_raise(e);                                        \
            }

        AR_TEST_EXCEPTION(ConnectionError);
        AR_TEST_EXCEPTION(TimeoutError);
        AR_TEST_EXCEPTION(SSLError);
        AR_TEST_EXCEPTION(Redirection);
        AR_TEST_EXCEPTION(ClientError);
        AR_TEST_EXCEPTION(BadRequest);
        AR_TEST_EXCEPTION(UnauthorizedAccess);
        AR_TEST_EXCEPTION(ForbiddenAccess);
        AR_TEST_EXCEPTION(ResourceNotFound);
        AR_TEST_EXCEPTION(MethodNotAllowed);
        AR_TEST_EXCEPTION(ResourceConflict);
        AR_TEST_EXCEPTION(ResourceGone);
        AR_TEST_EXCEPTION(ServerError);

        return Qnil;
    }
}

static VALUE set_follow_redirects(VALUE self, VALUE follow)
{
    QActiveResource::Resource *resource = get_resource(self);
    resource->setFollowRedirects(follow == Qtrue);
    return follow;
}

static VALUE qar_extended(VALUE self, VALUE base)
{
    VALUE resource = rb_funcall(rb_cQARResource, _new, 0);
    rb_cvar_set(base, ___qar_resource, resource, false);
    return Qnil;
}

extern "C"
{
    void Init_QAR(void)
    {
        #define DEFINE_CLASS(module, name) \
            rb_c##module##name = rb_define_class_under(rb_m##module, #name, rb_cObject)

        rb_mActiveResource = rb_define_module("ActiveResource");

        DEFINE_CLASS(ActiveResource, Base);

        #define AR_DEFINE_EXCEPTION(name, base) \
            rb_eActiveResource##name = rb_define_class_under(rb_mActiveResource, #name, rb_e##base)

        AR_DEFINE_EXCEPTION(ConnectionError, StandardError);
        AR_DEFINE_EXCEPTION(TimeoutError, ActiveResourceConnectionError);
        AR_DEFINE_EXCEPTION(SSLError, ActiveResourceConnectionError);
        AR_DEFINE_EXCEPTION(Redirection, ActiveResourceConnectionError);
        AR_DEFINE_EXCEPTION(ClientError, ActiveResourceConnectionError);
        AR_DEFINE_EXCEPTION(BadRequest, ActiveResourceClientError);
        AR_DEFINE_EXCEPTION(UnauthorizedAccess, ActiveResourceClientError);
        AR_DEFINE_EXCEPTION(ForbiddenAccess, ActiveResourceClientError);
        AR_DEFINE_EXCEPTION(ResourceNotFound, ActiveResourceClientError);
        AR_DEFINE_EXCEPTION(MethodNotAllowed, ActiveResourceClientError);
        AR_DEFINE_EXCEPTION(ResourceConflict, ActiveResourceClientError);
        AR_DEFINE_EXCEPTION(ResourceGone, ActiveResourceClientError);
        AR_DEFINE_EXCEPTION(ServerError, ActiveResourceConnectionError);

        rb_mQAR = rb_define_module("QAR");

        DEFINE_CLASS(QAR, Response);
        rb_define_method(rb_cQARResponse, "initialize", (ARGS) response_initialize, 3);
        rb_define_method(rb_cQARResponse, "[]", (ARGS) response_index_operator, 1);
        rb_attr(rb_cQARResponse, _code, 1, 0, Qfalse);
        rb_attr(rb_cQARResponse, _headers, 1, 0, Qfalse);
        rb_attr(rb_cQARResponse, _body, 1, 0, Qfalse);

        DEFINE_CLASS(QAR, ParamList);
        rb_define_alloc_func(rb_cQARResponse, resource_allocate);

        rb_define_alloc_func(rb_cQARParamList, param_list_allocate);

        rb_cQARResource = rb_define_class_under(rb_mQAR, "Resource", rb_cObject);
        rb_define_alloc_func(rb_cQARResource, resource_allocate);

        rb_define_method(rb_mQAR, "find", (ARGS) qar_find, -1);
        rb_define_method(rb_mQAR, "follow_redirects=", (ARGS) set_follow_redirects, 1);
        rb_define_singleton_method(rb_mQAR, "extended", (ARGS) qar_extended, 1);
    }
}
<commit_msg>Include the error message in the exception object.<commit_after>
/*
 * Copyright (C) 2010, Directed Edge, Inc. | Licensed under the MPL and LGPL
 */

#include "QActiveResource.h"
#include <QDateTime>
#include <QDebug>
#include <ruby.h>

typedef VALUE(*ARGS)(...);
typedef int(*ITERATOR)(...);

/*
 * Modules
 */

static VALUE rb_mQAR;
static VALUE rb_mActiveResource;

/*
 * Classes
 */

static VALUE rb_cActiveResourceBase;
static VALUE rb_cQARParamList;
static VALUE rb_cQARResource;
static VALUE rb_cQARResponse;

/*
 * Exceptions
 */

static VALUE rb_eActiveResourceConnectionError;
static VALUE rb_eActiveResourceTimeoutError;
static VALUE rb_eActiveResourceSSLError;
static VALUE rb_eActiveResourceRedirection;
static VALUE rb_eActiveResourceClientError;
static VALUE rb_eActiveResourceBadRequest;
static VALUE rb_eActiveResourceUnauthorizedAccess;
static VALUE rb_eActiveResourceForbiddenAccess;
static VALUE rb_eActiveResourceResourceNotFound;
static VALUE rb_eActiveResourceMethodNotAllowed;
static VALUE rb_eActiveResourceResourceConflict;
static VALUE rb_eActiveResourceResourceGone;
static VALUE rb_eActiveResourceServerError;

/*
 * Symbols
 */

static const ID _all = rb_intern("all");
static const ID _allocate = rb_intern("allocate");
static const ID _at = rb_intern("at");
static const ID _code = rb_intern("code");
static const ID _body = rb_intern("body");
static const ID _collection_name = rb_intern("collection_name");
static const ID _element_name = rb_intern("element_name");
static const ID _extend = rb_intern("extend");
static const ID _first = rb_intern("first");
static const ID _from = rb_intern("from");
static const ID _headers = rb_intern("headers");
static const ID _new = rb_intern("new");
static const ID _one = rb_intern("one");
static const ID _params = rb_intern("params");
static const ID _raise = rb_intern("raise");
static const ID _site = rb_intern("site");
static const ID _to_s = rb_intern("to_s");
static const ID _last = rb_intern("last");

/*
 * Instance variable symbols
 */

static const ID __attributes = rb_intern("@attributes");
static const ID __code = rb_intern("@code");
static const ID __body = rb_intern("@body");
static const ID __headers = rb_intern("@headers");
static const ID __prefix_options = rb_intern("@prefix_options");
static const ID __response = rb_intern("@response");
static const ID __message = rb_intern("@message");

/*
 * Class variable symbols
 */

static const ID ___qar_resource = rb_intern("@@qar_resource");

static QString to_s(VALUE value)
{
    VALUE s = rb_funcall(value, _to_s, 0);
    return QString::fromUtf8(StringValuePtr(s));
}

static VALUE to_value(const QString &s)
{
    return rb_str_new2(s.toUtf8());
}

static VALUE to_value(const QVariant &v, VALUE base, bool isChild = false)
{
    switch(v.type())
    {
    case QVariant::Hash:
    {
        QActiveResource::Record record = v;

        VALUE attributes = rb_hash_new();

        if(record.isEmpty())
        {
            return attributes;
        }

        VALUE klass = base;

        if(isChild)
        {
            QString name = record.className();
            klass = rb_define_class_under(base, name.toUtf8(), rb_cActiveResourceBase);
        }

        for(QActiveResource::Record::ConstIterator it = record.begin(); it != record.end(); ++it)
        {
            VALUE key = to_value(it.key());
            VALUE value = to_value(it.value(), base, true);
            rb_hash_aset(attributes, key, value);
        }

        VALUE value = rb_funcall(klass, _allocate, 0);
        rb_ivar_set(value, __attributes, attributes);
        rb_ivar_set(value, __prefix_options, rb_hash_new());
        return value;
    }
    case QVariant::List:
    {
        VALUE value = rb_ary_new();

        foreach(QVariant element, v.toList())
        {
            rb_ary_push(value, to_value(element, base, isChild));
        }

        return value;
    }
    case QVariant::Invalid:
        return Qnil;
    case QVariant::Bool:
        return v.toBool() ? Qtrue : Qfalse;
    case QVariant::Int:
        return rb_int_new(v.toInt());
    case QVariant::Double:
        return rb_float_new(v.toDouble());
    case QVariant::DateTime:
    {
        return rb_funcall(rb_cTime, _at, 1, rb_int_new(v.toDateTime().toTime_t()));
    }
    default:
        return to_value(v.toString());
    }
}

static VALUE to_value(const QHash<QString, QString> &hash)
{
    VALUE values = rb_hash_new();

    for(QHash<QString, QString>::ConstIterator it = hash.begin(); it != hash.end(); ++it)
    {
        rb_hash_aset(values, to_value(it.key()), to_value(it.value()));
    }

    return values;
}

/*
 * Resource
 */

static void resource_mark(QActiveResource::Resource *) {}
static void resource_free(QActiveResource::Resource *resource)
{
    delete resource;
}

static VALUE resource_allocate(VALUE klass)
{
    QActiveResource::Resource *resource = new QActiveResource::Resource;
    return Data_Wrap_Struct(klass, resource_mark, resource_free, resource);
}

/*
 * ParamList
 */

static VALUE param_list_mark(QActiveResource::ParamList *) {}
static VALUE param_list_free(QActiveResource::ParamList *params)
{
    delete params;
}

static VALUE param_list_allocate(VALUE klass)
{
    QActiveResource::ParamList *params = new QActiveResource::ParamList();
    return Data_Wrap_Struct(klass, param_list_mark, param_list_free, params);
}

static int params_hash_iterator(VALUE key, VALUE value, VALUE params)
{
    QActiveResource::ParamList *params_pointer;
    Data_Get_Struct(params, QActiveResource::ParamList, params_pointer);
    params_pointer->append(QActiveResource::Param(to_s(key), to_s(value)));
}

/*
 * Response
 */

static VALUE response_initialize(VALUE self, VALUE code, VALUE headers, VALUE body)
{
    rb_ivar_set(self, __code, code);
    rb_ivar_set(self, __headers, headers);
    rb_ivar_set(self, __body, body);
}

static VALUE response_index_operator(VALUE self, VALUE index)
{
    return rb_hash_aref(rb_ivar_get(self, __headers), index);
}

/*
 * Exception
 */

static VALUE exception_message(VALUE self)
{
    return rb_ivar_get(self, __message);
}

/*
 * QAR
 */

static QActiveResource::Resource *get_resource(VALUE self)
{
    VALUE member = rb_cvar_get(self, ___qar_resource);
    QActiveResource::Resource *resource = 0;
    Data_Get_Struct(member, QActiveResource::Resource, resource);
    return resource;
}

static VALUE qar_find(int argc, VALUE *argv, VALUE self)
{
    QActiveResource::Resource *resource = get_resource(self);
    resource->setBase(to_s(rb_funcall(self, _site, 0)));

    QString from;
    VALUE params = param_list_allocate(rb_cData);

    if(argc >= 2 && TYPE(argv[1]) == T_HASH)
    {
        VALUE params_hash = rb_hash_aref(argv[1], ID2SYM(_params));

        if(params_hash != Qnil && TYPE(params_hash) == T_HASH)
        {
            rb_hash_foreach(params_hash, (ITERATOR) params_hash_iterator, params);
        }

        from = to_s(rb_hash_aref(argv[1], ID2SYM(_from)));
    }

    QActiveResource::ParamList *params_pointer;
    Data_Get_Struct(params, QActiveResource::ParamList, params_pointer);
    resource->setResource(to_s(rb_funcall(self, _collection_name, 0)));

    try
    {
        if(argc >= 1)
        {
            ID current = SYM2ID(argv[0]);

            if(current == _one)
            {
                resource->setResource(to_s(rb_funcall(self, _element_name, 0)));
                QVariant v = resource->find(QActiveResource::FindOne, from, *params_pointer);
                return to_value(v, self);
            }
            else if(current == _first)
            {
                QVariant v = resource->find(QActiveResource::FindFirst, from, *params_pointer);
                return to_value(v, self);
            }
            else if(current == _last)
            {
                QVariant v = resource->find(QActiveResource::FindLast, from, *params_pointer);
                return to_value(v, self);
            }
            else if(current != _all)
            {
                return to_value(resource->find(to_s(argv[0])), self);
            }
        }

        QActiveResource::RecordList records =
            resource->find(QActiveResource::FindAll, from, *params_pointer);
        VALUE array = rb_ary_new2(records.length());

        for(int i = 0; i < records.length(); i++)
        {
            rb_ary_store(array, i, to_value(records[i], self));
        }

        return array;
    }
    catch(QActiveResource::Exception ex)
    {
        VALUE code = rb_int_new(ex.response().code());
        VALUE response = rb_funcall(rb_cQARResponse, _new, 3,
                                    code,
                                    to_value(ex.response().headers()),
                                    rb_str_new2(ex.response().data()));

        #define AR_TEST_EXCEPTION(name)                                 \
            if(ex.type() == QActiveResource::Exception::name)           \
            {                                                           \
                VALUE e = rb_funcall(                                   \
                    rb_eActiveResource##name, _allocate, 0);            \
                rb_ivar_set(e, __code, code);                           \
                rb_ivar_set(e, __response, response);                   \
                rb_ivar_set(e, __message, to_value(ex.message()));      \
                rb_exc_raise(e);                                        \
            }

        AR_TEST_EXCEPTION(ConnectionError);
        AR_TEST_EXCEPTION(TimeoutError);
        AR_TEST_EXCEPTION(SSLError);
        AR_TEST_EXCEPTION(Redirection);
        AR_TEST_EXCEPTION(ClientError);
        AR_TEST_EXCEPTION(BadRequest);
        AR_TEST_EXCEPTION(UnauthorizedAccess);
        AR_TEST_EXCEPTION(ForbiddenAccess);
        AR_TEST_EXCEPTION(ResourceNotFound);
        AR_TEST_EXCEPTION(MethodNotAllowed);
        AR_TEST_EXCEPTION(ResourceConflict);
        AR_TEST_EXCEPTION(ResourceGone);
        AR_TEST_EXCEPTION(ServerError);

        return Qnil;
    }
}

static VALUE set_follow_redirects(VALUE self, VALUE follow)
{
    QActiveResource::Resource *resource = get_resource(self);
    resource->setFollowRedirects(follow == Qtrue);
    return follow;
}

static VALUE qar_extended(VALUE self, VALUE base)
{
    VALUE resource = rb_funcall(rb_cQARResource, _new, 0);
    rb_cvar_set(base, ___qar_resource, resource, false);
    return Qnil;
}

extern "C"
{
    void Init_QAR(void)
    {
        #define DEFINE_CLASS(module, name) \
            rb_c##module##name = rb_define_class_under(rb_m##module, #name, rb_cObject)

        rb_mActiveResource = rb_define_module("ActiveResource");

        DEFINE_CLASS(ActiveResource, Base);

        #define AR_DEFINE_EXCEPTION(name, base) \
            rb_eActiveResource##name = rb_define_class_under(rb_mActiveResource, #name, rb_e##base); \
            rb_define_method(rb_eActiveResource##name, "message", (ARGS) exception_message, 0)

        AR_DEFINE_EXCEPTION(ConnectionError, StandardError);
        AR_DEFINE_EXCEPTION(TimeoutError, ActiveResourceConnectionError);
        AR_DEFINE_EXCEPTION(SSLError, ActiveResourceConnectionError);
        AR_DEFINE_EXCEPTION(Redirection, ActiveResourceConnectionError);
        AR_DEFINE_EXCEPTION(ClientError, ActiveResourceConnectionError);
        AR_DEFINE_EXCEPTION(BadRequest, ActiveResourceClientError);
        AR_DEFINE_EXCEPTION(UnauthorizedAccess, ActiveResourceClientError);
        AR_DEFINE_EXCEPTION(ForbiddenAccess, ActiveResourceClientError);
        AR_DEFINE_EXCEPTION(ResourceNotFound, ActiveResourceClientError);
        AR_DEFINE_EXCEPTION(MethodNotAllowed, ActiveResourceClientError);
        AR_DEFINE_EXCEPTION(ResourceConflict, ActiveResourceClientError);
        AR_DEFINE_EXCEPTION(ResourceGone, ActiveResourceClientError);
        AR_DEFINE_EXCEPTION(ServerError, ActiveResourceConnectionError);

        rb_mQAR = rb_define_module("QAR");

        DEFINE_CLASS(QAR, Response);
        rb_define_method(rb_cQARResponse, "initialize", (ARGS) response_initialize, 3);
        rb_define_method(rb_cQARResponse, "[]", (ARGS) response_index_operator, 1);
        rb_attr(rb_cQARResponse, _code, 1, 0, Qfalse);
        rb_attr(rb_cQARResponse, _headers, 1, 0, Qfalse);
        rb_attr(rb_cQARResponse, _body, 1, 0, Qfalse);

        DEFINE_CLASS(QAR, ParamList);
        rb_define_alloc_func(rb_cQARResponse, resource_allocate);

        rb_define_alloc_func(rb_cQARParamList, param_list_allocate);

        rb_cQARResource = rb_define_class_under(rb_mQAR, "Resource", rb_cObject);
        rb_define_alloc_func(rb_cQARResource, resource_allocate);

        rb_define_method(rb_mQAR, "find", (ARGS) qar_find, -1);
        rb_define_method(rb_mQAR, "follow_redirects=", (ARGS) set_follow_redirects, 1);
        rb_define_singleton_method(rb_mQAR, "extended", (ARGS) qar_extended, 1);
    }
}
<|endoftext|>


<commit_before>#include "equipment_window.h"
#include "gameengine.h"

namespace {
    const char* nameOrNothing (EntityId item, GameEngineInterface* engine) {
        DescriptionComponent* description = engine->getEntities()->getDescriptions()->get(item);
        if (item == 0) return "Nothing";
        if (description == 0) return "Something";
        return description->title.c_str();
    }
}

void EquipmentWindow::gainFocus () {
    setTitle ("Equipment");
}

void EquipmentWindow::resize() {

    int width  = 45;
    int height = 15;

    setDimensions (0, 0, width, height);

}

void EquipmentWindow::redraw() {
    EntityId player = getEngine()->getEntities()->getPlayer();
    EquipmentComponent* equipment = getEngine()->getEntities()->getEquipments()->get(player);

    drawString (2, 2, "Wielding");
    drawString (3, 4, "r", Color (GREEN));
    drawString (3, 5, "ight:");
    drawString (3, 11, nameOrNothing (equipment->rightHandWieldable, getEngine()));
    drawString (4, 4, "l", Color (GREEN));
    drawString (4, 5, "eft :");
    drawString (4, 11, nameOrNothing (equipment->leftHandWieldable, getEngine()));

    drawString (6, 2, "Wearing");
    drawString (7, 4, "h", Color (GREEN));
    drawString (7, 5, "ead :");
    drawString (7, 11, nameOrNothing (equipment->headWearable, getEngine()));

    drawString (8, 4, "f", Color (GREEN));
    drawString (8, 5, "ace :");
    drawString (8, 11, nameOrNothing (equipment->faceWearable, getEngine()));

    drawString (9, 4, "c", Color (GREEN));
    drawString (9, 5, "hest:");
    drawString (9, 11, nameOrNothing (equipment->faceWearable, getEngine()));

    drawString (10, 4, "a", Color (GREEN));
    drawString (10, 5, "rms :");
    drawString (10, 11, nameOrNothing (equipment->faceWearable, getEngine()));

    drawString (11, 4, "hands:");
    drawString (11, 7, "d", Color (GREEN));
    drawString (11, 11, nameOrNothing (equipment->faceWearable, getEngine()));

    drawString (12, 4, "legs:");
    drawString (12, 5, "e", Color (GREEN));
    drawString (12, 11, nameOrNothing (equipment->faceWearable, getEngine()));

    drawString (13, 4, "teet:");
    drawString (13, 7, "t", Color (GREEN));
    drawString (13, 11, nameOrNothing (equipment->faceWearable, getEngine()));

    drawBorder (0, getWidth()-18, getHeight()-2, 16);

    if (m_selectedItem == 0) {
        drawString (getHeight()/2, getWidth()-14, "Select item");
    } else {
        drawString (2, getWidth()-16, nameOrNothing (m_selectedItem, getEngine()));

        drawString (getHeight()-2, getWidth()-16, "D", Color (GREEN));
        drawString (getHeight()-2, getWidth()-15, "rop");

        drawString (getHeight()-3, getWidth()-16, "U", Color (GREEN));
        drawString (getHeight()-3, getWidth()-15, "nequip");

        drawString (getHeight()-4, getWidth()-16, "I", Color (GREEN));
        drawString (getHeight()-4, getWidth()-15, "nspect");
    }

}

void EquipmentWindow::keyDown (unsigned char key) {
    Window::keyDown (key);
    EntityId player = getEngine()->getEntities()->getPlayer();
    EquipmentComponent* equipment = getEngine()->getEntities()->getEquipments()->get(player);

    if (key == 27) {
        getEngine()->getWindows()->popWindow();
    }

    switch (key) {
        case 'r': m_selectedItem = equipment->rightHandWieldable; break;
        default: m_selectedItem = 0;
    }
}
<commit_msg>Show InspectionWindow for items<commit_after>#include "equipment_window.h"
#include "gameengine.h"
#include "inspection_window.h"

namespace {
    const char* nameOrNothing (EntityId item, GameEngineInterface* engine) {
        DescriptionComponent* description = engine->getEntities()->getDescriptions()->get(item);
        if (item == 0) return "<Nothing>";
        if (description == 0) return "?Something?";
        return description->title.c_str();
    }
}

void EquipmentWindow::gainFocus () {
    setTitle ("Equipment");
}

void EquipmentWindow::resize() {

    int width  = 45;
    int height = 15;

    setDimensions (0, 0, width, height);

}

void EquipmentWindow::redraw() {
    EntityId player = getEngine()->getEntities()->getPlayer();
    EquipmentComponent* equipment = getEngine()->getEntities()->getEquipments()->get(player);

    drawString (2, 2, "Wielding");

    if (m_selectedItem == equipment->rightHandWieldable) drawTile (3, 3, '>', Color (RED), Color (GREY));
    drawString (3, 4, "r", Color (GREEN));
    drawString (3, 5, "ight:");
    drawString (3, 11, nameOrNothing (equipment->rightHandWieldable, getEngine()));

    if (m_selectedItem == equipment->leftHandWieldable) drawTile (4, 3, '>', Color (RED), Color (GREY));
    drawString (4, 4, "l", Color (GREEN));
    drawString (4, 5, "eft :");
    drawString (4, 11, nameOrNothing (equipment->leftHandWieldable, getEngine()));

    drawString (6, 2, "Wearing");

    if (m_selectedItem && m_selectedItem == equipment->headWearable) drawTile (7, 3, '>', Color (RED), Color (GREY));
    drawString (7, 4, "h", Color (GREEN));
    drawString (7, 5, "ead :");
    drawString (7, 11, nameOrNothing (equipment->headWearable, getEngine()));

    if (m_selectedItem && m_selectedItem == equipment->faceWearable) drawTile (8, 3, '>', Color (RED), Color (GREY));
    drawString (8, 4, "f", Color (GREEN));
    drawString (8, 5, "ace :");
    drawString (8, 11, nameOrNothing (equipment->faceWearable, getEngine()));

    if (m_selectedItem && m_selectedItem == equipment->chestWearable) drawTile (9, 3, '>', Color (RED), Color (GREY));
    drawString (9, 4, "c", Color (GREEN));
    drawString (9, 5, "hest:");
    drawString (9, 11, nameOrNothing (equipment->chestWearable, getEngine()));

    if (m_selectedItem && m_selectedItem == equipment->armsWearable) drawTile (10, 3, '>', Color (RED), Color (GREY));
    drawString (10, 4, "a", Color (GREEN));
    drawString (10, 5, "rms :");
    drawString (10, 11, nameOrNothing (equipment->armsWearable, getEngine()));

    if (m_selectedItem && m_selectedItem == equipment->handsWearable) drawTile (11, 3, '>', Color (RED), Color (GREY));
    drawString (11, 4, "hands:");
    drawString (11, 7, "d", Color (GREEN));
    drawString (11, 11, nameOrNothing (equipment->handsWearable, getEngine()));

    if (m_selectedItem && m_selectedItem == equipment->legsWearable) drawTile (12, 3, '>', Color (RED), Color (GREY));
    drawString (12, 4, "legs :");
    drawString (12, 5, "e", Color (GREEN));
    drawString (12, 11, nameOrNothing (equipment->legsWearable, getEngine()));

    if (m_selectedItem && m_selectedItem == equipment->feetWearable) drawTile (13, 3, '>', Color (RED), Color (GREY));
    drawString (13, 4, "feet :");
    drawString (13, 7, "t", Color (GREEN));
    drawString (13, 11, nameOrNothing (equipment->feetWearable, getEngine()));

    drawBorder (0, getWidth()-18, getHeight()-2, 16);

    if (m_selectedItem == 0) {
        drawString (getHeight()/2, getWidth()-14, "Select item");
    } else {
        drawString (2, getWidth()-16, nameOrNothing (m_selectedItem, getEngine()));

        drawString (getHeight()-2, getWidth()-16, "d", Color (GREEN));
        drawString (getHeight()-2, getWidth()-15, "rop item");

        drawString (getHeight()-3, getWidth()-16, "u", Color (GREEN));
        drawString (getHeight()-3, getWidth()-15, "nequip");

        drawString (getHeight()-4, getWidth()-16, "i", Color (GREEN));
        drawString (getHeight()-4, getWidth()-15, "nspect");
    }

}

void EquipmentWindow::keyDown (unsigned char key) {
    Window::keyDown (key);
    EntityId player = getEngine()->getEntities()->getPlayer();
    EquipmentComponent* equipment = getEngine()->getEntities()->getEquipments()->get(player);

    if (key == 27) {
        getEngine()->getWindows()->popWindow();
    }

    switch (key) {
        case 'r': m_selectedItem = equipment->rightHandWieldable; break;
        case 'l': m_selectedItem = equipment->leftHandWieldable; break;
        case 'h': m_selectedItem = equipment->headWearable; break;
        case 'f': m_selectedItem = equipment->faceWearable; break;
        case 'a': m_selectedItem = equipment->armsWearable; break;
        case 'c': m_selectedItem = equipment->chestWearable; break;
        case 'e': m_selectedItem = equipment->legsWearable; break;
        case 't': m_selectedItem = equipment->feetWearable; break;
    }

    if (m_selectedItem && key == 'i') {
        EntityId* l_target = new EntityId(m_selectedItem);

        InspectionWindow* l_win = new InspectionWindow();
        l_win->initialise(getEngine(), l_target);
        getEngine()->getWindows()->pushWindow (l_win);
    }
}
<|endoftext|>


<commit_before>#include <sys/epoll.h>
#include <unistd.h>

#include "exemodel/timeree.hpp"
#include "exemodel/poll_tools.hpp"

namespace exemodel{
timeree::timeree(bool once,struct timercycle value)
: pollee(::timerfd_create(CLOCK_MONOTONIC,TFD_CLOEXEC),uint32_t(::EPOLLIN | ::EPOLLERR))
, m_value(value)
{
	setmodel(mod);
}

timeree::~timeree()
{
}

void timeree::start(void)
{
	//start timer
	struct itimerspec tmpTime = {
		m_interval,
		m_value,
	};
	int ret = timerfd_settime(_fd_(), 0, &tmpTime, NULL);
	validate_ret(ret,"start timer error!\n");
}

void timeree::stop(void)
{
	//stop timer
	struct itimerspec tmpTime = {
		 m_interval,
		 {0,0},
	};
	int ret = timerfd_settime(_fd_(), 0, &tmpTime, NULL);
	validate_ret(ret,"stop timer error!\n");
}

void timeree::setcycle(struct timercycle cycle)
{
	//reset cycle
	if((cycle.nsec!=0)||(cycle.sec!=0))
	{
		m_value.tv_sec=cycle.sec;
		m_value.tv_nsec=cycle.nsec;
	}else
	{
		std::cout << "WARNING:: cycle cann't set zero!" << std::endl;
	}

}

void timeree::setmodel(bool oneshot)
{
	//set model
	if(oneshot)             //ONCE
	{
		m_interval.tv_nsec=0;
		m_interval.tv_sec=0;
	}
	else               //LOOP
	{
		m_interval.tv_nsec=1;
	}
}

void timeree::dispose(poller & mgr, uint32_t evts)
{
	if(evts & EPOLLERR){
	      printf("timer error occurd fd %d\n",_fd_());
	      return;
	}
	//read the timeout information
	uint64_t buf = 0;
	ssize_t ret = ::read(_fd_(), &buf, sizeof(buf));
	if(ret != sizeof(buf)){
		printf("read error!\n");
		return;
		}

	if(evts & EPOLLIN){
		timeree::args_t args = { mgr, *this, evts };
		this->exe(args);

	}
}

}
<commit_msg>timeree.c<commit_after>#include <sys/epoll.h>
#include <unistd.h>

#include "exemodel/timeree.hpp"
#include "exemodel/poll_tools.hpp"

namespace exemodel{
timeree::timeree(bool once,struct timercycle value)
: pollee(::timerfd_create(CLOCK_MONOTONIC,TFD_CLOEXEC),uint32_t(::EPOLLIN | ::EPOLLERR))
, m_value(value)
{
	setmodel(once);
}

timeree::~timeree()
{
}

void timeree::start(void)
{
	//start timer
	struct itimerspec tmpTime = {
		m_interval,
		m_value,
	};
	int ret = timerfd_settime(_fd_(), 0, &tmpTime, NULL);
	validate_ret(ret,"start timer error!\n");
}

void timeree::stop(void)
{
	//stop timer
	struct itimerspec tmpTime = {
		 m_interval,
		 {0,0},
	};
	int ret = timerfd_settime(_fd_(), 0, &tmpTime, NULL);
	validate_ret(ret,"stop timer error!\n");
}

void timeree::setcycle(struct timercycle cycle)
{
	//reset cycle
	if((cycle.nsec!=0)||(cycle.sec!=0))
	{
		m_value.tv_sec=cycle.sec;
		m_value.tv_nsec=cycle.nsec;
	}else
	{
		std::cout << "WARNING:: cycle cann't set zero!" << std::endl;
	}

}

void timeree::setmodel(bool oneshot)
{
	//set model
	if(oneshot)             //ONCE
	{
		m_interval.tv_nsec=0;
		m_interval.tv_sec=0;
	}
	else               //LOOP
	{
		m_interval.tv_nsec=1;
	}
}

void timeree::dispose(poller & mgr, uint32_t evts)
{
	if(evts & EPOLLERR){
	      printf("timer error occurd fd %d\n",_fd_());
	      return;
	}
	//read the timeout information
	uint64_t buf = 0;
	ssize_t ret = ::read(_fd_(), &buf, sizeof(buf));
	if(ret != sizeof(buf)){
		printf("read error!\n");
		return;
		}

	if(evts & EPOLLIN){
		timeree::args_t args = { mgr, *this, evts };
		this->exe(args);

	}
}

}
<|endoftext|>


<commit_before>/**
 * fast_input_master.cc
 */
#include "fast_input_master.h"

namespace qvmmi {

	FastInputMaster::FastInputMaster(std::istream& input)
		: iter_(input),
			map_() {}

	void FastInputMaster::run() {
		/*
		 * Keep track of how many tasks were originally submitted. It oculd happen
		 * that fewer tasks are generated and sent than there are cores, so don't
		 * want to be waiting for tasks to return which were never submitted.
		 */
		int submitted = 1;
		/* Send initial matrices to workers. */
		for(int i = 1; i < num_proc_ && iter_.has_next(); ++i) {
			MatrixPtr matrix = iter_.next();
			send_matrix(*matrix, i);
			map_[i] = matrix;
			submitted++;
		}

		while(iter_.has_next()) {
			int result = receive_result();
			int worker = status_.Get_source();
			handle_result(result, worker);
			MatrixPtr matrix = iter_.next();
			send_matrix(*matrix, worker);
			map_[worker] = matrix;
		}
		/* Wait for remaining tasks. */
		for(int i = 1; i < submitted; ++i) {
			int result = receive_result();
			int worker = status_.Get_source();
			handle_result(result, worker);
		}
		send_shutdown();
	}

	void FastInputMaster::handle_result(int result, int worker) {
		if(result == 1) {
			/* Matrix is mmi. */
			MatrixPtr mat = map_[worker];
			std::cout << *mat << std::endl;
		}
	}
}

<commit_msg>Makes the fast input master show some sort of progress to stderr<commit_after>/**
 * fast_input_master.cc
 */
#include "fast_input_master.h"

namespace qvmmi {

	FastInputMaster::FastInputMaster(std::istream& input)
		: iter_(input),
			map_() {
		iter_.progress(true);
	}

	void FastInputMaster::run() {
		/*
		 * Keep track of how many tasks were originally submitted. It oculd happen
		 * that fewer tasks are generated and sent than there are cores, so don't
		 * want to be waiting for tasks to return which were never submitted.
		 */
		int submitted = 1;
		/* Send initial matrices to workers. */
		for(int i = 1; i < num_proc_ && iter_.has_next(); ++i) {
			MatrixPtr matrix = iter_.next();
			send_matrix(*matrix, i);
			map_[i] = matrix;
			submitted++;
		}

		while(iter_.has_next()) {
			int result = receive_result();
			int worker = status_.Get_source();
			handle_result(result, worker);
			MatrixPtr matrix = iter_.next();
			send_matrix(*matrix, worker);
			map_[worker] = matrix;
		}
		/* Wait for remaining tasks. */
		for(int i = 1; i < submitted; ++i) {
			int result = receive_result();
			int worker = status_.Get_source();
			handle_result(result, worker);
		}
		send_shutdown();
	}

	void FastInputMaster::handle_result(int result, int worker) {
		if(result == 1) {
			/* Matrix is mmi. */
			MatrixPtr mat = map_[worker];
			std::cout << *mat << std::endl;
		}
	}
}

<|endoftext|>


<commit_before>//
// Copyright (c) 2012, University of Erlangen-Nuremberg
// Copyright (c) 2012, Siemens AG
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
//

#ifndef __MASK_HPP__
#define __MASK_HPP__

#include "iterationspace.hpp"
#include "types.hpp"

namespace hipacc {
class MaskBase {
    protected:
        const int size_x, size_y;
        const int offset_x, offset_y;
        uchar *domain_space;
        IterationSpaceBase iteration_space;

    public:
        MaskBase(int size_x, int size_y) :
            size_x(size_x),
            size_y(size_y),
            offset_x(-size_x/2),
            offset_y(-size_y/2),
            domain_space(new uchar[size_x*size_y]),
            iteration_space(size_x, size_y)
        {
            assert(size_x>0 && size_y>0 && "Size for Domain must be positive!");
            // initialize full domain
            for (int i = 0; i < size_x*size_y; ++i) {
              domain_space[i] = 1;
            }
        }

        MaskBase(const MaskBase &mask) :
            size_x(size_x),
            size_y(size_y),
            offset_x(-size_x/2),
            offset_y(-size_y/2),
            domain_space(new uchar[size_x*size_y]),
            iteration_space(size_x, size_y)
        {
            for (int y=0; y<size_y; ++y) {
              for (int x=0; x<size_x; ++x) {
                domain_space[y * size_x + x] = mask.domain_space[y * size_x + x];
              }
            }
        }

        ~MaskBase() {
            if (domain_space != NULL) {
              delete[] domain_space;
              domain_space = NULL;
            }
        }

        int getSizeX() const { return size_x; }
        int getSizeY() const { return size_y; }

        virtual int getX() = 0;
        virtual int getY() = 0;

    friend class Domain;
    template<typename> friend class Mask;
};

class Domain : public MaskBase {
    public:
        class DomainIterator : public ElementIterator {
            private:
                uchar *domain_space;

            public:
                DomainIterator(int width=0, int height=0,
                               int offsetx=0, int offsety=0,
                               const IterationSpaceBase *iterspace=NULL,
                               uchar *domain_space=NULL) :
                    ElementIterator(width, height, offsetx, offsety, iterspace),
                    domain_space(domain_space)
                {
                    if (domain_space != NULL) {
                        // set current coordinate before domain
                        coord.x = min_x-1;
                        coord.y = min_y;

                        // use increment to search first non-zero value
                        ++(*this);
                    }
                }

                ~DomainIterator() {}

                // increment so we iterate over elements in a block
                DomainIterator &operator++() {
                    do {
                        if (iteration_space) {
                            coord.x++;
                            if (coord.x >= max_x) {
                                coord.x = min_x;
                                coord.y++;
                                if (coord.y >= max_y) {
                                    iteration_space = NULL;
                                }
                            }
                        }
                    } while (NULL != iteration_space &&
                             (NULL == domain_space ||
                              0 == domain_space[(coord.y-min_y) * (max_x-min_x)
                                                + (coord.x-min_x)]));
                    return *this;
                }
            };

    protected:
        DomainIterator *DI;

    public:
        Domain(int size_x, int size_y) :
            MaskBase(size_x, size_y),
            DI(NULL) {}

        Domain(const MaskBase &mask) :
            MaskBase(mask),
            DI(NULL) {}

        Domain(const Domain &domain) :
            MaskBase(domain),
            DI(domain.DI) {}

        ~Domain() {}

        int getX() {
            assert(DI && "DomainIterator for Domain not set!");
            return DI->getX();
        }
        int getY() {
            assert(DI && "DomainIterator for Domain not set!");
            return DI->getY();
        }

        uchar &operator()(unsigned int x, unsigned int y) {
            x += size_x >> 1;
            y += size_y >> 1;
            if ((int)x < size_x && (int)y < size_y) {
                return domain_space[y * size_x + x];
            } else {
                return domain_space[0];
            }
        }

        Domain &operator=(const uchar *other) {
            for (int y=0; y<size_y; ++y) {
                for (int x=0; x<size_x; ++x) {
                    domain_space[y * size_x + x] = other[y * size_x + x];
                }
            }

            return *this;
        }

        void operator=(const Domain &dom) {
            assert(size_x==dom.getSizeX() && size_y==dom.getSizeY() &&
                    "Domain sizes must be equal.");
            for (int y=0; y<size_y; ++y) {
                for (int x=0; x<size_x; ++x) {
                    domain_space[y * size_x + x] = dom.domain_space[y * size_x + x];
                }
            }
        }

        void operator=(const MaskBase &mask) {
            assert(size_x==mask.getSizeX() && size_y==mask.getSizeY() &&
                    "Domain and Mask size must be equal.");
            for (int y=0; y<size_y; ++y) {
                for (int x=0; x<size_x; ++x) {
                    domain_space[y * size_x + x] = mask.domain_space[y * size_x + x];
                }
            }
        }

        void setDI(DomainIterator *di) { DI = di; }
        DomainIterator begin() const {
            return DomainIterator(size_x, size_y, offset_x, offset_y,
                                  &iteration_space, domain_space);
        }
        DomainIterator end() const { return DomainIterator(); }
};

template<typename data_t>
class Mask : public MaskBase {
    private:
        ElementIterator *EI;
        data_t *array;

    public:
        Mask(int size_x, int size_y) :
            MaskBase(size_x, size_y),
            EI(NULL),
            array(new data_t[size_x*size_y])
        {
            assert(size_x>0 && size_y>0 && "size for Mask must be positive!");
        }

        Mask(const Mask &mask) :
            MaskBase(mask.size_x, mask.size_y),
            array(new data_t[mask.size_x*mask.size_y])
        {
            operator=(mask.array);
        }

        ~Mask() {
            if (array != NULL) {
              delete[] array;
              array = NULL;
            }
        }

        int getX() {
            assert(EI && "ElementIterator for Mask not set!");
            return EI->getX();
        }
        int getY() {
            assert(EI && "ElementIterator for Mask not set!");
            return EI->getY();
        }

        data_t &operator()(void) {
            assert(EI && "ElementIterator for Mask not set!");
            return array[(EI->getY()-offset_y)*size_x + EI->getX()-offset_x];
        }
        data_t &operator()(const int xf, const int yf) {
            return array[(yf-offset_y)*size_x + xf-offset_x];
        }
        data_t &operator()(Domain &D) {
            assert(D.getSizeX()==size_x && D.getSizeY()==size_y &&
                    "Domain and Mask size must be equal.");
            return array[(D.getY()-offset_y)*size_x + D.getX()-offset_x];
        }

        Mask &operator=(const data_t *other) {
            for (int y=0; y<size_y; ++y) {
                for (int x=0; x<size_x; ++x) {
                    array[y*size_x + x] = other[y*size_x + x];
                    // set holes in underlying domain_space
                    if (other[y*size_x + x] == 0) {
                        domain_space[y*size_x + x] = 0;
                    } else {
                        domain_space[y*size_x + x] = 1;
                    }
                }
            }

            return *this;
        }

        void setEI(ElementIterator *ei) { EI = ei; }
        ElementIterator begin() const {
            return ElementIterator(size_x, size_y, offset_x, offset_y,
                    &iteration_space);
        }
        ElementIterator end() const { return ElementIterator(); }
};

template <typename data_t, typename Function>
auto convolve(Mask<data_t> &mask, HipaccConvolutionMode mode, const Function& fun) -> decltype(fun()) {
    ElementIterator end = mask.end();
    ElementIterator iter = mask.begin();

    // register mask
    mask.setEI(&iter);

    // initialize result - calculate first iteration
    auto result = fun();
    ++iter;

    // advance iterator and apply kernel to remaining iteration space
    while (iter != end) {
        switch (mode) {
            case HipaccSUM:
                result += fun();
                break;
            case HipaccMIN:
                {
                auto tmp = fun();
                result = hipacc::math::min(tmp, result);
                }
                break;
            case HipaccMAX:
                {
                auto tmp = fun();
                result = hipacc::math::max(tmp, result);
                }
                break;
            case HipaccPROD:
                result *= fun();
                break;
            case HipaccMEDIAN:
                assert(0 && "HipaccMEDIAN not implemented yet!");
                break;
        }
        ++iter;
    }

    // de-register mask
    mask.setEI(NULL);

    return result;
}

template <typename Function>
auto reduce(Domain &domain, HipaccConvolutionMode mode,
            const Function &fun) -> decltype(fun()) {
    Domain::DomainIterator end = domain.end();
    Domain::DomainIterator iter = domain.begin();

    // register domain
    domain.setDI(&iter);

    // initialize result - calculate first iteration
    auto result = fun();
    ++iter;

    // advance iterator and apply kernel to remaining iteration space
    while (iter != end) {
        switch (mode) {
            case HipaccSUM:
                result += fun();
                break;
            case HipaccMIN: {
                auto tmp = fun();
                result = hipacc::math::min(tmp, result);
                }
              break;
            case HipaccMAX: {
                auto tmp = fun();
                result = hipacc::math::max(tmp, result);
                }
                break;
            case HipaccPROD:
                result *= fun();
                break;
            case HipaccMEDIAN:
                assert(0 && "HipaccMEDIAN not implemented yet!");
                break;
        }
        ++iter;
    }

    // de-register domain
    domain.setDI(NULL);

    return result;
}

template <typename Function>
void iterate(Domain &domain, const Function &fun) {
    Domain::DomainIterator end = domain.end();
    Domain::DomainIterator iter = domain.begin();

    // register domain
    domain.setDI(&iter);

    // advance iterator and apply kernel to iteration space
    while (iter != end) {
        fun();
        ++iter;
    }

    // de-register domain
    domain.setDI(NULL);
}
} // end namespace hipacc

#endif // __MASK_HPP__

<commit_msg>DSL: Fixed mask member initialization from previous commit<commit_after>//
// Copyright (c) 2012, University of Erlangen-Nuremberg
// Copyright (c) 2012, Siemens AG
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
//

#ifndef __MASK_HPP__
#define __MASK_HPP__

#include "iterationspace.hpp"
#include "types.hpp"

namespace hipacc {
class MaskBase {
    protected:
        const int size_x, size_y;
        const int offset_x, offset_y;
        uchar *domain_space;
        IterationSpaceBase iteration_space;

    public:
        MaskBase(int size_x, int size_y) :
            size_x(size_x),
            size_y(size_y),
            offset_x(-size_x/2),
            offset_y(-size_y/2),
            domain_space(new uchar[size_x*size_y]),
            iteration_space(size_x, size_y)
        {
            assert(size_x>0 && size_y>0 && "Size for Domain must be positive!");
            // initialize full domain
            for (int i = 0; i < size_x*size_y; ++i) {
              domain_space[i] = 1;
            }
        }

        MaskBase(const MaskBase &mask) :
            size_x(mask.size_x),
            size_y(mask.size_y),
            offset_x(-mask.size_x/2),
            offset_y(-mask.size_y/2),
            domain_space(new uchar[mask.size_x*mask.size_y]),
            iteration_space(mask.size_x, mask.size_y)
        {
            for (int y=0; y<size_y; ++y) {
              for (int x=0; x<size_x; ++x) {
                domain_space[y * size_x + x] = mask.domain_space[y * size_x + x];
              }
            }
        }

        ~MaskBase() {
            if (domain_space != NULL) {
              delete[] domain_space;
              domain_space = NULL;
            }
        }

        int getSizeX() const { return size_x; }
        int getSizeY() const { return size_y; }

        virtual int getX() = 0;
        virtual int getY() = 0;

    friend class Domain;
    template<typename> friend class Mask;
};

class Domain : public MaskBase {
    public:
        class DomainIterator : public ElementIterator {
            private:
                uchar *domain_space;

            public:
                DomainIterator(int width=0, int height=0,
                               int offsetx=0, int offsety=0,
                               const IterationSpaceBase *iterspace=NULL,
                               uchar *domain_space=NULL) :
                    ElementIterator(width, height, offsetx, offsety, iterspace),
                    domain_space(domain_space)
                {
                    if (domain_space != NULL) {
                        // set current coordinate before domain
                        coord.x = min_x-1;
                        coord.y = min_y;

                        // use increment to search first non-zero value
                        ++(*this);
                    }
                }

                ~DomainIterator() {}

                // increment so we iterate over elements in a block
                DomainIterator &operator++() {
                    do {
                        if (iteration_space) {
                            coord.x++;
                            if (coord.x >= max_x) {
                                coord.x = min_x;
                                coord.y++;
                                if (coord.y >= max_y) {
                                    iteration_space = NULL;
                                }
                            }
                        }
                    } while (NULL != iteration_space &&
                             (NULL == domain_space ||
                              0 == domain_space[(coord.y-min_y) * (max_x-min_x)
                                                + (coord.x-min_x)]));
                    return *this;
                }
            };

    protected:
        DomainIterator *DI;

    public:
        Domain(int size_x, int size_y) :
            MaskBase(size_x, size_y),
            DI(NULL) {}

        Domain(const MaskBase &mask) :
            MaskBase(mask),
            DI(NULL) {}

        Domain(const Domain &domain) :
            MaskBase(domain),
            DI(domain.DI) {}

        ~Domain() {}

        int getX() {
            assert(DI && "DomainIterator for Domain not set!");
            return DI->getX();
        }
        int getY() {
            assert(DI && "DomainIterator for Domain not set!");
            return DI->getY();
        }

        uchar &operator()(unsigned int x, unsigned int y) {
            x += size_x >> 1;
            y += size_y >> 1;
            if ((int)x < size_x && (int)y < size_y) {
                return domain_space[y * size_x + x];
            } else {
                return domain_space[0];
            }
        }

        Domain &operator=(const uchar *other) {
            for (int y=0; y<size_y; ++y) {
                for (int x=0; x<size_x; ++x) {
                    domain_space[y * size_x + x] = other[y * size_x + x];
                }
            }

            return *this;
        }

        void operator=(const Domain &dom) {
            assert(size_x==dom.getSizeX() && size_y==dom.getSizeY() &&
                    "Domain sizes must be equal.");
            for (int y=0; y<size_y; ++y) {
                for (int x=0; x<size_x; ++x) {
                    domain_space[y * size_x + x] = dom.domain_space[y * size_x + x];
                }
            }
        }

        void operator=(const MaskBase &mask) {
            assert(size_x==mask.getSizeX() && size_y==mask.getSizeY() &&
                    "Domain and Mask size must be equal.");
            for (int y=0; y<size_y; ++y) {
                for (int x=0; x<size_x; ++x) {
                    domain_space[y * size_x + x] = mask.domain_space[y * size_x + x];
                }
            }
        }

        void setDI(DomainIterator *di) { DI = di; }
        DomainIterator begin() const {
            return DomainIterator(size_x, size_y, offset_x, offset_y,
                                  &iteration_space, domain_space);
        }
        DomainIterator end() const { return DomainIterator(); }
};

template<typename data_t>
class Mask : public MaskBase {
    private:
        ElementIterator *EI;
        data_t *array;

    public:
        Mask(int size_x, int size_y) :
            MaskBase(size_x, size_y),
            EI(NULL),
            array(new data_t[size_x*size_y])
        {
            assert(size_x>0 && size_y>0 && "size for Mask must be positive!");
        }

        Mask(const Mask &mask) :
            MaskBase(mask.size_x, mask.size_y),
            array(new data_t[mask.size_x*mask.size_y])
        {
            operator=(mask.array);
        }

        ~Mask() {
            if (array != NULL) {
              delete[] array;
              array = NULL;
            }
        }

        int getX() {
            assert(EI && "ElementIterator for Mask not set!");
            return EI->getX();
        }
        int getY() {
            assert(EI && "ElementIterator for Mask not set!");
            return EI->getY();
        }

        data_t &operator()(void) {
            assert(EI && "ElementIterator for Mask not set!");
            return array[(EI->getY()-offset_y)*size_x + EI->getX()-offset_x];
        }
        data_t &operator()(const int xf, const int yf) {
            return array[(yf-offset_y)*size_x + xf-offset_x];
        }
        data_t &operator()(Domain &D) {
            assert(D.getSizeX()==size_x && D.getSizeY()==size_y &&
                    "Domain and Mask size must be equal.");
            return array[(D.getY()-offset_y)*size_x + D.getX()-offset_x];
        }

        Mask &operator=(const data_t *other) {
            for (int y=0; y<size_y; ++y) {
                for (int x=0; x<size_x; ++x) {
                    array[y*size_x + x] = other[y*size_x + x];
                    // set holes in underlying domain_space
                    if (other[y*size_x + x] == 0) {
                        domain_space[y*size_x + x] = 0;
                    } else {
                        domain_space[y*size_x + x] = 1;
                    }
                }
            }

            return *this;
        }

        void setEI(ElementIterator *ei) { EI = ei; }
        ElementIterator begin() const {
            return ElementIterator(size_x, size_y, offset_x, offset_y,
                    &iteration_space);
        }
        ElementIterator end() const { return ElementIterator(); }
};

template <typename data_t, typename Function>
auto convolve(Mask<data_t> &mask, HipaccConvolutionMode mode, const Function& fun) -> decltype(fun()) {
    ElementIterator end = mask.end();
    ElementIterator iter = mask.begin();

    // register mask
    mask.setEI(&iter);

    // initialize result - calculate first iteration
    auto result = fun();
    ++iter;

    // advance iterator and apply kernel to remaining iteration space
    while (iter != end) {
        switch (mode) {
            case HipaccSUM:
                result += fun();
                break;
            case HipaccMIN:
                {
                auto tmp = fun();
                result = hipacc::math::min(tmp, result);
                }
                break;
            case HipaccMAX:
                {
                auto tmp = fun();
                result = hipacc::math::max(tmp, result);
                }
                break;
            case HipaccPROD:
                result *= fun();
                break;
            case HipaccMEDIAN:
                assert(0 && "HipaccMEDIAN not implemented yet!");
                break;
        }
        ++iter;
    }

    // de-register mask
    mask.setEI(NULL);

    return result;
}

template <typename Function>
auto reduce(Domain &domain, HipaccConvolutionMode mode,
            const Function &fun) -> decltype(fun()) {
    Domain::DomainIterator end = domain.end();
    Domain::DomainIterator iter = domain.begin();

    // register domain
    domain.setDI(&iter);

    // initialize result - calculate first iteration
    auto result = fun();
    ++iter;

    // advance iterator and apply kernel to remaining iteration space
    while (iter != end) {
        switch (mode) {
            case HipaccSUM:
                result += fun();
                break;
            case HipaccMIN: {
                auto tmp = fun();
                result = hipacc::math::min(tmp, result);
                }
              break;
            case HipaccMAX: {
                auto tmp = fun();
                result = hipacc::math::max(tmp, result);
                }
                break;
            case HipaccPROD:
                result *= fun();
                break;
            case HipaccMEDIAN:
                assert(0 && "HipaccMEDIAN not implemented yet!");
                break;
        }
        ++iter;
    }

    // de-register domain
    domain.setDI(NULL);

    return result;
}

template <typename Function>
void iterate(Domain &domain, const Function &fun) {
    Domain::DomainIterator end = domain.end();
    Domain::DomainIterator iter = domain.begin();

    // register domain
    domain.setDI(&iter);

    // advance iterator and apply kernel to iteration space
    while (iter != end) {
        fun();
        ++iter;
    }

    // de-register domain
    domain.setDI(NULL);
}
} // end namespace hipacc

#endif // __MASK_HPP__

<|endoftext|>


<commit_before>// This file is part of the "x0" project, http://xzero.io/
//   (c) 2009-2014 Christian Parpart <trapni@gmail.com>
//
// Licensed under the MIT License (the "License"); you may not use this
// file except in compliance with the License. You may obtain a copy of
// the License at: http://opensource.org/licenses/MIT

#include <xzero/http/HttpChannel.h>
#include <xzero/http/HttpTransport.h>
#include <xzero/http/HttpRequest.h>
#include <xzero/http/HttpResponse.h>
#include <xzero/http/HttpResponseInfo.h>
#include <xzero/http/HttpOutput.h>
#include <xzero/http/HttpOutputCompressor.h>
#include <xzero/http/HttpVersion.h>
#include <xzero/http/HttpInputListener.h>
#include <xzero/http/BadMessage.h>
#include <xzero/logging/LogSource.h>
#include <xzero/io/FileRef.h>
#include <xzero/io/Filter.h>
#include <xzero/RuntimeError.h>
#include <xzero/sysconfig.h>

namespace xzero {

static LogSource connectionLogger("http.HttpChannel");
#define ERROR(msg...) do { connectionLogger.error(msg); } while (0)
#ifndef NDEBUG
#define TRACE(msg...) do { connectionLogger.trace(msg); } while (0)
#else
#define TRACE(msg...) do {} while (0)
#endif

HttpChannel::HttpChannel(HttpTransport* transport, const HttpHandler& handler,
                         std::unique_ptr<HttpInput>&& input,
                         size_t maxRequestUriLength,
                         size_t maxRequestBodyLength,
                         HttpOutputCompressor* outputCompressor)
    : maxRequestUriLength_(maxRequestUriLength),
      maxRequestBodyLength_(maxRequestBodyLength),
      state_(HttpChannelState::IDLE),
      transport_(transport),
      request_(new HttpRequest(std::move(input))),
      response_(new HttpResponse(this, createOutput())),
      outputFilters_(),
      outputCompressor_(outputCompressor),
      handler_(handler) {
  //.
}

HttpChannel::~HttpChannel() {
  //.
}

void HttpChannel::reset() {
  state_ = HttpChannelState::IDLE;
  request_->recycle();
  response_->recycle();
  outputFilters_.clear();
}

std::unique_ptr<HttpOutput> HttpChannel::createOutput() {
  return std::unique_ptr<HttpOutput>(new HttpOutput(this));
}

void HttpChannel::addOutputFilter(std::shared_ptr<Filter> filter) {
  if (response()->isCommitted())
    throw RUNTIME_ERROR("Invalid State. Cannot add output filters after commit.");

  outputFilters_.push_back(filter);
}

void HttpChannel::removeAllOutputFilters() {
  if (response()->isCommitted())
    throw RUNTIME_ERROR("Invalid State. Cannot clear output filters after commit.");

  outputFilters_.clear();
}

void HttpChannel::send(const BufferRef& data, CompletionHandler&& onComplete) {
  onBeforeSend();

  if (outputFilters_.empty()) {
    if (!response_->isCommitted()) {
      HttpResponseInfo info(commitInline());
      transport_->send(std::move(info), data, std::move(onComplete));
    } else {
      transport_->send(data, std::move(onComplete));
    }
  } else {
    Buffer filtered;
    Filter::applyFilters(outputFilters_, data, &filtered, false);

    if (!response_->isCommitted()) {
      HttpResponseInfo info(commitInline());
      transport_->send(std::move(info), std::move(filtered), std::move(onComplete));
    } else {
      transport_->send(std::move(filtered), std::move(onComplete));
    }
  }
}

void HttpChannel::send(Buffer&& data, CompletionHandler&& onComplete) {
  onBeforeSend();

  if (!outputFilters_.empty()) {
    Buffer output;
    Filter::applyFilters(outputFilters_, data.ref(), &output, false);
    data = std::move(output);
  }

  if (!response_->isCommitted()) {
    HttpResponseInfo info(commitInline());
    transport_->send(std::move(info), std::move(data), std::move(onComplete));
  } else {
    transport_->send(std::move(data), std::move(onComplete));
  }
}

void HttpChannel::send(FileRef&& file, CompletionHandler&& onComplete) {
  onBeforeSend();

  if (outputFilters_.empty()) {
    if (!response_->isCommitted()) {
      HttpResponseInfo info(commitInline());
      transport_->send(std::move(info), BufferRef(), nullptr);
    }

    transport_->send(std::move(file), std::move(onComplete));
  } else {
    Buffer filtered;
    Filter::applyFilters(outputFilters_, file, &filtered, false);

    if (!response_->isCommitted()) {
      HttpResponseInfo info(commitInline());
      transport_->send(std::move(info), std::move(filtered), std::move(onComplete));
    } else {
      transport_->send(std::move(filtered), std::move(onComplete));
    }
  }
}

void HttpChannel::onBeforeSend() {
  // install some last-minute output filters before committing

  if (response_->isCommitted())
    return;

  // for (HttpChannelListener* listener: listeners_)
  //   listener->onBeforeCommit(request(), response());

  if (outputCompressor_)
    outputCompressor_->postProcess(request(), response());
}

HttpResponseInfo HttpChannel::commitInline() {
  if (!response_->status())
    throw RUNTIME_ERROR("No HTTP response status set yet.");

  if (request_->expect100Continue())
    response_->send100Continue();

  response_->setCommitted(true);

  const bool isHeadReq = request_->method() == HttpMethod::HEAD;
  HttpResponseInfo info(response_->version(), response_->status(),
                        response_->reason(), isHeadReq,
                        response_->contentLength(),
                        response_->headers(),
                        response_->trailers());

  if (!info.headers().contains("Server"))
    info.headers().push_back("Server", "xzero/" LIBXZERO_VERSION);

  return info;
}

void HttpChannel::commit(CompletionHandler&& onComplete) {
  TRACE("commit()");
  send(BufferRef(), makeCompleter(std::move(onComplete)));
}

void HttpChannel::send100Continue() {
  if (!request()->expect100Continue())
    throw RUNTIME_ERROR("Illegal State. no 100-continue expected.");

  request()->setExpect100Continue(false);

  HttpResponseInfo info(request_->version(), HttpStatus::ContinueRequest,
                        "Continue", false, 0, {}, {});

  TRACE("send100Continue(): sending it");
  transport_->send(std::move(info), BufferRef(), nullptr);
}

bool HttpChannel::onMessageBegin(const BufferRef& method,
                                 const BufferRef& entity,
                                 HttpVersion version) {
  response_->setVersion(version);
  request_->setVersion(version);
  request_->setMethod(method.str());
  if (!request_->setUri(entity.str())) {
    state_ = HttpChannelState::HANDLING;
    response_->sendError(HttpStatus::BadRequest);
    return false;
  }

  TRACE("onMessageBegin(%s, %s, %s)", request_->unparsedMethod().c_str(),
        request_->path().c_str(), to_string(version).c_str());

  return true;
}

bool HttpChannel::onMessageHeader(const BufferRef& name,
                                  const BufferRef& value) {
  request_->headers().push_back(name.str(), value.str());

  if (iequals(name, "Expect") && iequals(value, "100-continue"))
    request_->setExpect100Continue(true);

  // rfc7230, Section 5.4, p2
  if (iequals(name, "Host")) {
    if (request_->host().empty())
      request_->setHost(value.str());
    else
      throw BadMessage(HttpStatus::BadRequest, "Multiple host headers are illegal.");
  }

  return true;
}

bool HttpChannel::onMessageHeaderEnd() {
  if (state_ != HttpChannelState::HANDLING) {
    state_ = HttpChannelState::HANDLING;

    // rfc7230, Section 5.4, p2
    if (request_->version() == HttpVersion::VERSION_1_1) {
      if (!request_->headers().contains("Host")) {
        throw BadMessage(HttpStatus::BadRequest, "No Host header given.");
      }
    }

    handleRequest();
  }
  return true;
}

void HttpChannel::handleRequest() {
  try {
    handler_(request(), response());
  } catch (std::exception& e) {
    // TODO: reportException(e);
    response()->sendError(HttpStatus::InternalServerError, e.what());
  } catch (...) {
    // TODO: reportException(RUNTIME_ERROR("Unhandled unknown exception caught");
    response()->sendError(HttpStatus::InternalServerError,
                          "unhandled unknown exception");
  }
}

bool HttpChannel::onMessageContent(const BufferRef& chunk) {
  request_->input()->onContent(chunk);
  return true;
}

bool HttpChannel::onMessageEnd() {
  if (!request_->input())
    throw RUNTIME_ERROR("Internal Error. No HttpInput available?");

  if (request_->input()->listener())
    request_->input()->listener()->onAllDataRead();

  return false;
}

void HttpChannel::onProtocolError(HttpStatus code, const std::string& message) {
  TRACE("onProtocolError()");
  response_->sendError(code, message);
}

void HttpChannel::completed() {
  if (!response_->isCommitted()) {
    TRACE("completed(): not committed yet. commit empty-body response");
    if (!response_->hasContentLength() && request_->method() != HttpMethod::HEAD) {
      response_->setContentLength(0);
    }
    send(BufferRef(), std::bind(&HttpChannel::completed, this));
    return;
  }

  if (response_->hasContentLength() && response_->output()->size() < response_->contentLength()) {
    transport_->abort();
    return;
  }

  if (!outputFilters_.empty()) {
    Buffer filtered;
    Filter::applyFilters(outputFilters_, "", &filtered, true);
    transport_->send(std::move(filtered),
                     std::bind(&HttpTransport::completed, transport_));
    return;
  }

  transport_->completed();
}

}  // namespace xzero
<commit_msg>first bits of the channel-state fix<commit_after>// This file is part of the "x0" project, http://xzero.io/
//   (c) 2009-2014 Christian Parpart <trapni@gmail.com>
//
// Licensed under the MIT License (the "License"); you may not use this
// file except in compliance with the License. You may obtain a copy of
// the License at: http://opensource.org/licenses/MIT

#include <xzero/http/HttpChannel.h>
#include <xzero/http/HttpTransport.h>
#include <xzero/http/HttpRequest.h>
#include <xzero/http/HttpResponse.h>
#include <xzero/http/HttpResponseInfo.h>
#include <xzero/http/HttpOutput.h>
#include <xzero/http/HttpOutputCompressor.h>
#include <xzero/http/HttpVersion.h>
#include <xzero/http/HttpInputListener.h>
#include <xzero/http/BadMessage.h>
#include <xzero/logging/LogSource.h>
#include <xzero/io/FileRef.h>
#include <xzero/io/Filter.h>
#include <xzero/RuntimeError.h>
#include <xzero/sysconfig.h>

namespace xzero {

static LogSource connectionLogger("http.HttpChannel");
#define ERROR(msg...) do { connectionLogger.error(msg); } while (0)
#ifndef NDEBUG
#define TRACE(msg...) do { connectionLogger.trace(msg); } while (0)
#else
#define TRACE(msg...) do {} while (0)
#endif

std::string to_string(HttpChannelState state) {
  switch (state) {
    case HttpChannelState::READING: return "READING";
    case HttpChannelState::HANDLING: return "HANDLING";
    case HttpChannelState::SENDING: return "SENDING";
    case HttpChannelState::DONE: return "DONE";
    default: {
      char buf[128];
      int n = snprintf(buf, sizeof(buf), "<%d>", static_cast<int>(state));
      return std::string(buf, n);
    }
  }
}

HttpChannel::HttpChannel(HttpTransport* transport, const HttpHandler& handler,
                         std::unique_ptr<HttpInput>&& input,
                         size_t maxRequestUriLength,
                         size_t maxRequestBodyLength,
                         HttpOutputCompressor* outputCompressor)
    : maxRequestUriLength_(maxRequestUriLength),
      maxRequestBodyLength_(maxRequestBodyLength),
      state_(HttpChannelState::READING),
      transport_(transport),
      request_(new HttpRequest(std::move(input))),
      response_(new HttpResponse(this, createOutput())),
      outputFilters_(),
      outputCompressor_(outputCompressor),
      handler_(handler) {
  //.
}

HttpChannel::~HttpChannel() {
  //.
}

void HttpChannel::reset() {
  setState(HttpChannelState::READING);
  request_->recycle();
  response_->recycle();
  outputFilters_.clear();
}

void HttpChannel::setState(HttpChannelState newState) {
  TRACE("%p setState from %s to %s",
        this,
        to_string(state_).c_str(),
        to_string(newState).c_str());

  state_ = newState;
}

CompletionHandler HttpChannel::makeCompleter(CompletionHandler&& next) {
  return [this, next](bool succeeded) {
    BUG_ON(state() != HttpChannelState::SENDING);
    setState(HttpChannelState::HANDLING);

    if (next) {
      next(succeeded);
    }
  };
}

std::unique_ptr<HttpOutput> HttpChannel::createOutput() {
  return std::unique_ptr<HttpOutput>(new HttpOutput(this));
}

void HttpChannel::addOutputFilter(std::shared_ptr<Filter> filter) {
  if (response()->isCommitted())
    throw RUNTIME_ERROR("Invalid State. Cannot add output filters after commit.");

  outputFilters_.push_back(filter);
}

void HttpChannel::removeAllOutputFilters() {
  if (response()->isCommitted())
    throw RUNTIME_ERROR("Invalid State. Cannot clear output filters after commit.");

  outputFilters_.clear();
}

void HttpChannel::send(const BufferRef& data, CompletionHandler&& onComplete) {
  onBeforeSend();

  auto next = makeCompleter(std::move(onComplete));

  if (outputFilters_.empty()) {
    if (!response_->isCommitted()) {
      HttpResponseInfo info(commitInline());
      transport_->send(std::move(info), data, std::move(next));
    } else {
      transport_->send(data, std::move(next));
    }
  } else {
    Buffer filtered;
    Filter::applyFilters(outputFilters_, data, &filtered, false);

    if (!response_->isCommitted()) {
      HttpResponseInfo info(commitInline());
      transport_->send(std::move(info), std::move(filtered), std::move(next));
    } else {
      transport_->send(std::move(filtered), std::move(next));
    }
  }
}

void HttpChannel::send(Buffer&& data, CompletionHandler&& onComplete) {
  onBeforeSend();

  auto next = makeCompleter(std::move(onComplete));

  if (!outputFilters_.empty()) {
    Buffer output;
    Filter::applyFilters(outputFilters_, data.ref(), &output, false);
    data = std::move(output);
  }

  if (!response_->isCommitted()) {
    HttpResponseInfo info(commitInline());
    transport_->send(std::move(info), std::move(data), std::move(next));
  } else {
    transport_->send(std::move(data), std::move(next));
  }
}

void HttpChannel::send(FileRef&& file, CompletionHandler&& onComplete) {
  onBeforeSend();

  auto next = makeCompleter(std::move(onComplete));

  if (outputFilters_.empty()) {
    if (!response_->isCommitted()) {
      HttpResponseInfo info(commitInline());
      transport_->send(std::move(info), BufferRef(), nullptr);
      transport_->send(std::move(file), std::move(next));
      // transport_->send(std::move(info), BufferRef(),
      //     std::bind(&HttpTransport::send, transport_, file, next));
    } else {
      transport_->send(std::move(file), std::move(next));
    }
  } else {
    Buffer filtered;
    Filter::applyFilters(outputFilters_, file, &filtered, false);

    if (!response_->isCommitted()) {
      HttpResponseInfo info(commitInline());
      transport_->send(std::move(info), std::move(filtered), std::move(next));
    } else {
      transport_->send(std::move(filtered), std::move(next));
    }
  }
}

void HttpChannel::onBeforeSend() {
  if (state() != HttpChannelState::HANDLING) {
    throw RUNTIME_ERROR("Invalid HTTP channel state " +
        to_string(state_) + ". Expected " +
        to_string(HttpChannelState::HANDLING) + ".");
  }

  setState(HttpChannelState::SENDING);

  // install some last-minute output filters before committing

  if (response_->isCommitted())
    return;

  // for (HttpChannelListener* listener: listeners_)
  //   listener->onBeforeCommit(request(), response());

  if (outputCompressor_)
    outputCompressor_->postProcess(request(), response());
}

HttpResponseInfo HttpChannel::commitInline() {
  if (!response_->status())
    throw RUNTIME_ERROR("No HTTP response status set yet.");

  if (request_->expect100Continue())
    response_->send100Continue();

  response_->setCommitted(true);

  const bool isHeadReq = request_->method() == HttpMethod::HEAD;
  HttpResponseInfo info(response_->version(), response_->status(),
                        response_->reason(), isHeadReq,
                        response_->contentLength(),
                        response_->headers(),
                        response_->trailers());

  if (!info.headers().contains("Server"))
    info.headers().push_back("Server", "xzero/" LIBXZERO_VERSION);

  return info;
}

void HttpChannel::commit(CompletionHandler&& onComplete) {
  TRACE("commit()");
  send(BufferRef(), makeCompleter(std::move(onComplete)));
}

void HttpChannel::send100Continue() {
  if (!request()->expect100Continue())
    throw RUNTIME_ERROR("Illegal State. no 100-continue expected.");

  request()->setExpect100Continue(false);

  HttpResponseInfo info(request_->version(), HttpStatus::ContinueRequest,
                        "Continue", false, 0, {}, {});

  TRACE("send100Continue(): sending it");
  transport_->send(std::move(info), BufferRef(), nullptr);
}

bool HttpChannel::onMessageBegin(const BufferRef& method,
                                 const BufferRef& entity,
                                 HttpVersion version) {
  response_->setVersion(version);
  request_->setVersion(version);
  request_->setMethod(method.str());
  if (!request_->setUri(entity.str())) {
    setState(HttpChannelState::HANDLING);
    response_->sendError(HttpStatus::BadRequest);
    return false;
  }

  TRACE("onMessageBegin(%s, %s, %s)", request_->unparsedMethod().c_str(),
        request_->path().c_str(), to_string(version).c_str());

  return true;
}

bool HttpChannel::onMessageHeader(const BufferRef& name,
                                  const BufferRef& value) {
  request_->headers().push_back(name.str(), value.str());

  if (iequals(name, "Expect") && iequals(value, "100-continue"))
    request_->setExpect100Continue(true);

  // rfc7230, Section 5.4, p2
  if (iequals(name, "Host")) {
    if (request_->host().empty())
      request_->setHost(value.str());
    else
      throw BadMessage(HttpStatus::BadRequest, "Multiple host headers are illegal.");
  }

  return true;
}

bool HttpChannel::onMessageHeaderEnd() {
  if (state() != HttpChannelState::HANDLING) {
    setState(HttpChannelState::HANDLING);

    // rfc7230, Section 5.4, p2
    if (request_->version() == HttpVersion::VERSION_1_1) {
      if (!request_->headers().contains("Host")) {
        throw BadMessage(HttpStatus::BadRequest, "No Host header given.");
      }
    }

    handleRequest();
  }
  return true;
}

void HttpChannel::handleRequest() {
  try {
    handler_(request(), response());
  } catch (std::exception& e) {
    // TODO: reportException(e);
    response()->sendError(HttpStatus::InternalServerError, e.what());
  } catch (...) {
    // TODO: reportException(RUNTIME_ERROR("Unhandled unknown exception caught");
    response()->sendError(HttpStatus::InternalServerError,
                          "unhandled unknown exception");
  }
}

bool HttpChannel::onMessageContent(const BufferRef& chunk) {
  request_->input()->onContent(chunk);
  return true;
}

bool HttpChannel::onMessageEnd() {
  if (!request_->input())
    throw RUNTIME_ERROR("Internal Error. No HttpInput available?");

  if (request_->input()->listener())
    request_->input()->listener()->onAllDataRead();

  return false;
}

void HttpChannel::onProtocolError(HttpStatus code, const std::string& message) {
  TRACE("onProtocolError()");
  response_->sendError(code, message);
}

void HttpChannel::completed() {
  if (!response_->isCommitted()) {
    TRACE("completed(): not committed yet. commit empty-body response");
    if (!response_->hasContentLength() && request_->method() != HttpMethod::HEAD) {
      response_->setContentLength(0);
    }
    send(BufferRef(), std::bind(&HttpChannel::completed, this));
    return;
  }

  if (state() != HttpChannelState::HANDLING) {
    throw RUNTIME_ERROR("Invalid HTTP channel state " +
        to_string(state_) + ". Expected " +
        to_string(HttpChannelState::HANDLING) + ".");
  }

  setState(HttpChannelState::DONE);

  if (response_->hasContentLength() && response_->output()->size() < response_->contentLength()) {
    transport_->abort();
    return;
  }

  if (!outputFilters_.empty()) {
    Buffer filtered;
    Filter::applyFilters(outputFilters_, "", &filtered, true);
    transport_->send(std::move(filtered),
                     std::bind(&HttpTransport::completed, transport_));
    return;
  }

  transport_->completed();
}

}  // namespace xzero
<|endoftext|>


<commit_before>#include "dynet/rnn.h"

#include "dynet/expr.h"
#include "dynet/param-init.h"

#include <string>
#include <vector>
#include <fstream>
#include <iostream>

using namespace std;
using namespace dynet;

namespace dynet {

enum { X2H=0, H2H, HB, L2H };

RNNBuilder::~RNNBuilder() {}

SimpleRNNBuilder::SimpleRNNBuilder(unsigned layers,
                       unsigned input_dim,
                       unsigned hidden_dim,
                       ParameterCollection& model,
                       bool support_lags) : layers(layers), input_dim_(input_dim),hidden_dim_(hidden_dim),lagging(support_lags) {
  local_model = model.add_subcollection("simple-rnn-builder");
  unsigned layer_input_dim = input_dim;
  for (unsigned i = 0; i < layers; ++i) {
    Parameter p_x2h = local_model.add_parameters({hidden_dim, layer_input_dim});
    Parameter p_h2h = local_model.add_parameters({hidden_dim, hidden_dim});
    Parameter p_hb = local_model.add_parameters({hidden_dim}, ParameterInitConst(0.f));

    vector<Parameter> ps = {p_x2h, p_h2h, p_hb};
    if (lagging)
        ps.push_back(local_model.add_parameters({hidden_dim, hidden_dim}));
    params.push_back(ps);
    layer_input_dim = hidden_dim;
  }
  dropout_rate = 0.f;
}

void SimpleRNNBuilder::new_graph_impl(ComputationGraph& cg, bool update) {
  param_vars.clear();
  for (unsigned i = 0; i < layers; ++i) {
    Parameter p_x2h = params[i][X2H];
    Parameter p_h2h = params[i][H2H];
    Parameter p_hb = params[i][HB];
    Expression i_x2h =  update ? parameter(cg,p_x2h) : const_parameter(cg,p_x2h);
    Expression i_h2h =  update ? parameter(cg,p_h2h) : const_parameter(cg,p_h2h);
    Expression i_hb =  update ? parameter(cg,p_hb) : const_parameter(cg,p_hb);
    vector<Expression> vars = {i_x2h, i_h2h, i_hb};

    if (lagging) {
        Parameter p_l2h = params[i][L2H];
        Expression i_l2h =  update ? parameter(cg,p_l2h) : const_parameter(cg,p_l2h);
        vars.push_back(i_l2h);
    }

    param_vars.push_back(vars);
  }
  _cg = &cg;
}

void SimpleRNNBuilder::start_new_sequence_impl(const vector<Expression>& h_0) {
  h.clear();
  h0 = h_0;
  DYNET_ARG_CHECK(h0.empty() || h0.size() == layers,
                          "Number of inputs passed to initialize RNNBuilder (" << h0.size() << ") is not equal to the number of layers (" << layers << ")");
  dropout_masks_valid = false;
}

Expression SimpleRNNBuilder::set_h_impl(int prev, const vector<Expression>& h_new) {
  DYNET_ARG_CHECK(h_new.empty() || h_new.size() == layers,
                          "Number of inputs passed to RNNBuilder::set_h() (" << h_new.size() << ") is not equal to the number of layers (" << layers << ")");
  const unsigned t = h.size();
  h.push_back(vector<Expression>(layers));
  for (unsigned i = 0; i < layers; ++i) {
    Expression y = h_new[i];
    h[t][i] = y;
  }
  return h[t].back();
}

void SimpleRNNBuilder::set_dropout_masks(unsigned batch_size){
    masks.clear();
    for (unsigned i = 0; i < layers; ++i) {
        std::vector<Expression> masks_i;
        unsigned idim = (i == 0) ? input_dim_ : hidden_dim_;
        if (dropout_rate > 0.f ) {
            float retention_rate = 1.f - dropout_rate;
            float scale = 1.f / retention_rate;

            // input
            masks_i.push_back(random_bernoulli(*_cg, Dim({idim}, batch_size), retention_rate, scale));

            // hidden
            masks_i.push_back(random_bernoulli(*_cg, Dim({hidden_dim_}, batch_size), retention_rate, scale));

            masks.push_back(masks_i);
        }
    }
    dropout_masks_valid = true;
}

Expression SimpleRNNBuilder::add_input_impl(int prev, const Expression &in) {
  if(dropout_rate != 0.f && !dropout_masks_valid)
    set_dropout_masks(in.dim().bd);
  const unsigned t = h.size();
  h.push_back(vector<Expression>(layers));

  Expression x = in;
  Expression h_prev;

  for (unsigned i = 0; i < layers; ++i) {
    const vector<Expression>& vars = param_vars[i];

    if(dropout_rate > 0.f){
      x = cmult(x,masks[i][0]);
    }

    bool exists_h_prev = false;
    // y <--- g(y_prev)
    if(prev >= 0) {
      h_prev = h[prev][i];
      exists_h_prev = true;
    } else if(h0.size() > 0) {
      h_prev = h0[i];
      exists_h_prev = true;
    }

    if(exists_h_prev) {
      if(dropout_rate > 0.f)
        h_prev = cmult(h_prev,masks[i][1]);
      x = h[t][i] = tanh( affine_transform({vars[2], vars[0], x, vars[1], h_prev}) );
    }
    else{
      x = h[t][i] = tanh( affine_transform({vars[2], vars[0], x}) );
    }
  }
  return h[t].back();
}

Expression SimpleRNNBuilder::add_auxiliary_input(const Expression &in, const Expression &aux) {
  const unsigned t = h.size();
  h.push_back(vector<Expression>(layers));

  Expression x = in;

  for (unsigned i = 0; i < layers; ++i) {
    const vector<Expression>& vars = param_vars[i];
    DYNET_ASSERT(vars.size() >= L2H + 1, "Failed dimension check in SimpleRNNBuilder");

    if(t > 0) {
      x = h[t][i] = tanh( affine_transform({vars[HB], vars[X2H], x, vars[L2H], aux, vars[H2H], h[t-1][i]}) );
    } else if(h0.size() > 0) {
      x = h[t][i] = tanh( affine_transform({vars[HB], vars[X2H], x, vars[L2H], aux, vars[H2H], h0[i]}) );
    } else {
      x = h[t][i] = tanh( affine_transform({vars[HB], vars[X2H], x, vars[L2H], aux}) );
    }

  }
  return h[t].back();
}

void SimpleRNNBuilder::copy(const RNNBuilder & rnn) {
  const SimpleRNNBuilder & rnn_simple = (const SimpleRNNBuilder&)rnn;
  DYNET_ARG_CHECK(params.size() == rnn_simple.params.size(),
                          "Attempt to copy between two SimpleRNNBuilders that are not the same size");
  for(size_t i = 0; i < rnn_simple.params.size(); ++i) {
    params[i][0] = rnn_simple.params[i][0];
    params[i][1] = rnn_simple.params[i][1];
    params[i][2] = rnn_simple.params[i][2];
  }
}

ParameterCollection & SimpleRNNBuilder::get_parameter_collection() {
  return local_model;
}

} // namespace dynet
<commit_msg>fix indent<commit_after>#include "dynet/rnn.h"

#include "dynet/expr.h"
#include "dynet/param-init.h"

#include <string>
#include <vector>
#include <fstream>
#include <iostream>

using namespace std;
using namespace dynet;

namespace dynet {

enum { X2H=0, H2H, HB, L2H };

RNNBuilder::~RNNBuilder() {}

SimpleRNNBuilder::SimpleRNNBuilder(unsigned layers,
                       unsigned input_dim,
                       unsigned hidden_dim,
                       ParameterCollection& model,
                       bool support_lags) : layers(layers), input_dim_(input_dim),hidden_dim_(hidden_dim),lagging(support_lags) {
  local_model = model.add_subcollection("simple-rnn-builder");
  unsigned layer_input_dim = input_dim;
  for (unsigned i = 0; i < layers; ++i) {
    Parameter p_x2h = local_model.add_parameters({hidden_dim, layer_input_dim});
    Parameter p_h2h = local_model.add_parameters({hidden_dim, hidden_dim});
    Parameter p_hb = local_model.add_parameters({hidden_dim}, ParameterInitConst(0.f));

    vector<Parameter> ps = {p_x2h, p_h2h, p_hb};
    if (lagging)
        ps.push_back(local_model.add_parameters({hidden_dim, hidden_dim}));
    params.push_back(ps);
    layer_input_dim = hidden_dim;
  }
  dropout_rate = 0.f;
}

void SimpleRNNBuilder::new_graph_impl(ComputationGraph& cg, bool update) {
  param_vars.clear();
  for (unsigned i = 0; i < layers; ++i) {
    Parameter p_x2h = params[i][X2H];
    Parameter p_h2h = params[i][H2H];
    Parameter p_hb = params[i][HB];
    Expression i_x2h =  update ? parameter(cg,p_x2h) : const_parameter(cg,p_x2h);
    Expression i_h2h =  update ? parameter(cg,p_h2h) : const_parameter(cg,p_h2h);
    Expression i_hb =  update ? parameter(cg,p_hb) : const_parameter(cg,p_hb);
    vector<Expression> vars = {i_x2h, i_h2h, i_hb};

    if (lagging) {
        Parameter p_l2h = params[i][L2H];
        Expression i_l2h =  update ? parameter(cg,p_l2h) : const_parameter(cg,p_l2h);
        vars.push_back(i_l2h);
    }

    param_vars.push_back(vars);
  }
  _cg = &cg;
}

void SimpleRNNBuilder::start_new_sequence_impl(const vector<Expression>& h_0) {
  h.clear();
  h0 = h_0;
  DYNET_ARG_CHECK(h0.empty() || h0.size() == layers,
                          "Number of inputs passed to initialize RNNBuilder (" << h0.size() << ") is not equal to the number of layers (" << layers << ")");
  dropout_masks_valid = false;
}

Expression SimpleRNNBuilder::set_h_impl(int prev, const vector<Expression>& h_new) {
  DYNET_ARG_CHECK(h_new.empty() || h_new.size() == layers,
                          "Number of inputs passed to RNNBuilder::set_h() (" << h_new.size() << ") is not equal to the number of layers (" << layers << ")");
  const unsigned t = h.size();
  h.push_back(vector<Expression>(layers));
  for (unsigned i = 0; i < layers; ++i) {
    Expression y = h_new[i];
    h[t][i] = y;
  }
  return h[t].back();
}

void SimpleRNNBuilder::set_dropout_masks(unsigned batch_size){
  masks.clear();
  for (unsigned i = 0; i < layers; ++i) {
    std::vector<Expression> masks_i;
    unsigned idim = (i == 0) ? input_dim_ : hidden_dim_;
    if (dropout_rate > 0.f ) {
      float retention_rate = 1.f - dropout_rate;
      float scale = 1.f / retention_rate;

      // input
      masks_i.push_back(random_bernoulli(*_cg, Dim({idim}, batch_size), retention_rate, scale));

      // hidden
      masks_i.push_back(random_bernoulli(*_cg, Dim({hidden_dim_}, batch_size), retention_rate, scale));

      masks.push_back(masks_i);
    }
  }
  dropout_masks_valid = true;
}

Expression SimpleRNNBuilder::add_input_impl(int prev, const Expression &in) {
  if(dropout_rate != 0.f && !dropout_masks_valid)
    set_dropout_masks(in.dim().bd);
  const unsigned t = h.size();
  h.push_back(vector<Expression>(layers));

  Expression x = in;
  Expression h_prev;

  for (unsigned i = 0; i < layers; ++i) {
    const vector<Expression>& vars = param_vars[i];

    if(dropout_rate > 0.f){
      x = cmult(x,masks[i][0]);
    }

    bool exists_h_prev = false;
    // y <--- g(y_prev)
    if(prev >= 0) {
      h_prev = h[prev][i];
      exists_h_prev = true;
    } else if(h0.size() > 0) {
      h_prev = h0[i];
      exists_h_prev = true;
    }

    if(exists_h_prev) {
      if(dropout_rate > 0.f)
        h_prev = cmult(h_prev,masks[i][1]);
      x = h[t][i] = tanh( affine_transform({vars[2], vars[0], x, vars[1], h_prev}) );
    }
    else{
      x = h[t][i] = tanh( affine_transform({vars[2], vars[0], x}) );
    }
  }
  return h[t].back();
}

Expression SimpleRNNBuilder::add_auxiliary_input(const Expression &in, const Expression &aux) {
  const unsigned t = h.size();
  h.push_back(vector<Expression>(layers));

  Expression x = in;

  for (unsigned i = 0; i < layers; ++i) {
    const vector<Expression>& vars = param_vars[i];
    DYNET_ASSERT(vars.size() >= L2H + 1, "Failed dimension check in SimpleRNNBuilder");

    if(t > 0) {
      x = h[t][i] = tanh( affine_transform({vars[HB], vars[X2H], x, vars[L2H], aux, vars[H2H], h[t-1][i]}) );
    } else if(h0.size() > 0) {
      x = h[t][i] = tanh( affine_transform({vars[HB], vars[X2H], x, vars[L2H], aux, vars[H2H], h0[i]}) );
    } else {
      x = h[t][i] = tanh( affine_transform({vars[HB], vars[X2H], x, vars[L2H], aux}) );
    }

  }
  return h[t].back();
}

void SimpleRNNBuilder::copy(const RNNBuilder & rnn) {
  const SimpleRNNBuilder & rnn_simple = (const SimpleRNNBuilder&)rnn;
  DYNET_ARG_CHECK(params.size() == rnn_simple.params.size(),
                          "Attempt to copy between two SimpleRNNBuilders that are not the same size");
  for(size_t i = 0; i < rnn_simple.params.size(); ++i) {
    params[i][0] = rnn_simple.params[i][0];
    params[i][1] = rnn_simple.params[i][1];
    params[i][2] = rnn_simple.params[i][2];
  }
}

ParameterCollection & SimpleRNNBuilder::get_parameter_collection() {
  return local_model;
}

} // namespace dynet
<|endoftext|>