<commit_before>/**
 * @file Tree_Data.cpp
 * @author Mislav Novakovic <mislav.novakovic@sartura.hr>
 * @brief Implementation of header Tree_Data.hpp.
 *
 * Copyright (c) 2017 Deutsche Telekom AG.
 *
 * This source code is licensed under BSD 3-Clause License (the "License").
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://opensource.org/licenses/BSD-3-Clause
 */

#include <iostream>
#include <memory>
#include <stdexcept>
#include <vector>

#include "Xml.hpp"
#include "Libyang.hpp"
#include "Tree_Data.hpp"
#include "Tree_Schema.hpp"

extern "C" {
#include "libyang.h"
#include "tree_data.h"
#include "tree_schema.h"
}

Value::Value(lyd_val value, uint16_t value_type, S_Deleter deleter):
    value(value),
    type(value_type),
    deleter(deleter)
{};
Value::~Value() {};
S_Data_Node Value::instance() {
    if (LY_TYPE_INST != type) {
        return nullptr;
    }
    return value.instance ? std::make_shared<Data_Node>(value.instance, deleter) : nullptr;
}
S_Data_Node Value::leafref() {
    if (LY_TYPE_LEAFREF != type) {
        return nullptr;
    }
    return value.leafref ? std::make_shared<Data_Node>(value.leafref, deleter) : nullptr;
}

Data_Node::Data_Node(struct lyd_node *node, S_Deleter deleter):
    node(node),
    deleter(deleter)
{};
Data_Node::Data_Node(S_Data_Node parent, S_Module module, const char *name) {
    lyd_node *new_node = nullptr;

    if (!module) {
        throw std::invalid_argument("Module can not be empty");
    }

    new_node = lyd_new(parent->node, module->module, name);
    if (!new_node) {
        check_libyang_error();
    }

    node = new_node;
    deleter = nullptr;
};
Data_Node::Data_Node(S_Data_Node parent, S_Module module, const char *name, const char *val_str) {
    lyd_node *new_node = nullptr;

    if (!module) {
        throw std::invalid_argument("Module can not be empty");
    }

    new_node = lyd_new_leaf(parent->node, module->module, name, val_str);
    if (!new_node) {
        check_libyang_error();
    }

    node = new_node;
    deleter = nullptr;
};
Data_Node::Data_Node(S_Data_Node parent, S_Module module, const char *name, const char *value, LYD_ANYDATA_VALUETYPE value_type) {
    lyd_node *new_node = nullptr;

    if (!module) {
        throw std::invalid_argument("Module can not be empty");
    }

    new_node = lyd_new_anydata(parent->node, module->module, name, (void *) value, value_type);
    if (!new_node) {
        check_libyang_error();
    }

    node = new_node;
    deleter = nullptr;
};
Data_Node::Data_Node(S_Data_Node parent, S_Module module, const char *name, S_Data_Node value, LYD_ANYDATA_VALUETYPE value_type) {
    lyd_node *new_node = nullptr;

    if (!module) {
        throw std::invalid_argument("Module can not be empty");
    }

    new_node = lyd_new_anydata(parent->node, module->module, name, (void *) value->node, value_type);
    if (!new_node) {
        check_libyang_error();
    }

    node = new_node;
    deleter = nullptr;
};
Data_Node::Data_Node(S_Data_Node parent, S_Module module, const char *name, S_Xml_Elem value, LYD_ANYDATA_VALUETYPE value_type) {
    lyd_node *new_node = nullptr;

    if (!module) {
        throw std::invalid_argument("Module can not be empty");
    }

    new_node = lyd_new_anydata(parent->node, module->module, name, (void *) value->elem, value_type);
    if (!new_node) {
        check_libyang_error();
    }

    node = new_node;
    deleter = nullptr;
}
Data_Node::~Data_Node() {};
S_Attr Data_Node::attr() LY_NEW(node, attr, Attr);
std::string Data_Node::path() {
    char *path = nullptr;

    path = lyd_path(node);
    if (!path) {
        check_libyang_error();
        return nullptr;
    }

    std::string s_path = path;
    free(path);
    return s_path;
}
S_Data_Node Data_Node::dup(int recursive) {
    struct lyd_node *new_node = nullptr;

    new_node = lyd_dup(node, recursive);

    return new_node ? std::make_shared<Data_Node>(new_node, deleter) : nullptr;
}
S_Data_Node Data_Node::dup_to_ctx(int recursive, S_Context context) {
    struct lyd_node *new_node = nullptr;

    new_node = lyd_dup_to_ctx(node, recursive, context->ctx);

    return new_node ? std::make_shared<Data_Node>(new_node, deleter) : nullptr;
}
int Data_Node::merge(S_Data_Node source, int options) {
    int ret = lyd_merge(node, source->node, options);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node::merge_to_ctx(S_Data_Node source, int options, S_Context context) {
    int ret = lyd_merge_to_ctx(&node, source->node, options, context->ctx);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node::insert(S_Data_Node new_node) {
    int ret = lyd_insert(node, new_node->node);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node::insert_sibling(S_Data_Node new_node) {
    int ret = lyd_insert_sibling(&node, new_node->node);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node::insert_before(S_Data_Node new_node) {
    int ret = lyd_insert_before(node, new_node->node);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node::insert_after(S_Data_Node new_node) {
    int ret = lyd_insert_after(node, new_node->node);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node::schema_sort(int recursive) {
    int ret = lyd_schema_sort(node, recursive);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
S_Set Data_Node::find_path(const char *expr) {
    struct ly_set *set = lyd_find_path(node, expr);
    if (!set) {
        return nullptr;
    }

    return std::make_shared<Set>(set, std::make_shared<Deleter>(set, deleter));
}
S_Set Data_Node::find_instance(S_Schema_Node schema) {
    struct ly_set *set = lyd_find_instance(node, schema->node);
    if (!set) {
        return nullptr;
    }

    return std::make_shared<Set>(set, std::make_shared<Deleter>(set, deleter));
}
S_Data_Node Data_Node::first_sibling() {
    struct lyd_node *new_node = nullptr;

    new_node = lyd_first_sibling(node);

    return new_node ? std::make_shared<Data_Node>(new_node, deleter) : nullptr;
}
int Data_Node::validate(int options, S_Context var_arg) {
    int ret = lyd_validate(&node, options, (void *) var_arg->ctx);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node::validate(int options, S_Data_Node var_arg) {
    int ret = lyd_validate(&node, options, (void *) var_arg->node);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}

int Data_Node::validate_value(const char *value) {
    int ret = lyd_validate_value(node->schema, value);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
S_Difflist Data_Node::diff(S_Data_Node second, int options) {
    struct lyd_difflist *diff;

    diff = lyd_diff(node, second->node, options);
    if (!diff) {
        check_libyang_error();
    }

    return diff ? std::make_shared<Difflist>(diff, deleter) : nullptr;
}
S_Data_Node Data_Node::new_path(S_Context ctx, const char *path, void *value, LYD_ANYDATA_VALUETYPE value_type, int options) {
    struct lyd_node *new_node = nullptr;

    new_node = lyd_new_path(node, ctx->ctx, path, value, value_type, options);
    if (!new_node) {
        check_libyang_error();
    }

    return new_node ? std::make_shared<Data_Node>(new_node, deleter) : nullptr;
}
unsigned int Data_Node::list_pos() {
    unsigned int ret = lyd_list_pos(node);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node::unlink() {
    int ret = lyd_unlink(node);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
S_Attr Data_Node::insert_attr(S_Module module, const char *name, const char *value) {
    struct lyd_attr *attr = nullptr;

    attr = lyd_insert_attr(node, module->module, name, value);
    if (!attr) {
        check_libyang_error();
    }

    return attr ? std::make_shared<Attr>(attr, deleter) : nullptr;
}
S_Module Data_Node::node_module() {
    struct lys_module *module = nullptr;

    module = lyd_node_module(node);
    if (!module) {
        check_libyang_error();
    }

    return module ? std::make_shared<Module>(module, deleter) : nullptr;
}
std::string Data_Node::print_mem(LYD_FORMAT format, int options) {
    char *strp = nullptr;
    int rc = 0;

    rc = lyd_print_mem(&strp, node, format, options);
    if (0 != rc) {
        check_libyang_error();
        return nullptr;
    }

    std::string s_strp = strp;
    free(strp);
    return s_strp;

}
std::vector<S_Data_Node> *Data_Node::tree_for() {
    auto s_vector = new std::vector<S_Data_Node>;

    struct lyd_node *elem = nullptr;
    LY_TREE_FOR(node, elem) {
        s_vector->push_back(std::make_shared<Data_Node>(elem, deleter));
    }

    return s_vector;
}
std::vector<S_Data_Node> *Data_Node::tree_dfs() {
    auto s_vector = new std::vector<S_Data_Node>;

    struct lyd_node *elem = nullptr, *next = nullptr;
    LY_TREE_DFS_BEGIN(node, next, elem) {
        s_vector->push_back(std::make_shared<Data_Node>(elem, deleter));
        LY_TREE_DFS_END(node, next, elem)
    }

    return s_vector;
}

Data_Node_Leaf_List::Data_Node_Leaf_List(struct lyd_node *node, S_Deleter deleter):
    Data_Node(node, deleter),
    node(node),
    deleter(deleter)
{};
Data_Node_Leaf_List::~Data_Node_Leaf_List() {};
S_Value Data_Node_Leaf_List::value() {
    struct lyd_node_leaf_list *leaf = (struct lyd_node_leaf_list *) node;
    return std::make_shared<Value>(leaf->value, leaf->value_type, deleter);
}
int Data_Node_Leaf_List::change_leaf(const char *val_str) {
    int ret = lyd_change_leaf((struct lyd_node_leaf_list *) node, val_str);
    if (ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node_Leaf_List::wd_default() {
    return lyd_wd_default((struct lyd_node_leaf_list *)node);
}
S_Type Data_Node_Leaf_List::leaf_type() {
    const struct lys_type *type = lyd_leaf_type((const struct lyd_node_leaf_list *) node);
    if (!type) {
        check_libyang_error();
    }

    return std::make_shared<Type>((struct lys_type *) type, deleter);
};

Data_Node_Anydata::Data_Node_Anydata(struct lyd_node *node, S_Deleter deleter):
    Data_Node(node, deleter),
    node(node),
    deleter(deleter)
{};
Data_Node_Anydata::~Data_Node_Anydata() {};

Attr::Attr(struct lyd_attr *attr, S_Deleter deleter):
    attr(attr),
    deleter(deleter)
{};
Attr::~Attr() {};
S_Value Attr::value() {
    struct lyd_node_leaf_list *leaf = (struct lyd_node_leaf_list *) attr;
    return std::make_shared<Value>(leaf->value, leaf->value_type, deleter);
}
S_Attr Attr::next() LY_NEW(attr, next, Attr);

Difflist::Difflist(struct lyd_difflist *diff, S_Deleter deleter) {
    diff = diff;
    deleter = std::make_shared<Deleter>(diff, deleter);
}
Difflist::~Difflist() {};
std::vector<S_Data_Node> *Difflist::first() {
    unsigned int i = 0;
    if (!*diff->first) {
        return nullptr;
    }

    auto s_vector = new std::vector<S_Data_Node>;

    for(i = 0; i < sizeof(*diff->first); i++) {
        s_vector->push_back(std::make_shared<Data_Node>(*diff->first, deleter));
    }

    return s_vector;
}
std::vector<S_Data_Node> *Difflist::second() {
    unsigned int i = 0;
    if (!*diff->second) {
        return nullptr;
    }

    auto s_vector = new std::vector<S_Data_Node>;

    for(i = 0; i < sizeof(*diff->second); i++) {
        s_vector->push_back(std::make_shared<Data_Node>(*diff->second, deleter));
    }

    return s_vector;
}

S_Data_Node create_new_Data_Node(struct lyd_node *new_node) {
    return new_node ? std::make_shared<Data_Node>(new_node, nullptr) : nullptr;
}
<commit_msg>swig BUGFIX check input parameters when dereferencing them<commit_after>/**
 * @file Tree_Data.cpp
 * @author Mislav Novakovic <mislav.novakovic@sartura.hr>
 * @brief Implementation of header Tree_Data.hpp.
 *
 * Copyright (c) 2017 Deutsche Telekom AG.
 *
 * This source code is licensed under BSD 3-Clause License (the "License").
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://opensource.org/licenses/BSD-3-Clause
 */

#include <iostream>
#include <memory>
#include <stdexcept>
#include <vector>

#include "Xml.hpp"
#include "Libyang.hpp"
#include "Tree_Data.hpp"
#include "Tree_Schema.hpp"

extern "C" {
#include "libyang.h"
#include "tree_data.h"
#include "tree_schema.h"
}

Value::Value(lyd_val value, uint16_t value_type, S_Deleter deleter):
    value(value),
    type(value_type),
    deleter(deleter)
{};
Value::~Value() {};
S_Data_Node Value::instance() {
    if (LY_TYPE_INST != type) {
        return nullptr;
    }
    return value.instance ? std::make_shared<Data_Node>(value.instance, deleter) : nullptr;
}
S_Data_Node Value::leafref() {
    if (LY_TYPE_LEAFREF != type) {
        return nullptr;
    }
    return value.leafref ? std::make_shared<Data_Node>(value.leafref, deleter) : nullptr;
}

Data_Node::Data_Node(struct lyd_node *node, S_Deleter deleter):
    node(node),
    deleter(deleter)
{};
Data_Node::Data_Node(S_Data_Node parent, S_Module module, const char *name) {
    lyd_node *new_node = nullptr;

    if (!module) {
        throw std::invalid_argument("Module can not be empty");
    }

    new_node = lyd_new(parent ? parent->node : NULL, module->module, name);
    if (!new_node) {
        check_libyang_error();
    }

    node = new_node;
    deleter = nullptr;
};
Data_Node::Data_Node(S_Data_Node parent, S_Module module, const char *name, const char *val_str) {
    lyd_node *new_node = nullptr;

    if (!module) {
        throw std::invalid_argument("Module can not be empty");
    }

    new_node = lyd_new_leaf(parent ? parent->node : NULL, module->module, name, val_str);
    if (!new_node) {
        check_libyang_error();
    }

    node = new_node;
    deleter = nullptr;
};
Data_Node::Data_Node(S_Data_Node parent, S_Module module, const char *name, const char *value, LYD_ANYDATA_VALUETYPE value_type) {
    lyd_node *new_node = nullptr;

    if (!module) {
        throw std::invalid_argument("Module can not be empty");
    }

    new_node = lyd_new_anydata(parent ? parent->node : NULL, module->module, name, (void *) value, value_type);
    if (!new_node) {
        check_libyang_error();
    }

    node = new_node;
    deleter = nullptr;
};
Data_Node::Data_Node(S_Data_Node parent, S_Module module, const char *name, S_Data_Node value, LYD_ANYDATA_VALUETYPE value_type) {
    lyd_node *new_node = nullptr;

    if (!module) {
        throw std::invalid_argument("Module can not be empty");
    }

    new_node = lyd_new_anydata(parent ? parent->node : NULL, module->module, name, (void *) value->node, value_type);
    if (!new_node) {
        check_libyang_error();
    }

    node = new_node;
    deleter = nullptr;
};
Data_Node::Data_Node(S_Data_Node parent, S_Module module, const char *name, S_Xml_Elem value, LYD_ANYDATA_VALUETYPE value_type) {
    lyd_node *new_node = nullptr;

    if (!module) {
        throw std::invalid_argument("Module can not be empty");
    }

    new_node = lyd_new_anydata(parent ? parent->node : NULL, module->module, name, (void *) value->elem, value_type);
    if (!new_node) {
        check_libyang_error();
    }

    node = new_node;
    deleter = nullptr;
}
Data_Node::~Data_Node() {};
S_Attr Data_Node::attr() LY_NEW(node, attr, Attr);
std::string Data_Node::path() {
    char *path = nullptr;

    path = lyd_path(node);
    if (!path) {
        check_libyang_error();
        return nullptr;
    }

    std::string s_path = path;
    free(path);
    return s_path;
}
S_Data_Node Data_Node::dup(int recursive) {
    struct lyd_node *new_node = nullptr;

    new_node = lyd_dup(node, recursive);

    return new_node ? std::make_shared<Data_Node>(new_node, deleter) : nullptr;
}
S_Data_Node Data_Node::dup_to_ctx(int recursive, S_Context context) {
    struct lyd_node *new_node = nullptr;

    new_node = lyd_dup_to_ctx(node, recursive, context->ctx);

    return new_node ? std::make_shared<Data_Node>(new_node, deleter) : nullptr;
}
int Data_Node::merge(S_Data_Node source, int options) {
    int ret = lyd_merge(node, source->node, options);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node::merge_to_ctx(S_Data_Node source, int options, S_Context context) {
    int ret = lyd_merge_to_ctx(&node, source->node, options, context->ctx);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node::insert(S_Data_Node new_node) {
    int ret = lyd_insert(node, new_node->node);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node::insert_sibling(S_Data_Node new_node) {
    int ret = lyd_insert_sibling(&node, new_node->node);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node::insert_before(S_Data_Node new_node) {
    int ret = lyd_insert_before(node, new_node->node);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node::insert_after(S_Data_Node new_node) {
    int ret = lyd_insert_after(node, new_node->node);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node::schema_sort(int recursive) {
    int ret = lyd_schema_sort(node, recursive);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
S_Set Data_Node::find_path(const char *expr) {
    struct ly_set *set = lyd_find_path(node, expr);
    if (!set) {
        return nullptr;
    }

    return std::make_shared<Set>(set, std::make_shared<Deleter>(set, deleter));
}
S_Set Data_Node::find_instance(S_Schema_Node schema) {
    struct ly_set *set = lyd_find_instance(node, schema->node);
    if (!set) {
        return nullptr;
    }

    return std::make_shared<Set>(set, std::make_shared<Deleter>(set, deleter));
}
S_Data_Node Data_Node::first_sibling() {
    struct lyd_node *new_node = nullptr;

    new_node = lyd_first_sibling(node);

    return new_node ? std::make_shared<Data_Node>(new_node, deleter) : nullptr;
}
int Data_Node::validate(int options, S_Context var_arg) {
    int ret = lyd_validate(&node, options, (void *) var_arg->ctx);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node::validate(int options, S_Data_Node var_arg) {
    int ret = lyd_validate(&node, options, (void *) var_arg->node);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}

int Data_Node::validate_value(const char *value) {
    int ret = lyd_validate_value(node->schema, value);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
S_Difflist Data_Node::diff(S_Data_Node second, int options) {
    struct lyd_difflist *diff;

    diff = lyd_diff(node, second->node, options);
    if (!diff) {
        check_libyang_error();
    }

    return diff ? std::make_shared<Difflist>(diff, deleter) : nullptr;
}
S_Data_Node Data_Node::new_path(S_Context ctx, const char *path, void *value, LYD_ANYDATA_VALUETYPE value_type, int options) {
    struct lyd_node *new_node = nullptr;

    new_node = lyd_new_path(node, ctx->ctx, path, value, value_type, options);
    if (!new_node) {
        check_libyang_error();
    }

    return new_node ? std::make_shared<Data_Node>(new_node, deleter) : nullptr;
}
unsigned int Data_Node::list_pos() {
    unsigned int ret = lyd_list_pos(node);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node::unlink() {
    int ret = lyd_unlink(node);
    if (!ret) {
        check_libyang_error();
    }
    return ret;
}
S_Attr Data_Node::insert_attr(S_Module module, const char *name, const char *value) {
    struct lyd_attr *attr = nullptr;

    attr = lyd_insert_attr(node, module ? module->module : NULL, name, value);
    if (!attr) {
        check_libyang_error();
    }

    return attr ? std::make_shared<Attr>(attr, deleter) : nullptr;
}
S_Module Data_Node::node_module() {
    struct lys_module *module = nullptr;

    module = lyd_node_module(node);
    if (!module) {
        check_libyang_error();
    }

    return module ? std::make_shared<Module>(module, deleter) : nullptr;
}
std::string Data_Node::print_mem(LYD_FORMAT format, int options) {
    char *strp = nullptr;
    int rc = 0;

    rc = lyd_print_mem(&strp, node, format, options);
    if (0 != rc) {
        check_libyang_error();
        return nullptr;
    }

    std::string s_strp = strp;
    free(strp);
    return s_strp;

}
std::vector<S_Data_Node> *Data_Node::tree_for() {
    auto s_vector = new std::vector<S_Data_Node>;

    struct lyd_node *elem = nullptr;
    LY_TREE_FOR(node, elem) {
        s_vector->push_back(std::make_shared<Data_Node>(elem, deleter));
    }

    return s_vector;
}
std::vector<S_Data_Node> *Data_Node::tree_dfs() {
    auto s_vector = new std::vector<S_Data_Node>;

    struct lyd_node *elem = nullptr, *next = nullptr;
    LY_TREE_DFS_BEGIN(node, next, elem) {
        s_vector->push_back(std::make_shared<Data_Node>(elem, deleter));
        LY_TREE_DFS_END(node, next, elem)
    }

    return s_vector;
}

Data_Node_Leaf_List::Data_Node_Leaf_List(struct lyd_node *node, S_Deleter deleter):
    Data_Node(node, deleter),
    node(node),
    deleter(deleter)
{};
Data_Node_Leaf_List::~Data_Node_Leaf_List() {};
S_Value Data_Node_Leaf_List::value() {
    struct lyd_node_leaf_list *leaf = (struct lyd_node_leaf_list *) node;
    return std::make_shared<Value>(leaf->value, leaf->value_type, deleter);
}
int Data_Node_Leaf_List::change_leaf(const char *val_str) {
    int ret = lyd_change_leaf((struct lyd_node_leaf_list *) node, val_str);
    if (ret) {
        check_libyang_error();
    }
    return ret;
}
int Data_Node_Leaf_List::wd_default() {
    return lyd_wd_default((struct lyd_node_leaf_list *)node);
}
S_Type Data_Node_Leaf_List::leaf_type() {
    const struct lys_type *type = lyd_leaf_type((const struct lyd_node_leaf_list *) node);
    if (!type) {
        check_libyang_error();
    }

    return std::make_shared<Type>((struct lys_type *) type, deleter);
};

Data_Node_Anydata::Data_Node_Anydata(struct lyd_node *node, S_Deleter deleter):
    Data_Node(node, deleter),
    node(node),
    deleter(deleter)
{};
Data_Node_Anydata::~Data_Node_Anydata() {};

Attr::Attr(struct lyd_attr *attr, S_Deleter deleter):
    attr(attr),
    deleter(deleter)
{};
Attr::~Attr() {};
S_Value Attr::value() {
    struct lyd_node_leaf_list *leaf = (struct lyd_node_leaf_list *) attr;
    return std::make_shared<Value>(leaf->value, leaf->value_type, deleter);
}
S_Attr Attr::next() LY_NEW(attr, next, Attr);

Difflist::Difflist(struct lyd_difflist *diff, S_Deleter deleter) {
    diff = diff;
    deleter = std::make_shared<Deleter>(diff, deleter);
}
Difflist::~Difflist() {};
std::vector<S_Data_Node> *Difflist::first() {
    unsigned int i = 0;
    if (!*diff->first) {
        return nullptr;
    }

    auto s_vector = new std::vector<S_Data_Node>;

    for(i = 0; i < sizeof(*diff->first); i++) {
        s_vector->push_back(std::make_shared<Data_Node>(*diff->first, deleter));
    }

    return s_vector;
}
std::vector<S_Data_Node> *Difflist::second() {
    unsigned int i = 0;
    if (!*diff->second) {
        return nullptr;
    }

    auto s_vector = new std::vector<S_Data_Node>;

    for(i = 0; i < sizeof(*diff->second); i++) {
        s_vector->push_back(std::make_shared<Data_Node>(*diff->second, deleter));
    }

    return s_vector;
}

S_Data_Node create_new_Data_Node(struct lyd_node *new_node) {
    return new_node ? std::make_shared<Data_Node>(new_node, nullptr) : nullptr;
}
<|endoftext|>


<commit_before>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include "config.h"

#include "common/common_init.h"
#include "common/arch.h"

#include <iostream>
#include <stdlib.h>
#include <dlfcn.h>

#include "include/rbd_types.h"

void usage()
{
  cout << "usage: cclsinfo [-n] [-v] [-a] <cls_file_name>\n"
       << "\t-n\tlist rbd images\n"
       << "\t-v\tshow information about image size, striping, etc.\n" << std::endl;

  exit(1);
}

static int char_count = 0;
static char print_char_maybe(char c)
{
  if (char_count++)
    return c;

  return  '\0';
}

int main(int argc, const char **argv)
{
  vector<const char*> args;
  DEFINE_CONF_VARS(usage);
  argv_to_vec(argc, argv, args);
  env_to_vec(args);
  common_init(args, "cclsinfo", false, true);

  bool opt_name = false, opt_ver = false, opt_arch = false;
  const char *fname = NULL;

  FOR_EACH_ARG(args) {
    if (CONF_ARG_EQ("name", 'n')) {
      CONF_SAFE_SET_ARG_VAL(&opt_name, OPT_BOOL);
    } else if (CONF_ARG_EQ("arch", 'a')) {
      CONF_SAFE_SET_ARG_VAL(&opt_arch, OPT_BOOL);
    } else if (CONF_ARG_EQ("ver", 'v')) {
      CONF_SAFE_SET_ARG_VAL(&opt_arch, OPT_BOOL);
    } else  {
      if (fname)
        usage();
      fname = CONF_VAL;
    }
  }

  if (!fname)
    usage();

  if (!opt_name && !opt_ver && !opt_arch) {
    opt_name = true;
    opt_ver = true;
    opt_arch = true;
  }

  void *handle = dlopen(fname, RTLD_LAZY);
  if (!handle) {
    perror("dlopen");
    exit(1);
  }

  const char *cls_name = *(const char **)dlsym(handle, "__cls_name");
  if (!cls_name) {
    cerr << "cls_name not defined, not a ceph class\n" << std::endl;
    dlclose(handle);
    exit(1);
  }

  if (opt_name) {
    cout << print_char_maybe(' ') << cls_name;
  }

  if (opt_ver) {
    int ver_maj = *(int *)dlsym(handle, "__cls_ver_maj");
    int ver_min = *(int *)dlsym(handle, "__cls_ver_min");
    cout << print_char_maybe(' ') << ver_maj << "." << ver_min;
  }

  if (opt_arch) {
    cout << print_char_maybe(' ') << get_arch();
  }

  cout << print_char_maybe('\n');

  dlclose(handle);
  exit(0);

}

<commit_msg>cclsinfo: some fixes<commit_after>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include "config.h"

#include "common/common_init.h"
#include "common/arch.h"

#include <iostream>
#include <stdlib.h>
#include <dlfcn.h>

#include "include/rbd_types.h"

void usage()
{
  cout << "usage: cclsinfo [-n] [-v] [-a] <cls_file_name>\n"
       << "\t-n\tlist rbd images\n"
       << "\t-v\tshow information about image size, striping, etc.\n" << std::endl;

  exit(1);
}

static int char_count = 0;
static char print_char_maybe(char c)
{
  if (char_count++)
    return c;

  return  '\0';
}

int main(int argc, const char **argv)
{
  vector<const char*> args;
  DEFINE_CONF_VARS(usage);
  argv_to_vec(argc, argv, args);
  env_to_vec(args);

  bool opt_name = false, opt_ver = false, opt_arch = false;
  const char *fname = NULL;

  FOR_EACH_ARG(args) {
    if (CONF_ARG_EQ("name", 'n')) {
      CONF_SAFE_SET_ARG_VAL(&opt_name, OPT_BOOL);
    } else if (CONF_ARG_EQ("arch", 'a')) {
      CONF_SAFE_SET_ARG_VAL(&opt_arch, OPT_BOOL);
    } else if (CONF_ARG_EQ("ver", 'v')) {
      CONF_SAFE_SET_ARG_VAL(&opt_ver, OPT_BOOL);
    } else  {
      if (fname)
        usage();
      fname = CONF_VAL;
    }
  }

  if (!fname)
    usage();

  if (!opt_name && !opt_ver && !opt_arch) {
    opt_name = true;
    opt_ver = true;
    opt_arch = true;
  }

  void *handle = dlopen(fname, RTLD_LAZY);
  if (!handle) {
    perror("dlopen");
    exit(1);
  }

  const char *cls_name = *(const char **)dlsym(handle, "__cls_name");
  if (!cls_name) {
    cerr << "cls_name not defined, not a ceph class\n" << std::endl;
    dlclose(handle);
    exit(1);
  }

  if (opt_name) {
    cout << print_char_maybe(' ') << cls_name;
  }

  if (opt_ver) {
    int ver_maj = *(int *)dlsym(handle, "__cls_ver_maj");
    int ver_min = *(int *)dlsym(handle, "__cls_ver_min");
    cout << print_char_maybe(' ') << ver_maj << "." << ver_min;
  }

  if (opt_arch) {
    cout << print_char_maybe(' ') << get_arch();
  }

  cout << print_char_maybe('\n');

  dlclose(handle);
  exit(0);

}

<|endoftext|>


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

#include "flutter/lib/ui/compositing/scene_builder.h"

#include "flutter/lib/ui/painting/matrix.h"
#include "flutter/lib/ui/painting/shader.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "flutter/lib/ui/window/window.h"
#include "lib/fxl/build_config.h"
#include "lib/tonic/converter/dart_converter.h"
#include "lib/tonic/dart_args.h"
#include "lib/tonic/dart_binding_macros.h"
#include "lib/tonic/dart_library_natives.h"
#include "third_party/skia/include/core/SkColorFilter.h"

namespace blink {

static void SceneBuilder_constructor(Dart_NativeArguments args) {
  DartCallConstructor(&SceneBuilder::create, args);
}

IMPLEMENT_WRAPPERTYPEINFO(ui, SceneBuilder);

#define FOR_EACH_BINDING(V)                         \
  V(SceneBuilder, pushTransform)                    \
  V(SceneBuilder, pushClipRect)                     \
  V(SceneBuilder, pushClipRRect)                    \
  V(SceneBuilder, pushClipPath)                     \
  V(SceneBuilder, pushOpacity)                      \
  V(SceneBuilder, pushColorFilter)                  \
  V(SceneBuilder, pushBackdropFilter)               \
  V(SceneBuilder, pushShaderMask)                   \
  V(SceneBuilder, pushPhysicalModel)                \
  V(SceneBuilder, pop)                              \
  V(SceneBuilder, addPicture)                       \
  V(SceneBuilder, addChildScene)                    \
  V(SceneBuilder, addPerformanceOverlay)            \
  V(SceneBuilder, setRasterizerTracingThreshold)    \
  V(SceneBuilder, setCheckerboardOffscreenLayers)   \
  V(SceneBuilder, setCheckerboardRasterCacheImages) \
  V(SceneBuilder, build)

FOR_EACH_BINDING(DART_NATIVE_CALLBACK)

void SceneBuilder::RegisterNatives(tonic::DartLibraryNatives* natives) {
  natives->Register(
      {{"SceneBuilder_constructor", SceneBuilder_constructor, 1, true},
       FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}

SceneBuilder::SceneBuilder() : layer_builder_(flow::LayerBuilder::Create()) {}

SceneBuilder::~SceneBuilder() = default;

void SceneBuilder::pushTransform(const tonic::Float64List& matrix4) {
  layer_builder_->PushTransform(ToSkMatrix(matrix4));
}

void SceneBuilder::pushClipRect(double left,
                                double right,
                                double top,
                                double bottom) {
  layer_builder_->PushClipRect(SkRect::MakeLTRB(left, top, right, bottom));
}

void SceneBuilder::pushClipRRect(const RRect& rrect) {
  layer_builder_->PushClipRoundedRect(rrect.sk_rrect);
}

void SceneBuilder::pushClipPath(const CanvasPath* path) {
  layer_builder_->PushClipPath(path->path());
}

void SceneBuilder::pushOpacity(int alpha) {
  layer_builder_->PushOpacity(alpha);
}

void SceneBuilder::pushColorFilter(int color, int blendMode) {
  layer_builder_->PushColorFilter(static_cast<SkColor>(color),
                                  static_cast<SkBlendMode>(blendMode));
}

void SceneBuilder::pushBackdropFilter(ImageFilter* filter) {
  layer_builder_->PushBackdropFilter(filter->filter());
}

void SceneBuilder::pushShaderMask(Shader* shader,
                                  double maskRectLeft,
                                  double maskRectRight,
                                  double maskRectTop,
                                  double maskRectBottom,
                                  int blendMode) {
  layer_builder_->PushShaderMask(
      shader->shader(),
      SkRect::MakeLTRB(maskRectLeft, maskRectTop, maskRectRight,
                       maskRectBottom),
      static_cast<SkBlendMode>(blendMode));
}

void SceneBuilder::pushPhysicalModel(const RRect& rrect,
                                     double elevation,
                                     int color) {
  layer_builder_->PushPhysicalModel(
      rrect.sk_rrect,               //
      elevation,                    //
      static_cast<SkColor>(color),  //
      UIDartState::Current()->window()->viewport_metrics().device_pixel_ratio);
}

void SceneBuilder::pop() {
  layer_builder_->Pop();
}

void SceneBuilder::addPicture(double dx,
                              double dy,
                              Picture* picture,
                              int hints) {
  layer_builder_->PushPicture(SkPoint::Make(dx, dy),  //
                              picture->picture(),     //
                              !!(hints & 1),          // picture is complex
                              !!(hints & 2)           // picture will change
  );
}

void SceneBuilder::addChildScene(double dx,
                                 double dy,
                                 double width,
                                 double height,
                                 SceneHost* sceneHost,
                                 bool hitTestable) {
#if defined(OS_FUCHSIA)
  layer_builder_->PushChildScene(SkPoint::Make(dx, dy),            //
                                 SkSize::Make(width, height),      //
                                 sceneHost->export_node_holder(),  //
                                 hitTestable);
#endif  // defined(OS_FUCHSIA)
}

void SceneBuilder::addPerformanceOverlay(uint64_t enabledOptions,
                                         double left,
                                         double right,
                                         double top,
                                         double bottom) {
  layer_builder_->PushPerformanceOverlay(
      enabledOptions, SkRect::MakeLTRB(left, top, right, bottom));
}

void SceneBuilder::setRasterizerTracingThreshold(uint32_t frameInterval) {
  layer_builder_->SetRasterizerTracingThreshold(frameInterval);
}

void SceneBuilder::setCheckerboardRasterCacheImages(bool checkerboard) {
  layer_builder_->SetCheckerboardRasterCacheImages(checkerboard);
}

void SceneBuilder::setCheckerboardOffscreenLayers(bool checkerboard) {
  layer_builder_->SetCheckerboardOffscreenLayers(checkerboard);
}

fxl::RefPtr<Scene> SceneBuilder::build() {
  fxl::RefPtr<Scene> scene =
      Scene::create(layer_builder_->TakeLayer(),
                    layer_builder_->GetRasterizerTracingThreshold(),
                    layer_builder_->GetCheckerboardRasterCacheImages(),
                    layer_builder_->GetCheckerboardOffscreenLayers());
  ClearDartWrapper();
  layer_builder_.reset();
  return scene;
}

}  // namespace blink
<commit_msg>Remove use of a SceneBuilder member after deletion (#4209)<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/lib/ui/compositing/scene_builder.h"

#include "flutter/lib/ui/painting/matrix.h"
#include "flutter/lib/ui/painting/shader.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "flutter/lib/ui/window/window.h"
#include "lib/fxl/build_config.h"
#include "lib/tonic/converter/dart_converter.h"
#include "lib/tonic/dart_args.h"
#include "lib/tonic/dart_binding_macros.h"
#include "lib/tonic/dart_library_natives.h"
#include "third_party/skia/include/core/SkColorFilter.h"

namespace blink {

static void SceneBuilder_constructor(Dart_NativeArguments args) {
  DartCallConstructor(&SceneBuilder::create, args);
}

IMPLEMENT_WRAPPERTYPEINFO(ui, SceneBuilder);

#define FOR_EACH_BINDING(V)                         \
  V(SceneBuilder, pushTransform)                    \
  V(SceneBuilder, pushClipRect)                     \
  V(SceneBuilder, pushClipRRect)                    \
  V(SceneBuilder, pushClipPath)                     \
  V(SceneBuilder, pushOpacity)                      \
  V(SceneBuilder, pushColorFilter)                  \
  V(SceneBuilder, pushBackdropFilter)               \
  V(SceneBuilder, pushShaderMask)                   \
  V(SceneBuilder, pushPhysicalModel)                \
  V(SceneBuilder, pop)                              \
  V(SceneBuilder, addPicture)                       \
  V(SceneBuilder, addChildScene)                    \
  V(SceneBuilder, addPerformanceOverlay)            \
  V(SceneBuilder, setRasterizerTracingThreshold)    \
  V(SceneBuilder, setCheckerboardOffscreenLayers)   \
  V(SceneBuilder, setCheckerboardRasterCacheImages) \
  V(SceneBuilder, build)

FOR_EACH_BINDING(DART_NATIVE_CALLBACK)

void SceneBuilder::RegisterNatives(tonic::DartLibraryNatives* natives) {
  natives->Register(
      {{"SceneBuilder_constructor", SceneBuilder_constructor, 1, true},
       FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}

SceneBuilder::SceneBuilder() : layer_builder_(flow::LayerBuilder::Create()) {}

SceneBuilder::~SceneBuilder() = default;

void SceneBuilder::pushTransform(const tonic::Float64List& matrix4) {
  layer_builder_->PushTransform(ToSkMatrix(matrix4));
}

void SceneBuilder::pushClipRect(double left,
                                double right,
                                double top,
                                double bottom) {
  layer_builder_->PushClipRect(SkRect::MakeLTRB(left, top, right, bottom));
}

void SceneBuilder::pushClipRRect(const RRect& rrect) {
  layer_builder_->PushClipRoundedRect(rrect.sk_rrect);
}

void SceneBuilder::pushClipPath(const CanvasPath* path) {
  layer_builder_->PushClipPath(path->path());
}

void SceneBuilder::pushOpacity(int alpha) {
  layer_builder_->PushOpacity(alpha);
}

void SceneBuilder::pushColorFilter(int color, int blendMode) {
  layer_builder_->PushColorFilter(static_cast<SkColor>(color),
                                  static_cast<SkBlendMode>(blendMode));
}

void SceneBuilder::pushBackdropFilter(ImageFilter* filter) {
  layer_builder_->PushBackdropFilter(filter->filter());
}

void SceneBuilder::pushShaderMask(Shader* shader,
                                  double maskRectLeft,
                                  double maskRectRight,
                                  double maskRectTop,
                                  double maskRectBottom,
                                  int blendMode) {
  layer_builder_->PushShaderMask(
      shader->shader(),
      SkRect::MakeLTRB(maskRectLeft, maskRectTop, maskRectRight,
                       maskRectBottom),
      static_cast<SkBlendMode>(blendMode));
}

void SceneBuilder::pushPhysicalModel(const RRect& rrect,
                                     double elevation,
                                     int color) {
  layer_builder_->PushPhysicalModel(
      rrect.sk_rrect,               //
      elevation,                    //
      static_cast<SkColor>(color),  //
      UIDartState::Current()->window()->viewport_metrics().device_pixel_ratio);
}

void SceneBuilder::pop() {
  layer_builder_->Pop();
}

void SceneBuilder::addPicture(double dx,
                              double dy,
                              Picture* picture,
                              int hints) {
  layer_builder_->PushPicture(SkPoint::Make(dx, dy),  //
                              picture->picture(),     //
                              !!(hints & 1),          // picture is complex
                              !!(hints & 2)           // picture will change
  );
}

void SceneBuilder::addChildScene(double dx,
                                 double dy,
                                 double width,
                                 double height,
                                 SceneHost* sceneHost,
                                 bool hitTestable) {
#if defined(OS_FUCHSIA)
  layer_builder_->PushChildScene(SkPoint::Make(dx, dy),            //
                                 SkSize::Make(width, height),      //
                                 sceneHost->export_node_holder(),  //
                                 hitTestable);
#endif  // defined(OS_FUCHSIA)
}

void SceneBuilder::addPerformanceOverlay(uint64_t enabledOptions,
                                         double left,
                                         double right,
                                         double top,
                                         double bottom) {
  layer_builder_->PushPerformanceOverlay(
      enabledOptions, SkRect::MakeLTRB(left, top, right, bottom));
}

void SceneBuilder::setRasterizerTracingThreshold(uint32_t frameInterval) {
  layer_builder_->SetRasterizerTracingThreshold(frameInterval);
}

void SceneBuilder::setCheckerboardRasterCacheImages(bool checkerboard) {
  layer_builder_->SetCheckerboardRasterCacheImages(checkerboard);
}

void SceneBuilder::setCheckerboardOffscreenLayers(bool checkerboard) {
  layer_builder_->SetCheckerboardOffscreenLayers(checkerboard);
}

fxl::RefPtr<Scene> SceneBuilder::build() {
  fxl::RefPtr<Scene> scene =
      Scene::create(layer_builder_->TakeLayer(),
                    layer_builder_->GetRasterizerTracingThreshold(),
                    layer_builder_->GetCheckerboardRasterCacheImages(),
                    layer_builder_->GetCheckerboardOffscreenLayers());
  ClearDartWrapper();
  return scene;
}

}  // namespace blink
<|endoftext|>


<commit_before>//  Copyright 2010 Gregory Szorc
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

#include <zippylog/client.hpp>
#include <zippylog/device/server.hpp>

#include <gtest/gtest.h>

using ::std::invalid_argument;
using ::std::string;
using ::std::vector;
using ::zippylog::device::Server;
using ::zippylog::device::ServerStartParams;
using ::zippylog::Store;
using ::zmq::context_t;

namespace zippylog {
namespace client {

class ClientTest : public ::testing::Test
{
    protected:
        Server * server;
        Store * store;
        context_t ctx;

        ClientTest() :
            server(NULL),
            store(NULL),
            ctx(2)
        { }

        ~ClientTest() {
            if (this->server) {
                this->server->Shutdown();
                delete this->server;
            }

            if (this->store) delete this->store;
        }

        Server * GetServer(string store_path, string &endpoint)
        {
            if (this->server) {
                delete this->server;
                this->server = NULL;
            }

            ServerStartParams p1;
            p1.listen_endpoints.push_back("inproc://test00");
            endpoint = "inproc://test00";
            p1.store_path = store_path;
            p1.ctx = &this->ctx;

            // disable log writing
            p1.log_bucket.clear();
            p1.log_stream_set.clear();

            this->server = new Server(p1);
            server->RunAsync();

            return this->server;
        }

        Store * GetStore(string path)
        {
            if (this->store) {
                delete this->store;
                this->store = NULL;
            }

            this->store = Store::CreateStore(path);

            return this->store;
        }

        context_t * GetContext() {
            return &this->ctx;
        }
};

TEST_F(ClientTest, StartParamValidation)
{
    ASSERT_TRUE(true);
}

TEST_F(ClientTest, SynchronousTimeout)
{
    string endpoint;
    Server *s = this->GetServer("simpledirectory://test/stores/00-simple", endpoint);
    Client c(this->GetContext(), endpoint);

    protocol::StoreInfo si;
    // it is not reasonable to expect the server to respond in 1 microsecond
    // although, it could be possible
    ASSERT_FALSE(c.StoreInfo(si, 1));
}

TEST_F(ClientTest, StoreInfoSynchronous)
{
    string endpoint;
    string store_path = "simpledirectory://test/stores/00-simple";
    Server *s = this->GetServer(store_path, endpoint);
    Store *store = this->GetStore(store_path);

    Client c(this->GetContext(), endpoint);

    protocol::StoreInfo si;
    ASSERT_TRUE(c.StoreInfo(si));
    protocol::StoreInfo expected;
    ASSERT_TRUE(store->StoreInfo(expected));

    ASSERT_TRUE(si.SerializeAsString() == expected.SerializeAsString());
}

}} // namespaces<commit_msg>implement synchronous Get basic unit test<commit_after>//  Copyright 2010 Gregory Szorc
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

#include <zippylog/client.hpp>
#include <zippylog/device/server.hpp>

#include <gtest/gtest.h>

using ::std::invalid_argument;
using ::std::string;
using ::std::vector;
using ::zippylog::device::Server;
using ::zippylog::device::ServerStartParams;
using ::zippylog::Store;
using ::zmq::context_t;

namespace zippylog {
namespace client {

class ClientTest : public ::testing::Test
{
    protected:
        Server * server;
        Store * store;
        context_t ctx;

        ClientTest() :
            server(NULL),
            store(NULL),
            ctx(2)
        { }

        ~ClientTest() {
            if (this->server) {
                this->server->Shutdown();
                delete this->server;
            }

            if (this->store) delete this->store;
        }

        Server * GetServer(string store_path, string &endpoint)
        {
            if (this->server) {
                delete this->server;
                this->server = NULL;
            }

            ServerStartParams p1;
            p1.listen_endpoints.push_back("inproc://test00");
            endpoint = "inproc://test00";
            p1.store_path = store_path;
            p1.ctx = &this->ctx;

            // disable log writing
            p1.log_bucket.clear();
            p1.log_stream_set.clear();

            this->server = new Server(p1);
            server->RunAsync();

            return this->server;
        }

        Store * GetStore(string path)
        {
            if (this->store) {
                delete this->store;
                this->store = NULL;
            }

            this->store = Store::CreateStore(path);

            return this->store;
        }

        context_t * GetContext() {
            return &this->ctx;
        }
};

TEST_F(ClientTest, StartParamValidation)
{
    ASSERT_TRUE(true);
}

TEST_F(ClientTest, SynchronousTimeout)
{
    string endpoint;
    Server *s = this->GetServer("simpledirectory://test/stores/00-simple", endpoint);
    Client c(this->GetContext(), endpoint);

    protocol::StoreInfo si;
    // it is not reasonable to expect the server to respond in 1 microsecond
    // although, it could be possible
    ASSERT_FALSE(c.StoreInfo(si, 1));
}

TEST_F(ClientTest, StoreInfoSynchronous)
{
    string endpoint;
    string store_path = "simpledirectory://test/stores/00-simple";
    Server *s = this->GetServer(store_path, endpoint);
    Store *store = this->GetStore(store_path);

    Client c(this->GetContext(), endpoint);

    protocol::StoreInfo si;
    ASSERT_TRUE(c.StoreInfo(si));
    protocol::StoreInfo expected;
    ASSERT_TRUE(store->StoreInfo(expected));

    ASSERT_TRUE(si.SerializeAsString() == expected.SerializeAsString());
}

TEST_F(ClientTest, GetSynchronous)
{
    string endpoint;
    string store_path = "simpledirectory://test/stores/01-singlestream";
    Server *s = this->GetServer(store_path, endpoint);
    Store *store = this->GetStore(store_path);

    Client c(this->GetContext(), endpoint);

    StreamSegment segment;
    ASSERT_TRUE(c.Get("/A/B/2010-11-26-07", 0, segment, 5000000));

    EXPECT_EQ(segment.EnvelopesSent, segment.Envelopes.size());
    EXPECT_EQ(160, segment.EnvelopesSent);
}

}} // namespaces<|endoftext|>


<commit_before>/* RTcmix  - Copyright (C) 2004  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <rtcmix_types.h>
#include <PField.h>
#include <ugens.h>		// for warn, die

// Functions for creating LFO PFields.    -John Gibson, 11/20/04

extern int resetval;		// declared in src/rtcmix/minc_functions.c

extern "C" {
Handle maketable(const Arg args[], const int nargs); // defined in table.cpp
}

// --------------------------------------------------------- local utilities ---
static Handle
_createPFieldHandle(PField *pfield)
{
	Handle handle = (Handle) malloc(sizeof(struct _handle));
	handle->type = PFieldType;
	handle->ptr = (void *) pfield;
	return handle;
}

// Create an appropriate TablePField from a string description.
// We use ideal waveforms instead of building them up from harmonics.
// For square waves, this avoids the ripple that we'd get otherwise.

static TablePField *
_makewavetable(const char *wavetype)
{
	int nargs;
	Arg *mtargs;
	const int tabsize = 1000;

	if (strncmp(wavetype, "sine", 3) == 0) {
		nargs = 3;
		mtargs = new Arg[nargs];
		mtargs[0] = "wave";
		mtargs[1] = tabsize;
		mtargs[2] = 1.0;
	}
	else if (strncmp(wavetype, "sawup", 4) == 0) {
		nargs = 6;
		mtargs = new Arg[nargs];
		mtargs[0] = "linebrk";
		mtargs[1] = "nonorm";
		mtargs[2] = tabsize;
		mtargs[3] = -1.0;
		mtargs[4] = tabsize;
		mtargs[5] = 1.0;
	}
	else if (strncmp(wavetype, "sawdown", 3) == 0) {
		nargs = 6;
		mtargs = new Arg[nargs];
		mtargs[0] = "linebrk";
		mtargs[1] = "nonorm";
		mtargs[2] = tabsize;
		mtargs[3] = 1.0;
		mtargs[4] = tabsize;
		mtargs[5] = -1.0;
	}
	else if (strncmp(wavetype, "square", 3) == 0) {
		nargs = 10;
		mtargs = new Arg[nargs];
		mtargs[0] = "linebrk";
		mtargs[1] = "nonorm";
		mtargs[2] = tabsize;
		mtargs[3] = -1.0;
		mtargs[4] = tabsize >> 1;
		mtargs[5] = -1.0;
		mtargs[6] = 0.0;
		mtargs[7] = 1.0;
		mtargs[8] = tabsize >> 1;
		mtargs[9] = 1.0;
	}
	else if (strncmp(wavetype, "triangle", 3) == 0) {
		nargs = 8;
		mtargs = new Arg[nargs];
		mtargs[0] = "linebrk";
		mtargs[1] = "nonorm";
		mtargs[2] = tabsize;
		mtargs[3] = -1.0;
		mtargs[4] = tabsize >> 1;
		mtargs[5] = 1.0;
		mtargs[6] = tabsize >> 1;
		mtargs[7] = -1.0;
	}
	else {
		die("makeLFO", "Waveform string can be \"sine\", \"sawup\", \"sawdown\", "
						"\"square\" or \"triangle\"; or pass a table handle.");
		delete [] mtargs;
		return NULL;
	}

	Handle handle = maketable(mtargs, nargs);
	delete [] mtargs;

	return (TablePField *) handle->ptr;
}

// =============================================================================
// The remaining functions are public, callable from scripts.

extern "C" {
	Handle makeLFO(const Arg args[], const int nargs);
	Handle makerandom(const Arg args[], const int nargs);
}

typedef enum {
	kTruncate,
	kInterp1stOrder
} InterpType;

// ----------------------------------------------------------------- makeLFO ---
static Handle
_makeLFO_usage()
{
	die("makeLFO",
		"\n   usage: lfo = makeLFO(wave, [interp,] freq, amp)"
		"\nOR"
		"\n   usage: lfo = makeLFO(wave, [interp,] freq, min, max)\n");
	return NULL;
}

Handle
makeLFO(const Arg args[], const int nargs)
{
	if (nargs < 3)
		return _makeLFO_usage();

	TablePField *wavetablePF = (TablePField *) ((PField *) args[0]);
	if (wavetablePF == NULL || wavetablePF->values() < 2) {	// not a TablePField
		if (args[0].isType(StringType)) {
			wavetablePF = _makewavetable(args[0]);
			if (wavetablePF == NULL)
				return NULL;
		}
		else
			return _makeLFO_usage();
	}
	double *wavetable = (double *) *wavetablePF;
	int len = wavetablePF->values();

	InterpType interp = kInterp1stOrder;
	int index = 1;
	if (args[index].isType(StringType)) {
		if (args[index] == "nointerp")
			interp = kTruncate;
		else if (args[index] == "interp")
			interp = kInterp1stOrder;
		else {
			die("makeLFO", "Invalid string option \"%s\".",
													(const char *) args[index]);
			return NULL;
		}
		index++;
	}

	PField *freqpf = (PField *) args[index];
	if (freqpf == NULL) {
		if (args[index].isType(DoubleType))
			freqpf = new ConstPField((double) args[index]);
		else
			return _makeLFO_usage();
	}
	index++;

	PField *amppf = NULL;
	PField *minpf = NULL;
	PField *maxpf = NULL;
	if (nargs - index > 1) {		// min, max instead of amp
		minpf = (PField *) args[index];
		if (minpf == NULL) {
			if (args[index].isType(DoubleType))
				minpf = new ConstPField((double) args[index]);
			else
				return _makeLFO_usage();
		}
		index++;
		maxpf = (PField *) args[index];
		if (maxpf == NULL) {
			if (args[index].isType(DoubleType))
				maxpf = new ConstPField((double) args[index]);
			else
				return _makeLFO_usage();
		}
	}
	else {
		amppf = (PField *) args[index];
		if (amppf == NULL) {
			if (args[index].isType(DoubleType))
				amppf = new ConstPField((double) args[index]);
			else
				return _makeLFO_usage();
		}
	}

	PField *lfo;
	if (interp == kInterp1stOrder)
		lfo = new LFOPField(resetval, wavetable, len, freqpf);
	else // (interp == kTruncate)
		lfo = new LFOPField(resetval, wavetable, len, freqpf, LFOPField::Truncate);

	if (amppf != NULL)
		lfo = new MultPField(lfo, amppf);
	else
		lfo = new RangePField(lfo, minpf, maxpf);

	return _createPFieldHandle(lfo);
}

// -------------------------------------------------------------- makerandom ---
#include <Random.h>
#include <sys/time.h>

static Handle
_makerandom_usage()
{
	die("makerandom",
		"\n   usage: rand = makerandom(type, [interp,] freq, seed, min, max)"
		"\n");
	return NULL;
}

Handle
makerandom(const Arg args[], const int nargs)
{
	int type;
	if (args[0].isType(StringType)) {
		if (args[0] == "even" || args[0] == "linear")
			type = kLinearRandom;
		else if (args[0] == "low")
			type = kLowLinearRandom;
		else if (args[0] == "high")
			type = kHighLinearRandom;
		else if (args[0] == "triangle")
			type = kTriangleRandom;
		else if (args[0] == "gaussian")
			type = kGaussianRandom;
		else if (args[0] == "cauchy")
			type = kCauchyRandom;
		else if (args[0] == "prob")
			type = kProbRandom;
		else {
			die("makerandom", "Unsupported distribution type \"%s\".",
						  (const char *) args[0]);
			return NULL;
		}
	}
	else
		return _makerandom_usage();

	InterpType interp = kInterp1stOrder;
	int index = 1;
	if (args[index].isType(StringType)) {
		if (args[index] == "nointerp")
			interp = kTruncate;
		else if (args[index] == "interp")
			interp = kInterp1stOrder;
		else {
			die("makerandom", "Invalid string option \"%s\".",
													(const char *) args[index]);
			return NULL;
		}
		index++;
	}

	PField *freqpf = (PField *) args[index];
	if (freqpf == NULL) {
		if (args[index].isType(DoubleType))
			freqpf = new ConstPField((double) args[index]);
		else
			return _makeLFO_usage();
	}
	index++;

	int seed;
	if ((int) args[index] == 0) {
		struct timeval tv;
		gettimeofday(&tv, NULL);
		seed = (int) tv.tv_usec;
	}
	else
		seed = (int) args[index];
	index++;

	PField *minpf = (PField *) args[index];
	if (minpf == NULL) {
		if (args[index].isType(DoubleType))
			minpf = new ConstPField((double) args[index]);
		else
			return _makerandom_usage();
	}
	double min = minpf->doubleValue(0);
	index++;

	PField *midpf = NULL;
	if (type == kProbRandom) {
		midpf = (PField *) args[index];
		if (midpf == NULL) {
			if (args[index].isType(DoubleType))
				midpf = new ConstPField((double) args[index]);
			else
				return _makerandom_usage();
		}
		index++;
	}
	double mid = midpf ? midpf->doubleValue(0) : 0.0;

	PField *maxpf = (PField *) args[index];
	if (maxpf == NULL) {
		if (args[index].isType(DoubleType))
			maxpf = new ConstPField((double) args[index]);
		else
			return _makerandom_usage();
	}
	double max = maxpf->doubleValue(0);
	index++;

	PField *tightpf = NULL;
	if (type == kProbRandom) {
		tightpf = (PField *) args[index];
		if (tightpf == NULL) {
			if (args[index].isType(DoubleType))
				tightpf = new ConstPField((double) args[index]);
			else
				return _makerandom_usage();
		}
		index++;
	}
	double tight = tightpf ? tightpf->doubleValue(0) : 0.0;

	// check initial values
	if (min > max) {
		die("makerandom", "<min> must be less than or equal to <max>.");
		return NULL;
	}
	if (tight < 0.0) {
		die("makerandom", "<tight> must be zero or greater.");
		return NULL;
	}

	Random *gen;
	switch (type) {
		case kLinearRandom:
			gen = new LinearRandom(seed, min, max);
			break;
		case kLowLinearRandom:
			gen = new LowLinearRandom(seed, min, max);
			break;
		case kHighLinearRandom:
			gen = new HighLinearRandom(seed, min, max);
			break;
		case kTriangleRandom:
			gen = new TriangleRandom(seed, min, max);
			break;
		case kGaussianRandom:
			gen = new GaussianRandom(seed, min, max);
			break;
		case kCauchyRandom:
			gen = new CauchyRandom(seed, min, max);
			break;
		case kProbRandom:
			gen = new ProbRandom(seed, min, mid, max, tight);
			break;
		default:		// can't get here if type inited correctly above
			break;
	}

#ifdef NOTYET
	PField *rand = new RandomPField(resetval, type, gen, freqpf, minpf, midpf,
									maxpf, tightpf, (interp == kInterp1stOrder));

	return _createPFieldHandle(rand);
#else
   return NULL;
#endif
}

<commit_msg>Arg order and comment changes; arg index checks.<commit_after>/* RTcmix  - Copyright (C) 2004  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <rtcmix_types.h>
#include <PField.h>
#include <ugens.h>		// for warn, die

// Functions for creating LFO PFields.    -John Gibson, 11/20/04

extern int resetval;		// declared in src/rtcmix/minc_functions.c

extern "C" {
Handle maketable(const Arg args[], const int nargs); // defined in table.cpp
}

// --------------------------------------------------------- local utilities ---
static Handle
_createPFieldHandle(PField *pfield)
{
	Handle handle = (Handle) malloc(sizeof(struct _handle));
	handle->type = PFieldType;
	handle->ptr = (void *) pfield;
	return handle;
}

// Create an appropriate TablePField from a string description.
// We use ideal waveforms instead of building them up from harmonics.
// For square waves, this avoids the ripple that we'd get otherwise.

static TablePField *
_makewavetable(const char *wavetype)
{
	int nargs;
	Arg *mtargs;
	const int tabsize = 1000;

	if (strncmp(wavetype, "sine", 3) == 0) {
		nargs = 3;
		mtargs = new Arg[nargs];
		mtargs[0] = "wave";
		mtargs[1] = tabsize;
		mtargs[2] = 1.0;
	}
	else if (strncmp(wavetype, "sawup", 4) == 0) {
		nargs = 6;
		mtargs = new Arg[nargs];
		mtargs[0] = "linebrk";
		mtargs[1] = "nonorm";
		mtargs[2] = tabsize;
		mtargs[3] = -1.0;
		mtargs[4] = tabsize;
		mtargs[5] = 1.0;
	}
	else if (strncmp(wavetype, "sawdown", 3) == 0) {
		nargs = 6;
		mtargs = new Arg[nargs];
		mtargs[0] = "linebrk";
		mtargs[1] = "nonorm";
		mtargs[2] = tabsize;
		mtargs[3] = 1.0;
		mtargs[4] = tabsize;
		mtargs[5] = -1.0;
	}
	else if (strncmp(wavetype, "square", 3) == 0) {
		nargs = 10;
		mtargs = new Arg[nargs];
		mtargs[0] = "linebrk";
		mtargs[1] = "nonorm";
		mtargs[2] = tabsize;
		mtargs[3] = -1.0;
		mtargs[4] = tabsize >> 1;
		mtargs[5] = -1.0;
		mtargs[6] = 0.0;
		mtargs[7] = 1.0;
		mtargs[8] = tabsize >> 1;
		mtargs[9] = 1.0;
	}
	else if (strncmp(wavetype, "triangle", 3) == 0) {
		nargs = 8;
		mtargs = new Arg[nargs];
		mtargs[0] = "linebrk";
		mtargs[1] = "nonorm";
		mtargs[2] = tabsize;
		mtargs[3] = -1.0;
		mtargs[4] = tabsize >> 1;
		mtargs[5] = 1.0;
		mtargs[6] = tabsize >> 1;
		mtargs[7] = -1.0;
	}
	else {
		die("makeLFO", "Waveform string can be \"sine\", \"sawup\", \"sawdown\", "
						"\"square\" or \"triangle\"; or pass a table handle.");
		delete [] mtargs;
		return NULL;
	}

	Handle handle = maketable(mtargs, nargs);
	delete [] mtargs;

	return (TablePField *) handle->ptr;
}

// =============================================================================
// The remaining functions are public, callable from scripts.

extern "C" {
	Handle makeLFO(const Arg args[], const int nargs);
	Handle makerandom(const Arg args[], const int nargs);
}

typedef enum {
	kTruncate,
	kInterp1stOrder
} InterpType;

// ----------------------------------------------------------------- makeLFO ---
static Handle
_makeLFO_usage()
{
	die("makeLFO",
		"\n   usage: lfo = makeLFO(wave, [interp,] freq, amp)"
		"\nOR"
		"\n   usage: lfo = makeLFO(wave, [interp,] freq, min, max)\n");
	return NULL;
}

Handle
makeLFO(const Arg args[], const int nargs)
{
	if (nargs < 3)
		return _makeLFO_usage();

	TablePField *wavetablePF = (TablePField *) ((PField *) args[0]);
	if (wavetablePF == NULL || wavetablePF->values() < 2) {	// not a TablePField
		if (args[0].isType(StringType)) {
			wavetablePF = _makewavetable(args[0]);
			if (wavetablePF == NULL)
				return NULL;
		}
		else
			return _makeLFO_usage();
	}
	double *wavetable = (double *) *wavetablePF;
	int len = wavetablePF->values();

	InterpType interp = kInterp1stOrder;
	int index = 1;
	if (args[index].isType(StringType)) {
		if (args[index] == "nointerp")
			interp = kTruncate;
		else if (args[index] == "interp")
			interp = kInterp1stOrder;
		else {
			die("makeLFO", "Invalid string option \"%s\".",
													(const char *) args[index]);
			return NULL;
		}
		index++;
	}

	PField *freqpf = (PField *) args[index];
	if (freqpf == NULL) {
		if (args[index].isType(DoubleType))
			freqpf = new ConstPField((double) args[index]);
		else
			return _makeLFO_usage();
	}
	index++;
	if (index >= nargs)
		return _makeLFO_usage();

	PField *amppf = NULL;
	PField *minpf = NULL;
	PField *maxpf = NULL;
	if (nargs - index > 1) {		// min, max instead of amp
		minpf = (PField *) args[index];
		if (minpf == NULL) {
			if (args[index].isType(DoubleType))
				minpf = new ConstPField((double) args[index]);
			else
				return _makeLFO_usage();
		}
		index++;
		if (index >= nargs)
			return _makeLFO_usage();
		maxpf = (PField *) args[index];
		if (maxpf == NULL) {
			if (args[index].isType(DoubleType))
				maxpf = new ConstPField((double) args[index]);
			else
				return _makeLFO_usage();
		}
	}
	else {
		amppf = (PField *) args[index];
		if (amppf == NULL) {
			if (args[index].isType(DoubleType))
				amppf = new ConstPField((double) args[index]);
			else
				return _makeLFO_usage();
		}
	}

	PField *lfo;
	if (interp == kInterp1stOrder)
		lfo = new LFOPField(resetval, wavetable, len, freqpf);
	else // (interp == kTruncate)
		lfo = new LFOPField(resetval, wavetable, len, freqpf, LFOPField::Truncate);

	if (amppf != NULL)
		lfo = new MultPField(lfo, amppf);
	else
		lfo = new RangePField(lfo, minpf, maxpf);

	return _createPFieldHandle(lfo);
}

// -------------------------------------------------------------- makerandom ---
#include <Random.h>
#include <sys/time.h>

static Handle
_makerandom_usage()
{
	die("makerandom",
		"\n   usage: rand = makerandom(type, [interp,] freq, min, max[, seed])"
		"\n          where <type> is \"linear\", \"low\", \"high\", "
						"\"triangle\", \"gaussian\", \"cauchy\""
		"\nOR"
		"\n   usage: rand = makerandom(\"prob\", [interp,] freq, min, max, mid, "
						"tight[, seed])"
		"\n");
	return NULL;
}

Handle
makerandom(const Arg args[], const int nargs)
{
	if (nargs < 4)
		return _makerandom_usage();

	int type;
	if (args[0].isType(StringType)) {
		if (args[0] == "even" || args[0] == "linear")
			type = kLinearRandom;
		else if (args[0] == "low")
			type = kLowLinearRandom;
		else if (args[0] == "high")
			type = kHighLinearRandom;
		else if (args[0] == "triangle")
			type = kTriangleRandom;
		else if (args[0] == "gaussian")
			type = kGaussianRandom;
		else if (args[0] == "cauchy")
			type = kCauchyRandom;
		else if (args[0] == "prob")
			type = kProbRandom;
		else {
			die("makerandom", "Unsupported distribution type \"%s\".",
						  (const char *) args[0]);
			return NULL;
		}
	}
	else
		return _makerandom_usage();

	InterpType interp = kInterp1stOrder;
	int index = 1;
	if (args[index].isType(StringType)) {
		if (args[index] == "nointerp")
			interp = kTruncate;
		else if (args[index] == "interp")
			interp = kInterp1stOrder;
		else {
			die("makerandom", "Invalid string option \"%s\".",
													(const char *) args[index]);
			return NULL;
		}
		index++;
	}

	PField *freqpf = (PField *) args[index];
	if (freqpf == NULL) {
		if (args[index].isType(DoubleType))
			freqpf = new ConstPField((double) args[index]);
		else
			return _makerandom_usage();
	}
	index++;

	PField *minpf = (PField *) args[index];
	if (minpf == NULL) {
		if (args[index].isType(DoubleType))
			minpf = new ConstPField((double) args[index]);
		else
			return _makerandom_usage();
	}
	double min = minpf->doubleValue(0);
	index++;
	if (index >= nargs)
		return _makerandom_usage();

	PField *maxpf = (PField *) args[index];
	if (maxpf == NULL) {
		if (args[index].isType(DoubleType))
			maxpf = new ConstPField((double) args[index]);
		else
			return _makerandom_usage();
	}
	double max = maxpf->doubleValue(0);
	index++;

	PField *midpf = NULL;
	if (type == kProbRandom) {
		if (index >= nargs)
			return _makerandom_usage();
		midpf = (PField *) args[index];
		if (midpf == NULL) {
			if (args[index].isType(DoubleType))
				midpf = new ConstPField((double) args[index]);
			else
				return _makerandom_usage();
		}
		index++;
		if (index >= nargs)
			return _makerandom_usage();
	}
	double mid = midpf ? midpf->doubleValue(0) : 0.0;

	PField *tightpf = NULL;
	if (type == kProbRandom) {
		tightpf = (PField *) args[index];
		if (tightpf == NULL) {
			if (args[index].isType(DoubleType))
				tightpf = new ConstPField((double) args[index]);
			else
				return _makerandom_usage();
		}
		index++;
	}
	double tight = tightpf ? tightpf->doubleValue(0) : 0.0;

	int seed = 0;
	if (nargs - index > 1)		// explicit seed
		seed = (int) args[index];
	if (seed == 0) {
		struct timeval tv;
		gettimeofday(&tv, NULL);
		seed = (int) tv.tv_usec;
	}

	// check initial values
	if (min > max) {
		die("makerandom", "<min> must be less than or equal to <max>.");
		return NULL;
	}
	if (tight < 0.0) {
		die("makerandom", "<tight> must be zero or greater.");
		return NULL;
	}

	Random *gen;
	switch (type) {
		case kLinearRandom:
			gen = new LinearRandom(seed, min, max);
			break;
		case kLowLinearRandom:
			gen = new LowLinearRandom(seed, min, max);
			break;
		case kHighLinearRandom:
			gen = new HighLinearRandom(seed, min, max);
			break;
		case kTriangleRandom:
			gen = new TriangleRandom(seed, min, max);
			break;
		case kGaussianRandom:
			gen = new GaussianRandom(seed, min, max);
			break;
		case kCauchyRandom:
			gen = new CauchyRandom(seed, min, max);
			break;
		case kProbRandom:
			gen = new ProbRandom(seed, min, mid, max, tight);
			break;
		default:		// can't get here if type inited correctly above
			break;
	}

#ifdef NOTYET
	PField *rand = new RandomPField(resetval, type, gen, freqpf, minpf, midpf,
									maxpf, tightpf, (interp == kInterp1stOrder));

	return _createPFieldHandle(rand);
#else
   return NULL;
#endif
}

<|endoftext|>


<commit_before>#include <qfile.h>

#include <kapp.h>
#include <dcopclient.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <klocale.h>
#include <kdebug.h>
#include <kmessagebox.h>

#include "modem.h"
#include "kandy.h"
#include "mobilemain.h"
#include "commandscheduler.h"
#include "kandyprefs.h"

static const char *description =
    I18N_NOOP("Communicating with your mobile phone.");

static const char *version = "0.2";

static KCmdLineOptions options[] =
{
   { "terminal", I18N_NOOP("Show terminal window."), 0 },
   { "mobilegui", I18N_NOOP("Show mobile GUI."), 0 },
   { "nogui", I18N_NOOP("Don't show GUI."), 0 },
   { "+[profile]", I18N_NOOP("Filename of command profile file."), 0 },
   { 0, 0, 0 } // End of options.
};

void initModem(Modem *modem)
{
  kdDebug() << "Opening serial Device: "
            << KandyPrefs::instance()->mSerialDevice
            << endl;

  modem->setDevice(KandyPrefs::instance()->mSerialDevice);
  modem->setSpeed(19200);
  modem->setData(8);
  modem->setParity('N');
  modem->setStop(1);

#if 0
  if (!modem->dsrOn()) {
    KMessageBox::sorry(this, i18n("Modem is off."), i18n("Modem Error"));
    modem->close();
    return;
  }
  if (!modem->ctsOn()) {
    KMessageBox::sorry(this, i18n("Modem is busy."), i18n("Modem Error"));
    modem->close();
    return;
  }
#endif

#if 0
  modem->writeLine("");
  usleep(250000);
  modem->flush();
  modem->writeLine("ATZ");
#endif
}

int main(int argc, char **argv)
{
  KAboutData about("kandy", I18N_NOOP("Kandy"), version, description,
  KAboutData::License_GPL, "(C) 2001 Cornelius Schumacher");
  about.addAuthor( "Cornelius Schumacher", 0, "schumacher@kde.org" );
  KCmdLineArgs::init(argc,argv,&about);
  KCmdLineArgs::addCmdLineOptions(options);

  KApplication app;
  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();

  // register ourselves as a dcop client
  app.dcopClient()->registerAs(app.name(),false);

  Modem *modem = new Modem;
  initModem(modem);
  CommandScheduler *scheduler = new CommandScheduler(modem);

  // see if we are starting with session management
  if (app.isRestored()) {
    // TODO: do session management
//      RESTORE(Kandy)
  } else
  {
    // no session.. just start up normally
    Kandy *k = new Kandy(scheduler);

    MobileMain *m = new MobileMain(scheduler);
    if (!args->isSet("gui")) {
    } else {
      if (KandyPrefs::instance()->mStartupTerminalWin ||
          args->isSet("terminal")) {
        k->show();
      }
      if (KandyPrefs::instance()->mStartupMobileWin ||
          args->isSet("mobilegui")) {
        m->show();
      }
    }

    if (args->count() == 1) {
      k->load(QFile::decodeName(args->arg(0)));
    } else if (args->count() > 1) {
      args->usage();
    }

    args->clear();

    QObject::connect(k,SIGNAL(showMobileWin()),m,SLOT(show()));
    QObject::connect(m,SIGNAL(showTerminalWin()),k,SLOT(show()));
    QObject::connect(m,SIGNAL(showPreferencesWin()),
                     k,SLOT(optionsPreferences()));
    QObject::connect(m,SIGNAL(modemConnect()),k,SLOT(modemConnect()));
    QObject::connect(m,SIGNAL(modemDisconnect()),k,SLOT(modemDisconnect()));
    QObject::connect(k,SIGNAL(connectStateChanged(bool)),
                     m,SLOT(setConnected(bool)));

    if (KandyPrefs::instance()->mStartupModem) k->modemConnect();
  }

  return app.exec();
}
<commit_msg>Adding home page to about data.<commit_after>#include <qfile.h>

#include <kapp.h>
#include <dcopclient.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <klocale.h>
#include <kdebug.h>
#include <kmessagebox.h>

#include "modem.h"
#include "kandy.h"
#include "mobilemain.h"
#include "commandscheduler.h"
#include "kandyprefs.h"

static const char *description =
    I18N_NOOP("Communicating with your mobile phone.");

static const char *version = "0.2";

static KCmdLineOptions options[] =
{
   { "terminal", I18N_NOOP("Show terminal window."), 0 },
   { "mobilegui", I18N_NOOP("Show mobile GUI."), 0 },
   { "nogui", I18N_NOOP("Don't show GUI."), 0 },
   { "+[profile]", I18N_NOOP("Filename of command profile file."), 0 },
   { 0, 0, 0 } // End of options.
};

void initModem(Modem *modem)
{
  kdDebug() << "Opening serial Device: "
            << KandyPrefs::instance()->mSerialDevice
            << endl;

  modem->setDevice(KandyPrefs::instance()->mSerialDevice);
  modem->setSpeed(19200);
  modem->setData(8);
  modem->setParity('N');
  modem->setStop(1);

#if 0
  if (!modem->dsrOn()) {
    KMessageBox::sorry(this, i18n("Modem is off."), i18n("Modem Error"));
    modem->close();
    return;
  }
  if (!modem->ctsOn()) {
    KMessageBox::sorry(this, i18n("Modem is busy."), i18n("Modem Error"));
    modem->close();
    return;
  }
#endif

#if 0
  modem->writeLine("");
  usleep(250000);
  modem->flush();
  modem->writeLine("ATZ");
#endif
}

int main(int argc, char **argv)
{
  KAboutData about("kandy", I18N_NOOP("Kandy"), version, description,
                   KAboutData::License_GPL, "(C) 2001 Cornelius Schumacher",0,
                   "http://devel-home.kde.org/~kandy");
  about.addAuthor( "Cornelius Schumacher", 0, "schumacher@kde.org" );
  KCmdLineArgs::init(argc,argv,&about);
  KCmdLineArgs::addCmdLineOptions(options);

  KApplication app;
  KCmdLineArgs *args = KCmdLineArgs::parsedArgs();

  // register ourselves as a dcop client
  app.dcopClient()->registerAs(app.name(),false);

  Modem *modem = new Modem;
  initModem(modem);
  CommandScheduler *scheduler = new CommandScheduler(modem);

  // see if we are starting with session management
  if (app.isRestored()) {
    // TODO: do session management
//      RESTORE(Kandy)
  } else
  {
    // no session.. just start up normally
    Kandy *k = new Kandy(scheduler);

    MobileMain *m = new MobileMain(scheduler);
    if (!args->isSet("gui")) {
    } else {
      if (KandyPrefs::instance()->mStartupTerminalWin ||
          args->isSet("terminal")) {
        k->show();
      }
      if (KandyPrefs::instance()->mStartupMobileWin ||
          args->isSet("mobilegui")) {
        m->show();
      }
    }

    if (args->count() == 1) {
      k->load(QFile::decodeName(args->arg(0)));
    } else if (args->count() > 1) {
      args->usage();
    }

    args->clear();

    QObject::connect(k,SIGNAL(showMobileWin()),m,SLOT(show()));
    QObject::connect(m,SIGNAL(showTerminalWin()),k,SLOT(show()));
    QObject::connect(m,SIGNAL(showPreferencesWin()),
                     k,SLOT(optionsPreferences()));
    QObject::connect(m,SIGNAL(modemConnect()),k,SLOT(modemConnect()));
    QObject::connect(m,SIGNAL(modemDisconnect()),k,SLOT(modemDisconnect()));
    QObject::connect(k,SIGNAL(connectStateChanged(bool)),
                     m,SLOT(setConnected(bool)));

    if (KandyPrefs::instance()->mStartupModem) k->modemConnect();
  }

  return app.exec();
}
<|endoftext|>


<commit_before>#pragma once
/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

#ifndef _QIMESSAGING_TYPE_HPP_
#define _QIMESSAGING_TYPE_HPP_

#include <typeinfo>
#include <boost/preprocessor.hpp>
#include <qimessaging/datastream.hpp>
#include <qimessaging/details/dynamicvalue.hpp>

namespace qi{

/** Interface for all the operations we need on any type:
 *
 *  - cloning/destruction in clone() and destroy()
 *  - type conversion is made by going through the generic container
 *    GenericValue, using the toValue() and fromValue() functions,
 *  - Serialization through serialize() and deserialize() to transmit
 *    the value through some kind of pipe.
 *
 * Our aim is to transport arbitrary values through:
 *  - synchronous calls: Nothing to do, values are just transported and
      converted.
 *  - asynchronous call/thread change: Values are copied.
 *  - process change: Values are serialized.
 *
 */
class QIMESSAGING_API Type
{
public:
  virtual const std::type_info& info() =0;
  const char* infoString() { return info().name();} // for easy gdb access
  /// @return the serialization signature used by this type.
  virtual std::string signature()=0;

  // Initialize and return a new storage, from nothing or a T*
  virtual void* initializeStorage(void* ptr=0)=0;
  // Get pointer to type from pointer to storage
  // No reference to avoid the case where the compiler makes a copy on the stack
  virtual void* ptrFromStorage(void**)=0;

  virtual void* clone(void*)=0;
  virtual void destroy(void*)=0;

  virtual bool  toValue(const void*, qi::detail::DynamicValue&)=0;
  virtual void* fromValue(const qi::detail::DynamicValue&)=0;

  // Default impl does toValue.serialize()
  virtual void  serialize(ODataStream& s, const void*)=0;
  // Default impl does deserialize(GenericValue&) then fromValue
  virtual void* deserialize(IDataStream& s)=0;

  enum Kind
  {
    Void,
    Int,
    Float,
    String,
    List,
    Map,
    Object,
    Unknown,
  };
  virtual Kind kind() const;

  /* When someone makes a call with arguments that do not match the
   * target signature (ex: int vs float), we want to handle it.
   * For this, given the known correct signature S and known incorrect
   * GenericValue v, we want to be able to obtain a new Type T that
   * serializes with type S, and then try to convert o into type T.
   *
   * For this we need a map<Signature, Type> that we will feed with
   * known types.
   *
   */
  typedef std::map<std::string, Type*> TypeSignatureMap;
  static TypeSignatureMap& typeSignatureMap()
  {
    static TypeSignatureMap res;
    return res;
  }

  static Type* getCompatibleTypeWithSignature(const std::string& sig)
  {
    TypeSignatureMap::iterator i = typeSignatureMap().find(sig);
    if (i == typeSignatureMap().end())
      return 0;
    else
      return i->second;
  }

  static bool registerCompatibleType(const std::string& sig,
    Type* mt)
  {
    typeSignatureMap()[sig] = mt;
    return true;
  }

  #define QI_REGISTER_MAPPING(sig, type) \
  static bool BOOST_PP_CAT(_qireg_map_ , __LINE__) = ::qi::Type::registerCompatibleType(sig, \
    ::qi::typeOf<type>());
};

namespace detail {
  template<typename T> struct TypeFactory
  {
    void* operator()() { return new T();}
  };
};
#define QI_TYPE_NOT_CONSTRUCTIBLE(T) \
namespace qi { namespace detail { \
template<> struct TypeFactory<T> { void* operator()() { return 0;}};}}
/** Meta-type specialization.
 *  Use the aspect pattern, make a class per feature group
 *  (Clone, GenericValue, Serialize)
 *
 */

/// Access API that stores a T* in storage
template<typename T> class TypeDefaultAccess
{
public:
  typedef T type;
  static void* ptrFromStorage(void** storage)
  {
    return *storage;
  }
  static void* initializeStorage(void* ptr=0)
  {
    if (ptr)
      return ptr;
    void* res = detail::TypeFactory<T>()();
    if (!res)
      qiLogError("qi.meta") << "initializeStorage error on " << typeid(T).name();
    return res;
  }
};

/// Access api that stores T in storage
template<typename T> class TypeDirectAccess
{
public:
  typedef T type;
  static void* ptrFromStorage(void** storage)
  {
    return storage;
  }
  static void* initializeStorage(void* ptr=0)
  {
    if (ptr)
    {
      T val = *(T*)ptr;
      return *(void**)&val;
    }
    else
      return 0;
  }
};

template<typename A> class TypeDefaultClone
{
public:
  typedef typename A::type type;
  static void* clone(void* src)
  {
    const type* ptr = (const type*)A::ptrFromStorage(&src);
    void* res = A::initializeStorage();
    type* tres = (type*)A::ptrFromStorage(&res);
    *tres = *ptr;
    return res;
  }

  static void destroy(void* src)
  {
    type* ptr = (type*)A::ptrFromStorage(&src);
    delete ptr;
  }
};

template<typename A> class TypeNoClone
{
public:
  static void* clone(void* src)
  {
    return src;
  }

  static void destroy(void* ptr)
  {
    /* Assume a TypeNoClone is not serializable
     * So it cannot have been allocated by us.
     * So the destroy comes after a clone->ignore it
     */
  }
};

template<typename A>class TypeDefaultValue
{
public:
  typedef typename A::type type;
  static bool toValue(const void* src, qi::detail::DynamicValue& val)
  {
    const type* ptr = (const type*)A::ptrFromStorage((void**)&src);
    detail::DynamicValueConverter<type>::writeDynamicValue(*ptr, val);
    return true;
  }

  static void* fromValue(const qi::detail::DynamicValue& val)
  {
    void* storage;
    storage = A::initializeStorage();
    void* vptr = A::ptrFromStorage(&storage);
    qiLogDebug("wtf") << storage << ' ' << &storage << ' ' << vptr;
    detail::DynamicValueConverter<type>::readDynamicValue(val, *(type*)vptr);
    return storage;
  }
};

template<typename A>class TypeNoValue
{
public:
  typedef typename A::type type;
  static bool toValue(const void* ptr, qi::detail::DynamicValue& val)
  {
    qiLogWarning("qi.type") << "toValue not implemented for type " << typeid(type).name();
    return false;
  }

  static void* fromValue(const qi::detail::DynamicValue& val)
  {
    qiLogWarning("qi.type") << "fromValue not implemented for type " << typeid(type).name();
    return 0; // We may not have a default constructor
  }
};

template<typename A> class TypeDefaultSerialize
{
public:
  typedef typename A::type type;
  static void  serialize(ODataStream& s, const void* src)
  {
    const type* ptr = (const type*)A::ptrFromStorage((void**)&src);
    s << *ptr;
  }

  static void* deserialize(IDataStream& s)
  {
    void* storage = A::initializeStorage();
    type* ptr = (type*)A::ptrFromStorage(&storage);
    s >> *ptr;
    return storage;
  }
  static std::string signature()
  {
    return signatureFromType<type>::value();
  }
};

template<typename T> class TypeNoSerialize
{
public:
  static void serialize(ODataStream& s, const void* ptr)
  {
    qiLogWarning("qi.meta") << "serialize not implemented for " << typeid(T).name();
  }

  static void* deserialize(IDataStream& s)
  {
    qiLogWarning("qi.meta") << "deserialize not implemented for " << typeid(T).name();
    return 0;
  }
 static  std::string signature()
  {
    std::string res;
    res += (char)Signature::Type_Unknown;
    return res;
  }
};

/* TypeImpl implementation that bounces to the various aspect
 * subclasses.
 *
 * That way we can split the various aspects in different classes
 * for better reuse, without the cost of a second virtual call.
 */
template<typename T, typename Access    = TypeDefaultAccess<T>
                   , typename Cloner    = TypeDefaultClone<Access>
                   , typename Value     = TypeNoValue<Access>
                   , typename Serialize = TypeNoSerialize<Access>
         > class DefaultTypeImpl
: public Cloner
, public Value
, public Serialize
, public virtual Type
{
  virtual void* initializeStorage(void* ptr=0)
  {
    return Access::initializeStorage(ptr);
  }

  virtual void* ptrFromStorage(void** storage)
  {
    return Access::ptrFromStorage(storage);
  }

  virtual const std::type_info& info()
  {
    return typeid(T);
  }

  virtual void* clone(void* src)
  {
    return Cloner::clone(src);
  }

  virtual void destroy(void* ptr)
  {
    Cloner::destroy(ptr);
  }

  virtual bool toValue(const void* ptr, qi::detail::DynamicValue& val)
  {
    return Value::toValue(ptr, val);
  }

  virtual void* fromValue(const qi::detail::DynamicValue& val)
  {
    return Value::fromValue(val);
  }

  virtual std::string signature()
  {
    return Serialize::signature();
  }

  virtual void  serialize(ODataStream& s, const void* ptr)
  {
    Serialize::serialize(s, ptr);
  }

  virtual void* deserialize(IDataStream& s)
  {
    return Serialize::deserialize(s);
  }
};

/* Type "factory". Specialize this class to provide a custom
 * Type for a given type.
 */
template<typename T> class TypeImpl: public virtual DefaultTypeImpl<T>
{
};

/// Declare a type that is convertible to GenericValue, and serializable
#define QI_TYPE_CONVERTIBLE_SERIALIZABLE(T)  \
namespace qi {                                   \
template<> class TypeImpl<T>:                \
  public DefaultTypeImpl<T,                  \
    TypeDefaultAccess<T>,                    \
    TypeDefaultClone<TypeDefaultAccess<T> >, \
    TypeDefaultValue<TypeDefaultAccess<T> >,  \
    TypeDefaultSerialize<TypeDefaultAccess<T> >  \
  >{}; }

/** Declare that a type is not convertible to GenericValue.
 *  Must be called outside any namespace.
 */
#define QI_TYPE_SERIALIZABLE(T)              \
namespace qi {                                   \
template<> class TypeImpl<T>:                \
  public DefaultTypeImpl<T,                  \
    TypeDefaultAccess<T>,                    \
    TypeDefaultClone<TypeDefaultAccess<T> >, \
    TypeNoValue<TypeDefaultAccess<T> >,       \
    TypeDefaultSerialize<TypeDefaultAccess<T> >   \
  >{}; }

/// Declare that a type has no metatype and cannot be used in a Value
#define QI_NO_TYPE(T) namespace qi {template<> class TypeImpl<T> {};}

/// Declare that a type with default TypeImpl is not clonable
#define QI_TYPE_NOT_CLONABLE(T) \
namespace qi {    \
  template<> struct TypeDefaultClone<TypeDefaultAccess<T> >: public TypeNoClone<TypeDefaultAccess<T> >{}; \
}

/// Type factory getter. All other type access mechanism bounce here
QIMESSAGING_API Type*  getType(const std::type_info& type);
/// Type factory setter
QIMESSAGING_API bool registerType(const std::type_info& typeId, Type* type);

/** Get type from a type. Will return a static TypeImpl<T> if T is not registered
 */
template<typename T> Type* typeOf();

/// Get type from a value. No need to delete the result
template<typename T> Type* typeOf(const T& v)
{
  return typeOf<T>();
}

}

QI_TYPE_SERIALIZABLE(Buffer);

#include <qimessaging/details/type.hxx>

#endif  // _QIMESSAGING_TYPE_HPP_
<commit_msg>Type: DefaultTypeImpl: provide access to sub-operations classes to bypass virtual call when possible.<commit_after>#pragma once
/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

#ifndef _QIMESSAGING_TYPE_HPP_
#define _QIMESSAGING_TYPE_HPP_

#include <typeinfo>
#include <boost/preprocessor.hpp>
#include <qimessaging/datastream.hpp>
#include <qimessaging/details/dynamicvalue.hpp>

namespace qi{

/** Interface for all the operations we need on any type:
 *
 *  - cloning/destruction in clone() and destroy()
 *  - type conversion is made by going through the generic container
 *    GenericValue, using the toValue() and fromValue() functions,
 *  - Serialization through serialize() and deserialize() to transmit
 *    the value through some kind of pipe.
 *
 * Our aim is to transport arbitrary values through:
 *  - synchronous calls: Nothing to do, values are just transported and
      converted.
 *  - asynchronous call/thread change: Values are copied.
 *  - process change: Values are serialized.
 *
 */
class QIMESSAGING_API Type
{
public:
  virtual const std::type_info& info() =0;
  const char* infoString() { return info().name();} // for easy gdb access
  /// @return the serialization signature used by this type.
  virtual std::string signature()=0;

  // Initialize and return a new storage, from nothing or a T*
  virtual void* initializeStorage(void* ptr=0)=0;
  // Get pointer to type from pointer to storage
  // No reference to avoid the case where the compiler makes a copy on the stack
  virtual void* ptrFromStorage(void**)=0;

  virtual void* clone(void*)=0;
  virtual void destroy(void*)=0;

  virtual bool  toValue(const void*, qi::detail::DynamicValue&)=0;
  virtual void* fromValue(const qi::detail::DynamicValue&)=0;

  // Default impl does toValue.serialize()
  virtual void  serialize(ODataStream& s, const void*)=0;
  // Default impl does deserialize(GenericValue&) then fromValue
  virtual void* deserialize(IDataStream& s)=0;

  enum Kind
  {
    Void,
    Int,
    Float,
    String,
    List,
    Map,
    Object,
    Unknown,
  };
  virtual Kind kind() const;

  /* When someone makes a call with arguments that do not match the
   * target signature (ex: int vs float), we want to handle it.
   * For this, given the known correct signature S and known incorrect
   * GenericValue v, we want to be able to obtain a new Type T that
   * serializes with type S, and then try to convert o into type T.
   *
   * For this we need a map<Signature, Type> that we will feed with
   * known types.
   *
   */
  typedef std::map<std::string, Type*> TypeSignatureMap;
  static TypeSignatureMap& typeSignatureMap()
  {
    static TypeSignatureMap res;
    return res;
  }

  static Type* getCompatibleTypeWithSignature(const std::string& sig)
  {
    TypeSignatureMap::iterator i = typeSignatureMap().find(sig);
    if (i == typeSignatureMap().end())
      return 0;
    else
      return i->second;
  }

  static bool registerCompatibleType(const std::string& sig,
    Type* mt)
  {
    typeSignatureMap()[sig] = mt;
    return true;
  }

  #define QI_REGISTER_MAPPING(sig, type) \
  static bool BOOST_PP_CAT(_qireg_map_ , __LINE__) = ::qi::Type::registerCompatibleType(sig, \
    ::qi::typeOf<type>());
};

namespace detail {
  template<typename T> struct TypeFactory
  {
    void* operator()() { return new T();}
  };
};
#define QI_TYPE_NOT_CONSTRUCTIBLE(T) \
namespace qi { namespace detail { \
template<> struct TypeFactory<T> { void* operator()() { return 0;}};}}
/** Meta-type specialization.
 *  Use the aspect pattern, make a class per feature group
 *  (Clone, GenericValue, Serialize)
 *
 */

/// Access API that stores a T* in storage
template<typename T> class TypeDefaultAccess
{
public:
  typedef T type;
  static void* ptrFromStorage(void** storage)
  {
    return *storage;
  }
  static void* initializeStorage(void* ptr=0)
  {
    if (ptr)
      return ptr;
    void* res = detail::TypeFactory<T>()();
    if (!res)
      qiLogError("qi.meta") << "initializeStorage error on " << typeid(T).name();
    return res;
  }
};

/// Access api that stores T in storage
template<typename T> class TypeDirectAccess
{
public:
  typedef T type;
  static void* ptrFromStorage(void** storage)
  {
    return storage;
  }
  static void* initializeStorage(void* ptr=0)
  {
    if (ptr)
    {
      T val = *(T*)ptr;
      return *(void**)&val;
    }
    else
      return 0;
  }
};

template<typename A> class TypeDefaultClone
{
public:
  typedef typename A::type type;
  static void* clone(void* src)
  {
    const type* ptr = (const type*)A::ptrFromStorage(&src);
    void* res = A::initializeStorage();
    type* tres = (type*)A::ptrFromStorage(&res);
    *tres = *ptr;
    return res;
  }

  static void destroy(void* src)
  {
    type* ptr = (type*)A::ptrFromStorage(&src);
    delete ptr;
  }
};

template<typename A> class TypeNoClone
{
public:
  static void* clone(void* src)
  {
    return src;
  }

  static void destroy(void* ptr)
  {
    /* Assume a TypeNoClone is not serializable
     * So it cannot have been allocated by us.
     * So the destroy comes after a clone->ignore it
     */
  }
};

template<typename A>class TypeDefaultValue
{
public:
  typedef typename A::type type;
  static bool toValue(const void* src, qi::detail::DynamicValue& val)
  {
    const type* ptr = (const type*)A::ptrFromStorage((void**)&src);
    detail::DynamicValueConverter<type>::writeDynamicValue(*ptr, val);
    return true;
  }

  static void* fromValue(const qi::detail::DynamicValue& val)
  {
    void* storage;
    storage = A::initializeStorage();
    void* vptr = A::ptrFromStorage(&storage);
    qiLogDebug("wtf") << storage << ' ' << &storage << ' ' << vptr;
    detail::DynamicValueConverter<type>::readDynamicValue(val, *(type*)vptr);
    return storage;
  }
};

template<typename A>class TypeNoValue
{
public:
  typedef typename A::type type;
  static bool toValue(const void* ptr, qi::detail::DynamicValue& val)
  {
    qiLogWarning("qi.type") << "toValue not implemented for type " << typeid(type).name();
    return false;
  }

  static void* fromValue(const qi::detail::DynamicValue& val)
  {
    qiLogWarning("qi.type") << "fromValue not implemented for type " << typeid(type).name();
    return 0; // We may not have a default constructor
  }
};

template<typename A> class TypeDefaultSerialize
{
public:
  typedef typename A::type type;
  static void  serialize(ODataStream& s, const void* src)
  {
    const type* ptr = (const type*)A::ptrFromStorage((void**)&src);
    s << *ptr;
  }

  static void* deserialize(IDataStream& s)
  {
    void* storage = A::initializeStorage();
    type* ptr = (type*)A::ptrFromStorage(&storage);
    s >> *ptr;
    return storage;
  }
  static std::string signature()
  {
    return signatureFromType<type>::value();
  }
};

template<typename T> class TypeNoSerialize
{
public:
  static void serialize(ODataStream& s, const void* ptr)
  {
    qiLogWarning("qi.meta") << "serialize not implemented for " << typeid(T).name();
  }

  static void* deserialize(IDataStream& s)
  {
    qiLogWarning("qi.meta") << "deserialize not implemented for " << typeid(T).name();
    return 0;
  }
 static  std::string signature()
  {
    std::string res;
    res += (char)Signature::Type_Unknown;
    return res;
  }
};

/* TypeImpl implementation that bounces to the various aspect
 * subclasses.
 *
 * That way we can split the various aspects in different classes
 * for better reuse, without the cost of a second virtual call.
 */
template<typename T, typename _Access    = TypeDefaultAccess<T>
                   , typename _Cloner    = TypeDefaultClone<_Access>
                   , typename _Value     = TypeNoValue<_Access>
                   , typename _Serialize = TypeNoSerialize<_Access>
         > class DefaultTypeImpl
: public _Cloner
, public _Value
, public _Serialize
, public virtual Type
{
public:
  typedef _Access Access;
  typedef _Cloner Cloner;
  typedef _Value  Value;
  typedef _Serialize Serialize;
  virtual void* initializeStorage(void* ptr=0)
  {
    return Access::initializeStorage(ptr);
  }

  virtual void* ptrFromStorage(void** storage)
  {
    return Access::ptrFromStorage(storage);
  }

  virtual const std::type_info& info()
  {
    return typeid(T);
  }

  virtual void* clone(void* src)
  {
    return Cloner::clone(src);
  }

  virtual void destroy(void* ptr)
  {
    Cloner::destroy(ptr);
  }

  virtual bool toValue(const void* ptr, qi::detail::DynamicValue& val)
  {
    return Value::toValue(ptr, val);
  }

  virtual void* fromValue(const qi::detail::DynamicValue& val)
  {
    return Value::fromValue(val);
  }

  virtual std::string signature()
  {
    return Serialize::signature();
  }

  virtual void  serialize(ODataStream& s, const void* ptr)
  {
    Serialize::serialize(s, ptr);
  }

  virtual void* deserialize(IDataStream& s)
  {
    return Serialize::deserialize(s);
  }
};

/* Type "factory". Specialize this class to provide a custom
 * Type for a given type.
 */
template<typename T> class TypeImpl: public virtual DefaultTypeImpl<T>
{
};

/// Declare a type that is convertible to GenericValue, and serializable
#define QI_TYPE_CONVERTIBLE_SERIALIZABLE(T)  \
namespace qi {                                   \
template<> class TypeImpl<T>:                \
  public DefaultTypeImpl<T,                  \
    TypeDefaultAccess<T>,                    \
    TypeDefaultClone<TypeDefaultAccess<T> >, \
    TypeDefaultValue<TypeDefaultAccess<T> >,  \
    TypeDefaultSerialize<TypeDefaultAccess<T> >  \
  >{}; }

/** Declare that a type is not convertible to GenericValue.
 *  Must be called outside any namespace.
 */
#define QI_TYPE_SERIALIZABLE(T)              \
namespace qi {                                   \
template<> class TypeImpl<T>:                \
  public DefaultTypeImpl<T,                  \
    TypeDefaultAccess<T>,                    \
    TypeDefaultClone<TypeDefaultAccess<T> >, \
    TypeNoValue<TypeDefaultAccess<T> >,       \
    TypeDefaultSerialize<TypeDefaultAccess<T> >   \
  >{}; }

/// Declare that a type has no metatype and cannot be used in a Value
#define QI_NO_TYPE(T) namespace qi {template<> class TypeImpl<T> {};}

/// Declare that a type with default TypeImpl is not clonable
#define QI_TYPE_NOT_CLONABLE(T) \
namespace qi {    \
  template<> struct TypeDefaultClone<TypeDefaultAccess<T> >: public TypeNoClone<TypeDefaultAccess<T> >{}; \
}

/// Type factory getter. All other type access mechanism bounce here
QIMESSAGING_API Type*  getType(const std::type_info& type);
/// Type factory setter
QIMESSAGING_API bool registerType(const std::type_info& typeId, Type* type);

/** Get type from a type. Will return a static TypeImpl<T> if T is not registered
 */
template<typename T> Type* typeOf();

/// Get type from a value. No need to delete the result
template<typename T> Type* typeOf(const T& v)
{
  return typeOf<T>();
}

}

QI_TYPE_SERIALIZABLE(Buffer);

#include <qimessaging/details/type.hxx>

#endif  // _QIMESSAGING_TYPE_HPP_
<|endoftext|>