<commit_before>/*
 * Copyright 2011-2013 Esrille Inc.
 *
 * 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 "CSSImportRuleImp.h"

#include <boost/bind.hpp>
#include <boost/version.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>

#include "DocumentImp.h"
#include "WindowImp.h"

#include "CSSInputStream.h"
#include "CSSParser.h"
#include "CSSStyleSheetImp.h"

#include "http/HTTPRequest.h"

#include "Test.util.h"

namespace org
{
namespace w3c
{
namespace dom
{
namespace bootstrap
{

using namespace css;

CSSImportRuleImp::CSSImportRuleImp(const std::u16string& href) :
    href(href),
    mediaList(MediaListImp::All),
    request(0),
    styleSheet(0)
{
}

CSSImportRuleImp::~CSSImportRuleImp()
{
    delete request;
}

// CSSRule
unsigned short CSSImportRuleImp::getType()
{
    return CSSRule::IMPORT_RULE;
}

std::u16string CSSImportRuleImp::getCssText()
{
    std::u16string text = u"@import url(" + href + u")";
    std::u16string media = mediaList.getMediaText();
    if (!media.empty())
        text += u" " + media;
    return text;
}

// CSSImportRule
std::u16string CSSImportRuleImp::getHref()
{
    return href;
}

stylesheets::MediaList CSSImportRuleImp::getMedia()
{
    return &mediaList;
}

void CSSImportRuleImp::setMedia(const std::u16string& media)
{
    mediaList.setMediaText(media);
}

css::CSSStyleSheet CSSImportRuleImp::getStyleSheet()
{
    if (!styleSheet && !href.empty() && !request) {  // TODO: deal with ins. mem
        request = new(std::nothrow) HttpRequest(document->getDocumentURI());
        if (request) {
            request->open(u"GET", href);
            request->setHandler(boost::bind(&CSSImportRuleImp::notify, this));
            document->incrementLoadEventDelayCount();
            request->send();
        }
    }
    return styleSheet;
}

void CSSImportRuleImp::notify()
{
    if (request->getStatus() == 200) {
#if 104400 <= BOOST_VERSION
        boost::iostreams::stream<boost::iostreams::file_descriptor_source> stream(request->getContentDescriptor(), boost::iostreams::never_close_handle);
#else
        boost::iostreams::stream<boost::iostreams::file_descriptor_source> stream(request->getContentDescriptor(), false);
#endif
        CSSParser parser;
        CSSInputStream cssStream(stream, request->getResponseMessage().getContentCharset(), utfconv(document->getCharacterSet()));
        styleSheet = parser.parse(document, cssStream);
        if (auto imp = dynamic_cast<CSSStyleSheetImp*>(styleSheet.self()))
            imp->setParentStyleSheet(getParentStyleSheet());
        if (4 <= getLogLevel())
            dumpStyleSheet(std::cerr, styleSheet.self());
    }
    document->decrementLoadEventDelayCount();

    if (WindowImp* view = document->getDefaultWindow())
        view->setFlags(1);
}

}
}
}
}
<commit_msg>(CSSImportRuleImp::notify): Fix a bug<commit_after>/*
 * Copyright 2011-2013 Esrille Inc.
 *
 * 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 "CSSImportRuleImp.h"

#include <boost/bind.hpp>
#include <boost/version.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>

#include "DocumentImp.h"
#include "WindowImp.h"

#include "CSSInputStream.h"
#include "CSSParser.h"
#include "CSSStyleSheetImp.h"

#include "http/HTTPRequest.h"

#include "Test.util.h"

namespace org
{
namespace w3c
{
namespace dom
{
namespace bootstrap
{

using namespace css;

CSSImportRuleImp::CSSImportRuleImp(const std::u16string& href) :
    href(href),
    mediaList(MediaListImp::All),
    request(0),
    styleSheet(0)
{
}

CSSImportRuleImp::~CSSImportRuleImp()
{
    delete request;
}

// CSSRule
unsigned short CSSImportRuleImp::getType()
{
    return CSSRule::IMPORT_RULE;
}

std::u16string CSSImportRuleImp::getCssText()
{
    std::u16string text = u"@import url(" + href + u")";
    std::u16string media = mediaList.getMediaText();
    if (!media.empty())
        text += u" " + media;
    return text;
}

// CSSImportRule
std::u16string CSSImportRuleImp::getHref()
{
    return href;
}

stylesheets::MediaList CSSImportRuleImp::getMedia()
{
    return &mediaList;
}

void CSSImportRuleImp::setMedia(const std::u16string& media)
{
    mediaList.setMediaText(media);
}

css::CSSStyleSheet CSSImportRuleImp::getStyleSheet()
{
    if (!styleSheet && !href.empty() && !request) {  // TODO: deal with ins. mem
        request = new(std::nothrow) HttpRequest(document->getDocumentURI());
        if (request) {
            request->open(u"GET", href);
            request->setHandler(boost::bind(&CSSImportRuleImp::notify, this));
            document->incrementLoadEventDelayCount();
            request->send();
        }
    }
    return styleSheet;
}

void CSSImportRuleImp::notify()
{
    if (request->getStatus() == 200) {
#if 104400 <= BOOST_VERSION
        boost::iostreams::stream<boost::iostreams::file_descriptor_source> stream(request->getContentDescriptor(), boost::iostreams::never_close_handle);
#else
        boost::iostreams::stream<boost::iostreams::file_descriptor_source> stream(request->getContentDescriptor(), false);
#endif
        CSSParser parser;
        CSSInputStream cssStream(stream, request->getResponseMessage().getContentCharset(), utfconv(document->getCharacterSet()));
        styleSheet = parser.parse(document, cssStream);
        if (auto imp = dynamic_cast<CSSStyleSheetImp*>(styleSheet.self()))
            imp->setParentStyleSheet(getParentStyleSheet());
        if (4 <= getLogLevel())
            dumpStyleSheet(std::cerr, styleSheet.self());
    }
    document->decrementLoadEventDelayCount();

    if (WindowImp* view = document->getDefaultWindow())
        view->setFlags(Box::NEED_SELECTOR_REMATCHING);
}

}
}
}
}
<|endoftext|>


<commit_before>#include <sstream>
#include "std_members.h"
#include "types.h"
#include "symtable.h"

cx_symtab *std_members = nullptr;

void init_std_members (void) {
    // initialize after basic types are init

    struct {
        cx_symtab_node *p_node;
        std::string name;
        cx_function_code code;
        m_call member_call;
        cx_type *p_type;
    } type_members[] = {
        { nullptr, "each", func_std_iterator, &cx_std_members::each, p_void_type},
        { nullptr, "size", func_std_member, &cx_std_members::size, p_integer_type},
        { nullptr, "length", func_std_member, &cx_std_members::length, p_integer_type},
        { nullptr, "to_str", func_std_member, &cx_std_members::to_str, new cx_type(fc_array, 0, nullptr)},
        { nullptr, "to_wstr", func_std_member, &cx_std_members::to_wstr, new cx_type(fc_array, 0, nullptr)},
        { nullptr, "to_int", func_std_member, &cx_std_members::to_int, p_integer_type},
        { nullptr, "to_chr", func_std_member, &cx_std_members::to_chr, p_char_type},
        { nullptr, "to_flt", func_std_member, &cx_std_members::to_flt, p_float_type},
        { nullptr, "to_bool", func_std_member, &cx_std_members::to_bool, p_boolean_type},
        { nullptr, "to_wchr", func_std_member, &cx_std_members::to_wchr, p_wchar_type},
        { nullptr, "to_byte", func_std_member, &cx_std_members::to_byte, p_uint8_type}
    };
    // allocate std member functions for basic types
    std_members = new cx_symtab;

    p_integer_type->complex.p_class_scope = std_members;
    p_uint8_type->complex.p_class_scope = std_members;
    p_float_type->complex.p_class_scope = std_members;
    p_boolean_type->complex.p_class_scope = std_members;
    p_char_type->complex.p_class_scope = std_members;
    p_wchar_type->complex.p_class_scope = std_members;

    for (auto &member : type_members) {
        member.p_node = std_members->enter(member.name.c_str(), dc_function);
        member.p_node->defn.routine.iterator.postfix = 0;
        member.p_node->defn.routine.std_member = member.member_call;
        member.p_node->defn.routine.which = member.code;
        member.p_node->defn.routine.parm_count = 0;
        member.p_node->defn.routine.total_parm_size = 0;
        member.p_node->defn.routine.locals.p_parms_ids = nullptr;
        member.p_node->defn.routine.locals.p_constant_ids = nullptr;
        member.p_node->defn.routine.locals.p_type_ids = nullptr;
        member.p_node->defn.routine.locals.p_variable_ids = nullptr;
        member.p_node->defn.routine.locals.p_function_ids = nullptr;

        set_type(member.p_node->p_type, member.p_type);

        if (member.name == "to_str") {
            set_type(member.p_node->p_type->array.p_element_type, p_char_type);
        } else if (member.name == "to_wstr") {
            set_type(member.p_node->p_type->array.p_element_type, p_wchar_type);
        }

    }
}

cx_type *cx_std_members::size (cx_executor* cx,
                               cx_symtab_node* cx_function_id,
                               const cx_type *p_type) {
    cx->pop();
    cx_stack_item *p_size_val = new cx_stack_item;
    p_size_val->basic_types.int__ = p_type->size;
    cx->push((void*) p_size_val);

    return cx_function_id->p_type;
}

cx_type *cx_std_members::length (cx_executor *cx,
                                 cx_symtab_node *cx_function_id,
                                 const cx_type *p_type) {

    cx->pop();
    cx_stack_item *p_length_val = new cx_stack_item;

    p_type->form == fc_array ?
            p_length_val->basic_types.int__ = p_type->array.element_count :
            p_length_val->basic_types.int__ = 1;

    cx->push((void *) p_length_val);

    return cx_function_id->p_type;
}

/** @TODO - needs to be fixed for wide char
 */
cx_type *cx_std_members::to_str (cx_executor *cx,
                                 cx_symtab_node *cx_function_id,
                                 const cx_type *p_type) {

    std::stringstream ss;
    ss.clear();

    cx_stack_item *mem = nullptr;

    ///if (p_type->.how == dc_reference) {
        mem = cx->top();
    //} else {
        mem = (cx_stack_item *) cx->top()->basic_types.addr__;
    //}

    switch (p_type->type_code) {
        case cx_int:
            ss << mem->basic_types.int__ << '\0';
            break;
        case cx_char:
            ss << mem->basic_types.char__ << '\0';
            break;
        case cx_wchar:
            ss << mem->basic_types.wchar__ << '\0';
            break;
        case cx_float:
            ss << mem->basic_types.float__ << '\0';
            break;
        case cx_bool:
            ss << (mem->basic_types.bool__ ? "true" : "false") << '\0';
            break;
        case cx_uint8:
            ss << (int) mem->basic_types.uint8__ << '\0';
            break;
        default:
            ss << mem->basic_types.addr__ << '\0';
            break;
    }

    cx->pop();

    const int size = ss.str().size() - 1;
    const int length = ss.str().length() - 1;

    cx_type *p_str = new cx_type(fc_array, size, nullptr);
    set_type(p_str->array.p_element_type, p_char_type);
    p_str->array.element_count = length;
    p_str->array.max_index = length;

    char *p_to_str = (char *) malloc(size + 1);
    memcpy(p_to_str, ss.str().c_str(), size + 1);

    cx->push((void *) p_to_str);

    return p_str;
}

cx_type *cx_std_members::to_wstr (cx_executor *cx,
                                  cx_symtab_node *cx_function_id,
                                  const cx_type *p_type) {

    return cx_function_id->p_type;
}

cx_type *cx_std_members::to_int (cx_executor *cx,
                                 cx_symtab_node *cx_function_id,
                                 const cx_type *p_type) {

    return cx_function_id->p_type;
}

cx_type *cx_std_members::to_chr (cx_executor *cx,
                                 cx_symtab_node *cx_function_id,
                                 const cx_type *p_type) {

    return cx_function_id->p_type;
}

cx_type *cx_std_members::to_flt (cx_executor *cx,
                                 cx_symtab_node *cx_function_id,
                                 const cx_type *p_type) {

    return cx_function_id->p_type;
}

cx_type *cx_std_members::to_bool (cx_executor *cx,
                                  cx_symtab_node *cx_function_id,
                                  const cx_type *p_type) {

    return cx_function_id->p_type;
}

cx_type *cx_std_members::to_wchr (cx_executor *cx,
                                  cx_symtab_node *cx_function_id,
                                  const cx_type *p_type) {

    return cx_function_id->p_type;
}

cx_type *cx_std_members::to_byte (cx_executor *cx,
                                  cx_symtab_node *cx_function_id,
                                  const cx_type *p_type) {

    return cx_function_id->p_type;
}

cx_type *cx_std_members::each (cx_executor *cx,
                               cx_symtab_node *cx_function_id,
                               const cx_type *p_type) {

    /*int *iteration = &cx_function_id->defn.routine.iterator.current_iteration;
    const int end = cx_function_id->defn.routine.iterator.p_node->p_type->array.element_count;

    int loop_start = cx_function_id->defn.routine.iterator.at_loop_start;*

    /*for (*iteration = 0; *iteration < end; ++*iteration) {
        cx->execute_variable(cx_function_id->defn.routine.iterator.p_node, true);*/
    cx->execute_iterator(cx_function_id);
    /*cx->goto_location(loop_start);
    cx->get_next_token();
}*/

    return cx_function_id->p_type;
}<commit_msg>gh-page<commit_after>#include <sstream>
#include "std_members.h"
#include "types.h"
#include "symtable.h"

cx_symtab *std_members = nullptr;

void init_std_members (void) {
    // initialize after basic types are init

    struct {
        cx_symtab_node *p_node;
        std::string name;
        cx_function_code code;
        m_call member_call;
        cx_type *p_type;
    } type_members[] = {
        { nullptr, "each", func_std_iterator, &cx_std_members::each, p_void_type},
        { nullptr, "size", func_std_member, &cx_std_members::size, p_integer_type},
        { nullptr, "length", func_std_member, &cx_std_members::length, p_integer_type},
        { nullptr, "to_str", func_std_member, &cx_std_members::to_str, new cx_type(fc_array, 0, nullptr)},
        { nullptr, "to_wstr", func_std_member, &cx_std_members::to_wstr, new cx_type(fc_array, 0, nullptr)},
        { nullptr, "to_int", func_std_member, &cx_std_members::to_int, p_integer_type},
        { nullptr, "to_chr", func_std_member, &cx_std_members::to_chr, p_char_type},
        { nullptr, "to_flt", func_std_member, &cx_std_members::to_flt, p_float_type},
        { nullptr, "to_bool", func_std_member, &cx_std_members::to_bool, p_boolean_type},
        { nullptr, "to_wchr", func_std_member, &cx_std_members::to_wchr, p_wchar_type},
        { nullptr, "to_byte", func_std_member, &cx_std_members::to_byte, p_uint8_type}
    };
    // allocate std member functions for basic types
    std_members = new cx_symtab;

    p_integer_type->complex.p_class_scope = std_members;
    p_uint8_type->complex.p_class_scope = std_members;
    p_float_type->complex.p_class_scope = std_members;
    p_boolean_type->complex.p_class_scope = std_members;
    p_char_type->complex.p_class_scope = std_members;
    p_wchar_type->complex.p_class_scope = std_members;

    for (auto &member : type_members) {
        member.p_node = std_members->enter(member.name.c_str(), dc_function);
        member.p_node->defn.routine.iterator.postfix = 0;
        member.p_node->defn.routine.std_member = member.member_call;
        member.p_node->defn.routine.which = member.code;
        member.p_node->defn.routine.parm_count = 0;
        member.p_node->defn.routine.total_parm_size = 0;
        member.p_node->defn.routine.locals.p_parms_ids = nullptr;
        member.p_node->defn.routine.locals.p_constant_ids = nullptr;
        member.p_node->defn.routine.locals.p_type_ids = nullptr;
        member.p_node->defn.routine.locals.p_variable_ids = nullptr;
        member.p_node->defn.routine.locals.p_function_ids = nullptr;

        set_type(member.p_node->p_type, member.p_type);

        if (member.name == "to_str") {
            set_type(member.p_node->p_type->array.p_element_type, p_char_type);
        } else if (member.name == "to_wstr") {
            set_type(member.p_node->p_type->array.p_element_type, p_wchar_type);
        }

    }
}

cx_type *cx_std_members::size (cx_executor* cx,
                               cx_symtab_node* cx_function_id,
                               const cx_type *p_type) {
    cx->pop();
    cx_stack_item *p_size_val = new cx_stack_item;
    p_size_val->basic_types.int__ = p_type->size;
    cx->push((void*) p_size_val);

    return cx_function_id->p_type;
}

cx_type *cx_std_members::length (cx_executor *cx,
                                 cx_symtab_node *cx_function_id,
                                 const cx_type *p_type) {

    cx->pop();
    cx_stack_item *p_length_val = new cx_stack_item;

    p_type->form == fc_array ?
            p_length_val->basic_types.int__ = p_type->array.element_count :
            p_length_val->basic_types.int__ = 1;

    cx->push((void *) p_length_val);

    return cx_function_id->p_type;
}

/** @TODO - needs to be fixed for wide char
 */
cx_type *cx_std_members::to_str (cx_executor *cx,
                                 cx_symtab_node *cx_function_id,
                                 const cx_type *p_type) {

    std::stringstream ss;
    ss.clear();

    cx_stack_item *mem = nullptr;

    ///if (p_type->.how == dc_reference) {
       // mem = cx->top();
    //} else {
        mem = (cx_stack_item *) cx->top()->basic_types.addr__;
    //}

    switch (p_type->type_code) {
        case cx_int:
            ss << mem->basic_types.int__ << '\0';
            break;
        case cx_char:
            ss << mem->basic_types.char__ << '\0';
            break;
        case cx_wchar:
            ss << mem->basic_types.wchar__ << '\0';
            break;
        case cx_float:
            ss << mem->basic_types.float__ << '\0';
            break;
        case cx_bool:
            ss << (mem->basic_types.bool__ ? "true" : "false") << '\0';
            break;
        case cx_uint8:
            ss << (int) mem->basic_types.uint8__ << '\0';
            break;
        default:
            ss << mem->basic_types.addr__ << '\0';
            break;
    }

    cx->pop();

    const int size = ss.str().size() - 1;
    const int length = ss.str().length() - 1;

    cx_type *p_str = new cx_type(fc_array, size, nullptr);
    set_type(p_str->array.p_element_type, p_char_type);
    p_str->array.element_count = length;
    p_str->array.max_index = length;

    char *p_to_str = (char *) malloc(size + 1);
    memcpy(p_to_str, ss.str().c_str(), size + 1);

    cx->push((void *) p_to_str);

    return p_str;
}

cx_type *cx_std_members::to_wstr (cx_executor *cx,
                                  cx_symtab_node *cx_function_id,
                                  const cx_type *p_type) {

    return cx_function_id->p_type;
}

cx_type *cx_std_members::to_int (cx_executor *cx,
                                 cx_symtab_node *cx_function_id,
                                 const cx_type *p_type) {

    return cx_function_id->p_type;
}

cx_type *cx_std_members::to_chr (cx_executor *cx,
                                 cx_symtab_node *cx_function_id,
                                 const cx_type *p_type) {

    return cx_function_id->p_type;
}

cx_type *cx_std_members::to_flt (cx_executor *cx,
                                 cx_symtab_node *cx_function_id,
                                 const cx_type *p_type) {

    return cx_function_id->p_type;
}

cx_type *cx_std_members::to_bool (cx_executor *cx,
                                  cx_symtab_node *cx_function_id,
                                  const cx_type *p_type) {

    return cx_function_id->p_type;
}

cx_type *cx_std_members::to_wchr (cx_executor *cx,
                                  cx_symtab_node *cx_function_id,
                                  const cx_type *p_type) {

    return cx_function_id->p_type;
}

cx_type *cx_std_members::to_byte (cx_executor *cx,
                                  cx_symtab_node *cx_function_id,
                                  const cx_type *p_type) {

    return cx_function_id->p_type;
}

cx_type *cx_std_members::each (cx_executor *cx,
                               cx_symtab_node *cx_function_id,
                               const cx_type *p_type) {

    /*int *iteration = &cx_function_id->defn.routine.iterator.current_iteration;
    const int end = cx_function_id->defn.routine.iterator.p_node->p_type->array.element_count;

    int loop_start = cx_function_id->defn.routine.iterator.at_loop_start;*

    /*for (*iteration = 0; *iteration < end; ++*iteration) {
        cx->execute_variable(cx_function_id->defn.routine.iterator.p_node, true);*/
    cx->execute_iterator(cx_function_id);
    /*cx->goto_location(loop_start);
    cx->get_next_token();
}*/

    return cx_function_id->p_type;
}<|endoftext|>


<commit_before><commit_msg>trivial: Make CI happy<commit_after><|endoftext|>


<commit_before>#pragma once
#include <PluginFactory/details/PluginHandle.hpp>
#include <PluginFactory/details/build_traits.hpp>

#include <boost/filesystem/path.hpp>
#include <string>

namespace PluginFactory { namespace details {

    // The primary template has a null implementation.
    // Actual implementations will live in specializations.
    template<build_traits::Platform Platform>
    class PluginLoaderImpl
    {
    public:
        PluginLoaderImpl(const boost::filesystem::path& /*pluginPath*/){}

        void validateCompiler(const std::string& /*compilerToken*/) {}
        void validatePluginVersion(const std::string& /*pluginVersion*/) {}
        void validatePluginServiceVersion(const std::string& /*serviceVersion*/) {}

        template<class PluginInterface, class PluginServiceInterface>
        PluginHandle<PluginInterface, PluginServiceInterface> getPluginHandle()
        {
            return PluginHandle<PluginInterface, PluginServiceInterface>();
        }
    };
}}
<commit_msg>Removing constructor from primary template definition of PluginLoaderImpl.<commit_after>#pragma once
#include <PluginFactory/details/build_traits.hpp>
#include <string>

namespace boost { namespace filesystem {
    class path;
}}

namespace PluginFactory { namespace details {

    // The primary template has none of the methods specified.
    template<build_traits::Platform Platform>
    struct PluginLoaderImpl
    {
    };
}}
<|endoftext|>


<commit_before>/*
This file is part of cpp-ethereum.

cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file whisperMessage.cpp
* @author Vladislav Gluhovsky <vlad@ethdev.com>
* @date June 2015
*/

#include <boost/test/unit_test.hpp>
#include <libdevcore/SHA3.h>
#include <libwhisper/BloomFilter.h>

using namespace std;
using namespace dev;
using namespace dev::shh;

using TopicBloomFilterShort = TopicBloomFilterBase<4>;
using TopicBloomFilterTest = TopicBloomFilterBase<c_topicBloomFilterSize>;

void testAddNonExisting(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{
	BOOST_REQUIRE(!_f.containsRaw(_h));
	_f.addRaw(_h);
	BOOST_REQUIRE(_f.containsRaw(_h));
}

void testRemoveExisting(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{
	BOOST_REQUIRE(_f.containsRaw(_h));
	_f.removeRaw(_h);
	BOOST_REQUIRE(!_f.containsRaw(_h));
}

void testAddNonExistingBloom(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{
	BOOST_REQUIRE(!_f.containsBloom(_h));
	_f.addBloom(_h);
	BOOST_REQUIRE(_f.containsBloom(_h));
}

void testRemoveExistingBloom(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{
	BOOST_REQUIRE(_f.containsBloom(_h));
	_f.removeBloom(_h);
	BOOST_REQUIRE(!_f.containsBloom(_h));
}

double calculateExpected(TopicBloomFilterTest const& f, int n)
{
	int const m = f.size * 8; // number of bits in the bloom
	int const k = f.BitsPerBloom; // number of hash functions (e.g. bits set to 1 in every bloom)

	double singleBitSet = 1.0 / m; // probability of any bit being set after inserting a single bit
	double singleBitNotSet = (1.0 - singleBitSet);

	double singleNot = 1; // single bit not set after inserting N elements in the bloom filter
	for (int i = 0; i < k * n; ++i)
		singleNot *= singleBitNotSet;

	double single = 1.0 - singleNot; // probability of a single bit being set after inserting N elements in the bloom filter

	double kBitsSet = 1; // probability of K bits being set after inserting N elements in the bloom filter
	for (int i = 0; i < k; ++i)
		kBitsSet *= single;

	return kBitsSet;
}

double testFalsePositiveRate(TopicBloomFilterTest const& f, int inserted, Topic& x)
{
	int const c_sampleSize = 1000;
	int falsePositive = 0;

	for (int i = 0; i < c_sampleSize; ++i)
	{
		x = sha3(x);
		AbridgedTopic a(x);
		if (f.containsBloom(a))
			++falsePositive;
	}

	double res = double(falsePositive) / double(c_sampleSize);

	double expected = calculateExpected(f, inserted);
	double allowed = expected * 1.2 + 0.05; // allow deviations ~25%

	//cnote << "Inserted: " << inserted << ", False Positive Rate: " << res << ", Expected: " << expected;
	BOOST_REQUIRE(res <= allowed);
	return expected;
}

BOOST_AUTO_TEST_SUITE(bloomFilter)

BOOST_AUTO_TEST_CASE(falsePositiveRate)
{
	VerbosityHolder setTemporaryLevel(10);
	cnote << "Testing Bloom Filter False Positive Rate...";

	TopicBloomFilterTest f;
	Topic x(0xC0DEFEED); // deterministic pseudorandom value

	double expectedRate = 0;

	for (int i = 1; i < 50 && isless(expectedRate, 0.5); ++i)
	{
		x = sha3(x);
		f.addBloom(AbridgedTopic(x));
		expectedRate = testFalsePositiveRate(f, i, x);
	}
}

BOOST_AUTO_TEST_CASE(bloomFilterRandom)
{
	VerbosityHolder setTemporaryLevel(10);
	cnote << "Testing Bloom Filter matching...";

	TopicBloomFilterShort f;
	vector<AbridgedTopic> vec;
	Topic x(0xDEADBEEF);
	int const c_rounds = 4;

	for (int i = 0; i < c_rounds; ++i, x = sha3(x))
		vec.push_back(abridge(x));

	for (int i = 0; i < c_rounds; ++i)
		testAddNonExisting(f, vec[i]);

	for (int i = 0; i < c_rounds; ++i)
		testRemoveExisting(f, vec[i]);

	for (int i = 0; i < c_rounds; ++i)
		testAddNonExistingBloom(f, vec[i]);

	for (int i = 0; i < c_rounds; ++i)
		testRemoveExistingBloom(f, vec[i]);
}

BOOST_AUTO_TEST_CASE(bloomFilterRaw)
{
	VerbosityHolder setTemporaryLevel(10);
	cnote << "Testing Raw Bloom matching...";

	TopicBloomFilterShort f;

	AbridgedTopic b00000001(0x01);
	AbridgedTopic b00010000(0x10);
	AbridgedTopic b00011000(0x18);
	AbridgedTopic b00110000(0x30);
	AbridgedTopic b00110010(0x32);
	AbridgedTopic b00111000(0x38);
	AbridgedTopic b00000110(0x06);
	AbridgedTopic b00110110(0x36);
	AbridgedTopic b00110111(0x37);

	testAddNonExisting(f, b00000001);
	testAddNonExisting(f, b00010000);
	testAddNonExisting(f, b00011000);
	testAddNonExisting(f, b00110000);
	BOOST_REQUIRE(f.contains(b00111000));
	testAddNonExisting(f, b00110010);
	testAddNonExisting(f, b00000110);
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(f.contains(b00110111));

	f.removeRaw(b00000001);
	f.removeRaw(b00000001);
	f.removeRaw(b00000001);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(f.contains(b00011000));
	BOOST_REQUIRE(f.contains(b00110000));
	BOOST_REQUIRE(f.contains(b00110010));
	BOOST_REQUIRE(f.contains(b00111000));
	BOOST_REQUIRE(f.contains(b00000110));
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));

	f.removeRaw(b00010000);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(f.contains(b00011000));
	BOOST_REQUIRE(f.contains(b00110000));
	BOOST_REQUIRE(f.contains(b00110010));
	BOOST_REQUIRE(f.contains(b00111000));
	BOOST_REQUIRE(f.contains(b00000110));
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));

	f.removeRaw(b00111000);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(!f.contains(b00011000));
	BOOST_REQUIRE(f.contains(b00110000));
	BOOST_REQUIRE(f.contains(b00110010));
	BOOST_REQUIRE(!f.contains(b00111000));
	BOOST_REQUIRE(f.contains(b00000110));
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));

	f.addRaw(b00000001);
	BOOST_REQUIRE(f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(!f.contains(b00011000));
	BOOST_REQUIRE(f.contains(b00110000));
	BOOST_REQUIRE(f.contains(b00110010));
	BOOST_REQUIRE(!f.contains(b00111000));
	BOOST_REQUIRE(f.contains(b00000110));
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(f.contains(b00110111));

	f.removeRaw(b00110111);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(!f.contains(b00011000));
	BOOST_REQUIRE(!f.contains(b00110000));
	BOOST_REQUIRE(!f.contains(b00110010));
	BOOST_REQUIRE(!f.contains(b00111000));
	BOOST_REQUIRE(!f.contains(b00000110));
	BOOST_REQUIRE(!f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));

	f.removeRaw(b00110111);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(!f.contains(b00010000));
	BOOST_REQUIRE(!f.contains(b00011000));
	BOOST_REQUIRE(!f.contains(b00110000));
	BOOST_REQUIRE(!f.contains(b00110010));
	BOOST_REQUIRE(!f.contains(b00111000));
	BOOST_REQUIRE(!f.contains(b00000110));
	BOOST_REQUIRE(!f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));
}

static const unsigned DistributionTestSize = 8;
static const unsigned TestArrSize = 8 * DistributionTestSize;

void updateDistribution(FixedHash<DistributionTestSize> const& _h, array<unsigned, TestArrSize>& _distribution)
{
	unsigned bits = 0;
	for (unsigned i = 0; i < DistributionTestSize; ++i)
		if (_h[i])
			for (unsigned j = 0; j < 8; ++j)
				if (_h[i] & c_powerOfTwoBitMmask[j])
				{
					_distribution[i * 8 + j]++;
					if (++bits >= TopicBloomFilterTest::BitsPerBloom)
						return;
				}
}

BOOST_AUTO_TEST_CASE(distributionRate)
{
	cnote << "Testing Bloom Filter Distribution Rate...";

	array<unsigned, TestArrSize> distribution;
	for (unsigned i = 0; i < TestArrSize; ++i)
		distribution[i] = 0;

	Topic x(0xC0FFEE); // deterministic pseudorandom value

	for (unsigned i = 0; i < 22000; ++i)
	{
		x = sha3(x);
		FixedHash<DistributionTestSize> h = x.template bloomPart<TopicBloomFilterTest::BitsPerBloom, DistributionTestSize>();
		updateDistribution(h, distribution);
	}

	unsigned average = 0;
	for (unsigned i = 0; i < TestArrSize; ++i)
		average += distribution[i];

	average /= TestArrSize;
	unsigned deviation = average / 10; // approx. 10%
	unsigned maxAllowed = average + deviation;
	unsigned minAllowed = average - deviation;

	for (unsigned i = 0; i < TestArrSize; ++i)
	{
		//cnote << i << ":" << distribution[i];
		BOOST_REQUIRE(distribution[i] > minAllowed);
		BOOST_REQUIRE(distribution[i] < maxAllowed);
	}
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>build fix<commit_after>/*
This file is part of cpp-ethereum.

cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file whisperMessage.cpp
* @author Vladislav Gluhovsky <vlad@ethdev.com>
* @date June 2015
*/

#include <boost/test/unit_test.hpp>
#include <libdevcore/SHA3.h>
#include <libwhisper/BloomFilter.h>

using namespace std;
using namespace dev;
using namespace dev::shh;

using TopicBloomFilterShort = TopicBloomFilterBase<4>;
using TopicBloomFilterTest = TopicBloomFilterBase<TopicBloomFilterSize>;

void testAddNonExisting(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{
	BOOST_REQUIRE(!_f.containsRaw(_h));
	_f.addRaw(_h);
	BOOST_REQUIRE(_f.containsRaw(_h));
}

void testRemoveExisting(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{
	BOOST_REQUIRE(_f.containsRaw(_h));
	_f.removeRaw(_h);
	BOOST_REQUIRE(!_f.containsRaw(_h));
}

void testAddNonExistingBloom(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{
	BOOST_REQUIRE(!_f.containsBloom(_h));
	_f.addBloom(_h);
	BOOST_REQUIRE(_f.containsBloom(_h));
}

void testRemoveExistingBloom(TopicBloomFilterShort& _f, AbridgedTopic const& _h)
{
	BOOST_REQUIRE(_f.containsBloom(_h));
	_f.removeBloom(_h);
	BOOST_REQUIRE(!_f.containsBloom(_h));
}

double calculateExpected(TopicBloomFilterTest const& f, int n)
{
	int const m = f.size * 8; // number of bits in the bloom
	int const k = BitsPerBloom; // number of hash functions (e.g. bits set to 1 in every bloom)

	double singleBitSet = 1.0 / m; // probability of any bit being set after inserting a single bit
	double singleBitNotSet = (1.0 - singleBitSet);

	double singleNot = 1; // single bit not set after inserting N elements in the bloom filter
	for (int i = 0; i < k * n; ++i)
		singleNot *= singleBitNotSet;

	double single = 1.0 - singleNot; // probability of a single bit being set after inserting N elements in the bloom filter

	double kBitsSet = 1; // probability of K bits being set after inserting N elements in the bloom filter
	for (int i = 0; i < k; ++i)
		kBitsSet *= single;

	return kBitsSet;
}

double testFalsePositiveRate(TopicBloomFilterTest const& f, int inserted, Topic& x)
{
	int const c_sampleSize = 1000;
	int falsePositive = 0;

	for (int i = 0; i < c_sampleSize; ++i)
	{
		x = sha3(x);
		AbridgedTopic a(x);
		if (f.containsBloom(a))
			++falsePositive;
	}

	double res = double(falsePositive) / double(c_sampleSize);

	double expected = calculateExpected(f, inserted);
	double allowed = expected * 1.2 + 0.05; // allow deviations ~25%

	//cnote << "Inserted: " << inserted << ", False Positive Rate: " << res << ", Expected: " << expected;
	BOOST_REQUIRE(res <= allowed);
	return expected;
}

BOOST_AUTO_TEST_SUITE(bloomFilter)

BOOST_AUTO_TEST_CASE(falsePositiveRate)
{
	VerbosityHolder setTemporaryLevel(10);
	cnote << "Testing Bloom Filter False Positive Rate...";

	TopicBloomFilterTest f;
	Topic x(0xC0DEFEED); // deterministic pseudorandom value

	double expectedRate = 0;

	for (int i = 1; i < 50 && isless(expectedRate, 0.5); ++i)
	{
		x = sha3(x);
		f.addBloom(AbridgedTopic(x));
		expectedRate = testFalsePositiveRate(f, i, x);
	}
}

BOOST_AUTO_TEST_CASE(bloomFilterRandom)
{
	VerbosityHolder setTemporaryLevel(10);
	cnote << "Testing Bloom Filter matching...";

	TopicBloomFilterShort f;
	vector<AbridgedTopic> vec;
	Topic x(0xDEADBEEF);
	int const c_rounds = 4;

	for (int i = 0; i < c_rounds; ++i, x = sha3(x))
		vec.push_back(abridge(x));

	for (int i = 0; i < c_rounds; ++i)
		testAddNonExisting(f, vec[i]);

	for (int i = 0; i < c_rounds; ++i)
		testRemoveExisting(f, vec[i]);

	for (int i = 0; i < c_rounds; ++i)
		testAddNonExistingBloom(f, vec[i]);

	for (int i = 0; i < c_rounds; ++i)
		testRemoveExistingBloom(f, vec[i]);
}

BOOST_AUTO_TEST_CASE(bloomFilterRaw)
{
	VerbosityHolder setTemporaryLevel(10);
	cnote << "Testing Raw Bloom matching...";

	TopicBloomFilterShort f;

	AbridgedTopic b00000001(0x01);
	AbridgedTopic b00010000(0x10);
	AbridgedTopic b00011000(0x18);
	AbridgedTopic b00110000(0x30);
	AbridgedTopic b00110010(0x32);
	AbridgedTopic b00111000(0x38);
	AbridgedTopic b00000110(0x06);
	AbridgedTopic b00110110(0x36);
	AbridgedTopic b00110111(0x37);

	testAddNonExisting(f, b00000001);
	testAddNonExisting(f, b00010000);
	testAddNonExisting(f, b00011000);
	testAddNonExisting(f, b00110000);
	BOOST_REQUIRE(f.contains(b00111000));
	testAddNonExisting(f, b00110010);
	testAddNonExisting(f, b00000110);
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(f.contains(b00110111));

	f.removeRaw(b00000001);
	f.removeRaw(b00000001);
	f.removeRaw(b00000001);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(f.contains(b00011000));
	BOOST_REQUIRE(f.contains(b00110000));
	BOOST_REQUIRE(f.contains(b00110010));
	BOOST_REQUIRE(f.contains(b00111000));
	BOOST_REQUIRE(f.contains(b00000110));
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));

	f.removeRaw(b00010000);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(f.contains(b00011000));
	BOOST_REQUIRE(f.contains(b00110000));
	BOOST_REQUIRE(f.contains(b00110010));
	BOOST_REQUIRE(f.contains(b00111000));
	BOOST_REQUIRE(f.contains(b00000110));
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));

	f.removeRaw(b00111000);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(!f.contains(b00011000));
	BOOST_REQUIRE(f.contains(b00110000));
	BOOST_REQUIRE(f.contains(b00110010));
	BOOST_REQUIRE(!f.contains(b00111000));
	BOOST_REQUIRE(f.contains(b00000110));
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));

	f.addRaw(b00000001);
	BOOST_REQUIRE(f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(!f.contains(b00011000));
	BOOST_REQUIRE(f.contains(b00110000));
	BOOST_REQUIRE(f.contains(b00110010));
	BOOST_REQUIRE(!f.contains(b00111000));
	BOOST_REQUIRE(f.contains(b00000110));
	BOOST_REQUIRE(f.contains(b00110110));
	BOOST_REQUIRE(f.contains(b00110111));

	f.removeRaw(b00110111);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(f.contains(b00010000));
	BOOST_REQUIRE(!f.contains(b00011000));
	BOOST_REQUIRE(!f.contains(b00110000));
	BOOST_REQUIRE(!f.contains(b00110010));
	BOOST_REQUIRE(!f.contains(b00111000));
	BOOST_REQUIRE(!f.contains(b00000110));
	BOOST_REQUIRE(!f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));

	f.removeRaw(b00110111);
	BOOST_REQUIRE(!f.contains(b00000001));
	BOOST_REQUIRE(!f.contains(b00010000));
	BOOST_REQUIRE(!f.contains(b00011000));
	BOOST_REQUIRE(!f.contains(b00110000));
	BOOST_REQUIRE(!f.contains(b00110010));
	BOOST_REQUIRE(!f.contains(b00111000));
	BOOST_REQUIRE(!f.contains(b00000110));
	BOOST_REQUIRE(!f.contains(b00110110));
	BOOST_REQUIRE(!f.contains(b00110111));
}

static const unsigned DistributionTestSize = 8;
static const unsigned TestArrSize = 8 * DistributionTestSize;

void updateDistribution(FixedHash<DistributionTestSize> const& _h, array<unsigned, TestArrSize>& _distribution)
{
	unsigned bits = 0;
	for (unsigned i = 0; i < DistributionTestSize; ++i)
		if (_h[i])
			for (unsigned j = 0; j < 8; ++j)
				if (_h[i] & c_powerOfTwoBitMmask[j])
				{
					_distribution[i * 8 + j]++;
					if (++bits >= BitsPerBloom)
						return;
				}
}

BOOST_AUTO_TEST_CASE(distributionRate)
{
	cnote << "Testing Bloom Filter Distribution Rate...";

	array<unsigned, TestArrSize> distribution;
	for (unsigned i = 0; i < TestArrSize; ++i)
		distribution[i] = 0;

	Topic x(0xC0FFEE); // deterministic pseudorandom value

	for (unsigned i = 0; i < 22000; ++i)
	{
		x = sha3(x);
		FixedHash<DistributionTestSize> h = x.template bloomPart<BitsPerBloom, DistributionTestSize>();
		updateDistribution(h, distribution);
	}

	unsigned average = 0;
	for (unsigned i = 0; i < TestArrSize; ++i)
		average += distribution[i];

	average /= TestArrSize;
	unsigned deviation = average / 10; // approx. 10%
	unsigned maxAllowed = average + deviation;
	unsigned minAllowed = average - deviation;

	for (unsigned i = 0; i < TestArrSize; ++i)
	{
		//cnote << i << ":" << distribution[i];
		BOOST_REQUIRE(distribution[i] > minAllowed);
		BOOST_REQUIRE(distribution[i] < maxAllowed);
	}
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include "TTree.h"
#include "TFile.h"
#include "TList.h"
#include <TBenchmark.h>

int gHasLibrary = kFALSE;
TList gSkipped;

void DrawSkippable(TTree* tree, const char* what, const char* where, bool skip) {
  //cerr << "Doing " << what << " which is " << skip << endl;
  if (skip) gSkipped.Add(new TNamed(where,where));
  else {
    TString cut = what;
    cut.Append(">>");
    cut.Append(where);
    tree->Draw(cut.Data(),"","goff");
  }
};

void DrawSkippable(TTree* tree, const char* what, const char* cond,
                   const char* where, bool skip) {
  //cerr << "Doing " << what << " which is " << skip << endl;
  if (skip) gSkipped.Add(new TNamed(where,where));
  else {
    TString cut = what;
    cut.Append(">>");
    cut.Append(where);
    tree->Draw(cut.Data(),cond,"goff");
  }
};

// Rootmarks for fcdflnx1 is 153.4
void DrawMarks() {

  // The base is currently: RunDrawTest.C++("Event.old.split.root",0)
  Float_t rt_base = 2.33;
  Float_t cp_base = 2.34;

  Float_t rt = gBenchmark->GetRealTime("DrawTest");
  Float_t ct = gBenchmark->GetCpuTime("DrawTest");

  // gBenchmark->Print("DrawTest");

  Float_t rootmarks = 200*(rt_base + cp_base)/(rt + ct);

  printf("*  ROOTMARKS =%6.1f   *  Root%-8s  %d/%d\n",rootmarks,gROOT->GetVersion(),gROOT->GetVersionDate(),gROOT->GetVersionTime());

}

//_______________________________________________________________
TDirectory* GenerateDrawHist(TTree *tree,int level = 1)
{
// Test selections via TreeFormula
// tree is a TTree when called by stress9
// tree is a TChain when called from stres11
// This is a quite complex test checking the results of TTree::Draw
// or TChain::Draw with an explicit loop on events.
// Also a good test for the interpreter

   gROOT->cd();
   TDirectory *hfile = gDirectory;

   gBenchmark = new TBenchmark();
   gBenchmark->Start("DrawTest");

   // Each tree->Draw generates an histogram
   DrawSkippable(tree,"GetNtrack()","hGetNtrack",!(level>0 && gHasLibrary));

   //gBenchmark->Show("DrawTest");  gBenchmark->Start("DrawTest");

   tree->Draw("fNtrack>>hNtrack",    "","goff");
   tree->Draw("fNseg>>hNseg",        "","goff");
   tree->Draw("fTemperature>>hTemp", "","goff");

   tree->Draw("fH.GetMean()>>hHmean","","goff");
   if (level>0) tree->Draw("fH.fXaxis.fXmax>>hHAxisMax","","goff");
   if (level>0) tree->Draw("fH.fXaxis.GetXmax()>>hHAxisGetMax","","goff");
   DrawSkippable(tree,"fH.GetXaxis().GetXmax()","hHGetAxisGetMax",!(level>0));
   DrawSkippable(tree,"fH.GetXaxis().fXmax","hHGetAxisMax",!(level>0));
   DrawSkippable(tree,"GetHistogram().GetXaxis().GetXmax()","hGetHGetAxisMax",
                 !(level>0&&gHasLibrary));
   DrawSkippable(tree,"event.GetHistogram().GetXaxis().GetXmax()",
                 "hGetRefHGetAxisMax",!(level>0&&gHasLibrary));

   tree->Draw("fTracks.fPx>>hPx","fEvtHdr.fEvtNum%10 == 0","goff");
   tree->Draw("fTracks.fPy>>hPy","fEvtHdr.fEvtNum%10 == 0","goff");
   tree->Draw("fTracks.fPz>>hPz","fEvtHdr.fEvtNum%10 == 0","goff");
   tree->Draw("fRandom>>hRandom","fEvtHdr.fEvtNum%10 == 1","goff");
   tree->Draw("fMass2>>hMass2",  "fEvtHdr.fEvtNum%10 == 1","goff");
   tree->Draw("fBx>>hBx",        "fEvtHdr.fEvtNum%10 == 1","goff");
   tree->Draw("fBy>>hBy",        "fEvtHdr.fEvtNum%10 == 1","goff");
   tree->Draw("fXfirst>>hXfirst","fEvtHdr.fEvtNum%10 == 2","goff");
   tree->Draw("fYfirst>>hYfirst","fEvtHdr.fEvtNum%10 == 2","goff");
   tree->Draw("fZfirst>>hZfirst","fEvtHdr.fEvtNum%10 == 2","goff");
   tree->Draw("fXlast>>hXlast",  "fEvtHdr.fEvtNum%10 == 3","goff");
   tree->Draw("fYlast>>hYlast",  "fEvtHdr.fEvtNum%10 == 3","goff");
   tree->Draw("fZlast>>hZlast",  "fEvtHdr.fEvtNum%10 == 3","goff");
   tree->Draw("fCharge>>hCharge","fPx < 0","goff");
   tree->Draw("fNpoint>>hNpoint","fPx < 0","goff");
   tree->Draw("fValid>>hValid",  "fPx < 0","goff");

   tree->Draw("fMatrix>>hFullMatrix","","goff");
   tree->Draw("fMatrix[][0]>>hColMatrix","","goff");
   tree->Draw("fMatrix[1][]>>hRowMatrix","","goff");
   tree->Draw("fMatrix[2][2]>>hCellMatrix","","goff");

   tree->Draw("fMatrix - fVertex>>hFullOper","","goff");
   tree->Draw("fMatrix[2][1] - fVertex[5][1]>>hCellOper","","goff");
   tree->Draw("fMatrix[][1]  - fVertex[5][1]>>hColOper","","goff");
   tree->Draw("fMatrix[2][]  - fVertex[5][2]>>hRowOper","","goff");
   tree->Draw("fMatrix[2][]  - fVertex[5][]>>hMatchRowOper","","goff");
   tree->Draw("fMatrix[][2]  - fVertex[][1]>>hMatchColOper","","goff");
   tree->Draw("fMatrix[][2]  - fVertex[][]>>hRowMatOper","","goff");
   tree->Draw("fMatrix[][2]  - fVertex[5][]>>hMatchDiffOper","","goff");
   tree->Draw("fMatrix[][]   - fVertex[][]>>hFullOper2","","goff");

   // Test on variable arrays
   tree->Draw("fClosestDistance>>hClosestDistance","","goff");
   tree->Draw("fClosestDistance[2]>>hClosestDistance2","","goff");
   tree->Draw("fClosestDistance[9]>>hClosestDistance9","","goff");

   // Test variable indexing
   DrawSkippable(tree,"fClosestDistance[fNvertex/2]","hClosestDistanceIndex",
                 !(level>0));
   DrawSkippable(tree,"fPx:fPy[fNpoint]","fPy[fNpoint]>0","hPxInd",!(level>0));

   // Test of simple function calls
   DrawSkippable(tree,"sqrt(fNtrack)","hSqrtNtrack",!(level>0));

   // Test string operations
   DrawSkippable(tree,"fEvtHdr.fEvtNum","fType==\"type1\" ","hString",!(level>0));
   DrawSkippable(tree,"fEvtHdr.fEvtNum","strstr(fType,\"1\") ","+hString",!(level>0));

   // Test binary operators
   DrawSkippable(tree,"fValid<<4","hShiftValid",!(level>0));
   DrawSkippable(tree,"((fValid<<4)>>2)","+hShiftValid",!(level>0));
   DrawSkippable(tree,"fValid&0x1","(fNvertex>10) && (fNseg<=6000)"
                 ,"hAndValid",!(level>0));

   // Test weight
   DrawSkippable(tree,"fPx","(fBx>.4) || (fBy<=-.4)","hPxBx",!(level>0));
   DrawSkippable(tree,"fPx","fBx*fBx*(fBx>.4) + fBy*fBy*(fBy<=-.4)",
                 "hPxBxWeight",!(level>0));

   gBenchmark->Show("DrawTest");  gBenchmark->Start("DrawTest");

   return hfile;

}
<commit_msg>Replace non portable type bool by Bool_t<commit_after>#include "TTree.h"
#include "TFile.h"
#include "TList.h"
#include <TBenchmark.h>

int gHasLibrary = kFALSE;
TList gSkipped;

void DrawSkippable(TTree* tree, const char* what, const char* where, Bool_t skip) {
  //cerr << "Doing " << what << " which is " << skip << endl;
  if (skip) gSkipped.Add(new TNamed(where,where));
  else {
    TString cut = what;
    cut.Append(">>");
    cut.Append(where);
    tree->Draw(cut.Data(),"","goff");
  }
};

void DrawSkippable(TTree* tree, const char* what, const char* cond,
                   const char* where, Bool_t skip) {
  //cerr << "Doing " << what << " which is " << skip << endl;
  if (skip) gSkipped.Add(new TNamed(where,where));
  else {
    TString cut = what;
    cut.Append(">>");
    cut.Append(where);
    tree->Draw(cut.Data(),cond,"goff");
  }
};

// Rootmarks for fcdflnx1 is 153.4
void DrawMarks() {

  // The base is currently: RunDrawTest.C++("Event.old.split.root",0)
  Float_t rt_base = 2.33;
  Float_t cp_base = 2.34;

  Float_t rt = gBenchmark->GetRealTime("DrawTest");
  Float_t ct = gBenchmark->GetCpuTime("DrawTest");

  // gBenchmark->Print("DrawTest");

  Float_t rootmarks = 200*(rt_base + cp_base)/(rt + ct);

  printf("*  ROOTMARKS =%6.1f   *  Root%-8s  %d/%d\n",rootmarks,gROOT->GetVersion(),gROOT->GetVersionDate(),gROOT->GetVersionTime());

}

//_______________________________________________________________
TDirectory* GenerateDrawHist(TTree *tree,int level = 1)
{
// Test selections via TreeFormula
// tree is a TTree when called by stress9
// tree is a TChain when called from stres11
// This is a quite complex test checking the results of TTree::Draw
// or TChain::Draw with an explicit loop on events.
// Also a good test for the interpreter

   gROOT->cd();
   TDirectory *hfile = gDirectory;

   gBenchmark = new TBenchmark();
   gBenchmark->Start("DrawTest");

   // Each tree->Draw generates an histogram
   DrawSkippable(tree,"GetNtrack()","hGetNtrack",!(level>0 && gHasLibrary));

   //gBenchmark->Show("DrawTest");  gBenchmark->Start("DrawTest");

   tree->Draw("fNtrack>>hNtrack",    "","goff");
   tree->Draw("fNseg>>hNseg",        "","goff");
   tree->Draw("fTemperature>>hTemp", "","goff");

   tree->Draw("fH.GetMean()>>hHmean","","goff");
   if (level>0) tree->Draw("fH.fXaxis.fXmax>>hHAxisMax","","goff");
   if (level>0) tree->Draw("fH.fXaxis.GetXmax()>>hHAxisGetMax","","goff");
   DrawSkippable(tree,"fH.GetXaxis().GetXmax()","hHGetAxisGetMax",!(level>0));
   DrawSkippable(tree,"fH.GetXaxis().fXmax","hHGetAxisMax",!(level>0));
   DrawSkippable(tree,"GetHistogram().GetXaxis().GetXmax()","hGetHGetAxisMax",
                 !(level>0&&gHasLibrary));
   DrawSkippable(tree,"event.GetHistogram().GetXaxis().GetXmax()",
                 "hGetRefHGetAxisMax",!(level>0&&gHasLibrary));

   tree->Draw("fTracks.fPx>>hPx","fEvtHdr.fEvtNum%10 == 0","goff");
   tree->Draw("fTracks.fPy>>hPy","fEvtHdr.fEvtNum%10 == 0","goff");
   tree->Draw("fTracks.fPz>>hPz","fEvtHdr.fEvtNum%10 == 0","goff");
   tree->Draw("fRandom>>hRandom","fEvtHdr.fEvtNum%10 == 1","goff");
   tree->Draw("fMass2>>hMass2",  "fEvtHdr.fEvtNum%10 == 1","goff");
   tree->Draw("fBx>>hBx",        "fEvtHdr.fEvtNum%10 == 1","goff");
   tree->Draw("fBy>>hBy",        "fEvtHdr.fEvtNum%10 == 1","goff");
   tree->Draw("fXfirst>>hXfirst","fEvtHdr.fEvtNum%10 == 2","goff");
   tree->Draw("fYfirst>>hYfirst","fEvtHdr.fEvtNum%10 == 2","goff");
   tree->Draw("fZfirst>>hZfirst","fEvtHdr.fEvtNum%10 == 2","goff");
   tree->Draw("fXlast>>hXlast",  "fEvtHdr.fEvtNum%10 == 3","goff");
   tree->Draw("fYlast>>hYlast",  "fEvtHdr.fEvtNum%10 == 3","goff");
   tree->Draw("fZlast>>hZlast",  "fEvtHdr.fEvtNum%10 == 3","goff");
   tree->Draw("fCharge>>hCharge","fPx < 0","goff");
   tree->Draw("fNpoint>>hNpoint","fPx < 0","goff");
   tree->Draw("fValid>>hValid",  "fPx < 0","goff");

   tree->Draw("fMatrix>>hFullMatrix","","goff");
   tree->Draw("fMatrix[][0]>>hColMatrix","","goff");
   tree->Draw("fMatrix[1][]>>hRowMatrix","","goff");
   tree->Draw("fMatrix[2][2]>>hCellMatrix","","goff");

   tree->Draw("fMatrix - fVertex>>hFullOper","","goff");
   tree->Draw("fMatrix[2][1] - fVertex[5][1]>>hCellOper","","goff");
   tree->Draw("fMatrix[][1]  - fVertex[5][1]>>hColOper","","goff");
   tree->Draw("fMatrix[2][]  - fVertex[5][2]>>hRowOper","","goff");
   tree->Draw("fMatrix[2][]  - fVertex[5][]>>hMatchRowOper","","goff");
   tree->Draw("fMatrix[][2]  - fVertex[][1]>>hMatchColOper","","goff");
   tree->Draw("fMatrix[][2]  - fVertex[][]>>hRowMatOper","","goff");
   tree->Draw("fMatrix[][2]  - fVertex[5][]>>hMatchDiffOper","","goff");
   tree->Draw("fMatrix[][]   - fVertex[][]>>hFullOper2","","goff");

   // Test on variable arrays
   tree->Draw("fClosestDistance>>hClosestDistance","","goff");
   tree->Draw("fClosestDistance[2]>>hClosestDistance2","","goff");
   tree->Draw("fClosestDistance[9]>>hClosestDistance9","","goff");

   // Test variable indexing
   DrawSkippable(tree,"fClosestDistance[fNvertex/2]","hClosestDistanceIndex",
                 !(level>0));
   DrawSkippable(tree,"fPx:fPy[fNpoint]","fPy[fNpoint]>0","hPxInd",!(level>0));

   // Test of simple function calls
   DrawSkippable(tree,"sqrt(fNtrack)","hSqrtNtrack",!(level>0));

   // Test string operations
   DrawSkippable(tree,"fEvtHdr.fEvtNum","fType==\"type1\" ","hString",!(level>0));
   DrawSkippable(tree,"fEvtHdr.fEvtNum","strstr(fType,\"1\") ","+hString",!(level>0));

   // Test binary operators
   DrawSkippable(tree,"fValid<<4","hShiftValid",!(level>0));
   DrawSkippable(tree,"((fValid<<4)>>2)","+hShiftValid",!(level>0));
   DrawSkippable(tree,"fValid&0x1","(fNvertex>10) && (fNseg<=6000)"
                 ,"hAndValid",!(level>0));

   // Test weight
   DrawSkippable(tree,"fPx","(fBx>.4) || (fBy<=-.4)","hPxBx",!(level>0));
   DrawSkippable(tree,"fPx","fBx*fBx*(fBx>.4) + fBy*fBy*(fBy<=-.4)",
                 "hPxBxWeight",!(level>0));

   gBenchmark->Show("DrawTest");  gBenchmark->Start("DrawTest");

   return hfile;

}
<|endoftext|>


<commit_before>#include "AnimSprLoader.h"

#include <sprite2/AnimSprite.h>
#include <sprite2/SprTreePath.h>
#include <sprite2/UpdateParams.h>
#include <simp/from_int.h>
#include <simp/NodeAnimationSpr.h>

namespace gum
{

AnimSprLoader::AnimSprLoader(s2::AnimSprite* spr)
	: m_spr(spr)
{
	if (m_spr) {
		m_spr->AddReference();
	}
}

AnimSprLoader::~AnimSprLoader()
{
	if (m_spr) {
		m_spr->RemoveReference();
	}
}

void AnimSprLoader::LoadJson(const Json::Value& val, const std::string& dir)
{
	if (!m_spr || !val.isMember("animation")) {
		return;
	}

	const Json::Value& anim_val = val["animation"];

	m_spr->SetLoop(anim_val["loop"].asBool());
	m_spr->SetInterval(anim_val["interval"].asDouble());

	m_spr->SetFPS(anim_val["fps"].asInt());

	m_spr->SetStartRandom(s2::UpdateParams(), anim_val["start_random"].asBool());

	if (anim_val.isMember("active")) {
		m_spr->SetActive(anim_val["active"].asBool(), NULL);
	}
}

void AnimSprLoader::LoadBin(const simp::NodeAnimationSpr* node)
{
	if (!m_spr) {
		return;
	}

	m_spr->SetLoop(simp::int2bool(node->loop));
	m_spr->SetInterval(simp::int2float(node->interval, 1024));

	m_spr->SetFPS(node->fps);
}

}<commit_msg>up s2<commit_after>#include "AnimSprLoader.h"

#include <sprite2/AnimSprite.h>
#include <sprite2/UpdateParams.h>
#include <simp/from_int.h>
#include <simp/NodeAnimationSpr.h>

namespace gum
{

AnimSprLoader::AnimSprLoader(s2::AnimSprite* spr)
	: m_spr(spr)
{
	if (m_spr) {
		m_spr->AddReference();
	}
}

AnimSprLoader::~AnimSprLoader()
{
	if (m_spr) {
		m_spr->RemoveReference();
	}
}

void AnimSprLoader::LoadJson(const Json::Value& val, const std::string& dir)
{
	if (!m_spr || !val.isMember("animation")) {
		return;
	}

	const Json::Value& anim_val = val["animation"];

	m_spr->SetLoop(anim_val["loop"].asBool());
	m_spr->SetInterval(anim_val["interval"].asDouble());

	m_spr->SetFPS(anim_val["fps"].asInt());

	m_spr->SetStartRandom(s2::UpdateParams(), anim_val["start_random"].asBool());

	if (anim_val.isMember("active")) {
		m_spr->SetActive(anim_val["active"].asBool(), NULL);
	}
}

void AnimSprLoader::LoadBin(const simp::NodeAnimationSpr* node)
{
	if (!m_spr) {
		return;
	}

	m_spr->SetLoop(simp::int2bool(node->loop));
	m_spr->SetInterval(simp::int2float(node->interval, 1024));

	m_spr->SetFPS(node->fps);
}

}<|endoftext|>


<commit_before>#include <debugger/pathconvert.h>
#include <debugger/impl.h>
#include <debugger/path.h>
#include <base/util/unicode.h>
#include <base/util/dynarray.h>
#include <deque>
#include <Windows.h>

namespace vscode
{
	pathconvert::pathconvert(debugger_impl* dbg)
		: debugger_(dbg)
		, sourcemap_()
		, coding_(eCoding::ansi)
	{ }

	void pathconvert::set_coding(eCoding coding)
	{
		coding_ = coding;
		source2client_.clear();
	}

	void pathconvert::add_sourcemap(const std::string& server, const std::string& client)
	{
		sourcemap_.push_back(std::make_pair(server, client));
	}

	void pathconvert::add_skipfiles(const std::string& pattern)
	{
		skipfiles_.push_back(pattern);
	}

	void pathconvert::clear()
	{
		sourcemap_.clear();
	}

	bool pathconvert::match_sourcemap(const std::string& srv, std::string& cli, const std::string& srvmatch, const std::string& climatch)
	{
		size_t i = 0;
		for (; i < srvmatch.size(); ++i) {
			if (i >= srv.size()) {
				return false;
			}
			if (path::tochar(srvmatch[i]) == path::tochar(srv[i])) {
				continue;
			}
			return false;
		}
		cli = climatch + srv.substr(i);
		return true;
	}

	bool pathconvert::server2client(const std::string& server, std::string& client)
	{
		for (auto& it : sourcemap_)
		{
			if (match_sourcemap(server, client, it.first, it.second))
			{
				return true;
			}
		}
		client = path::normalize(server);
		return true;
	}

	bool pathconvert::get(const std::string& source, std::string& client)
	{
		auto it = source2client_.find(source);
		if (it != source2client_.end())
		{
			client = it->second;
			return !client.empty();
		}

		bool res = true;
		if (debugger_->custom_) {
			std::string server;
			if (debugger_->custom_->path_convert(source, server)) {
				res = server2client(server, client);
			}
			else {
				client.clear();
				res = false;
			}
		}
		else {
			if (source[0] == '@') {
				std::string server = coding_ == eCoding::utf8
					? source.substr(1)
					: base::a2u(base::strview(source.data() + 1, source.size() - 1))
					;
				res = server2client(server, client);
			}
			else {
				client.clear();
				res = false;
			}
		}
		source2client_[source] = client;
		return res;
	}
}
<commit_msg>支持skipfiles<commit_after>#include <debugger/pathconvert.h>
#include <debugger/impl.h>
#include <debugger/path.h>
#include <base/util/unicode.h>
#include <base/util/dynarray.h>
#include <deque>
#include <Windows.h>

namespace vscode
{
	pathconvert::pathconvert(debugger_impl* dbg)
		: debugger_(dbg)
		, sourcemap_()
		, coding_(eCoding::ansi)
	{ }

	void pathconvert::set_coding(eCoding coding)
	{
		coding_ = coding;
		source2client_.clear();
	}

	void pathconvert::add_sourcemap(const std::string& server, const std::string& client)
	{
		sourcemap_.push_back(std::make_pair(server, client));
	}

	void pathconvert::add_skipfiles(const std::string& pattern)
	{
		skipfiles_.push_back(pattern);
	}

	void pathconvert::clear()
	{
		sourcemap_.clear();
	}

	bool pathconvert::match_sourcemap(const std::string& srv, std::string& cli, const std::string& srvmatch, const std::string& climatch)
	{
		size_t i = 0;
		for (; i < srvmatch.size(); ++i) {
			if (i >= srv.size()) {
				return false;
			}
			if (path::tochar(srvmatch[i]) == path::tochar(srv[i])) {
				continue;
			}
			return false;
		}
		cli = climatch + srv.substr(i);
		return true;
	}

	bool pathconvert::server2client(const std::string& server, std::string& client)
	{
		for (auto& it : skipfiles_)
		{
			if (path::glob_match(it, server))
			{
				return false;
			}
		}

		for (auto& it : sourcemap_)
		{
			if (match_sourcemap(server, client, it.first, it.second))
			{
				return true;
			}
		}
		client = path::normalize(server);
		return true;
	}

	bool pathconvert::get(const std::string& source, std::string& client)
	{
		auto it = source2client_.find(source);
		if (it != source2client_.end())
		{
			client = it->second;
			return !client.empty();
		}

		bool res = true;
		if (debugger_->custom_) {
			std::string server;
			if (debugger_->custom_->path_convert(source, server)) {
				res = server2client(server, client);
			}
			else {
				client.clear();
				res = false;
			}
		}
		else {
			if (source[0] == '@') {
				std::string server = coding_ == eCoding::utf8
					? source.substr(1)
					: base::a2u(base::strview(source.data() + 1, source.size() - 1))
					;
				res = server2client(server, client);
			}
			else {
				client.clear();
				res = false;
			}
		}
		source2client_[source] = client;
		return res;
	}
}
<|endoftext|>


<commit_before>#ifndef SKINPLUGIN_SKINNING_COMPONENT_HPP_
#define SKINPLUGIN_SKINNING_COMPONENT_HPP_

#include <SkinningPluginMacros.hpp>

#include <Core/Animation/HandleWeight.hpp>
#include <Core/Animation/Pose.hpp>
#include <Core/Animation/SkinningData.hpp>
#include <Core/Asset/HandleData.hpp>
#include <Core/Geometry/TriangleMesh.hpp>
#include <Core/Math/DualQuaternion.hpp>
#include <Core/Utils/Index.hpp>

#include <Engine/Component/Component.hpp>
#include <Engine/Managers/ComponentMessenger/ComponentMessenger.hpp>
#include <Engine/Renderer/RenderTechnique/RenderTechnique.hpp>

namespace SkinningPlugin {

/// The SkinningComponent class is responsible for applying Geometric Skinning Methods
/// on an animated object's mesh.
class SKIN_PLUGIN_API SkinningComponent : public Ra::Engine::Component {
  public:
    /// The Geometric Skinning Method.
    enum SkinningType {
        LBS = 0,  ///< Linear Blend Skinning
        DQS,      ///< Dual Quaternion Skinning
        COR,      ///< Center of Rotation skinning
        STBS_LBS, ///< Stretchable Twistable Bone Skinning with LBS
        STBS_DQS  ///< Stretchable Twistable Bone Skinning with DQS
    };

    SkinningComponent( const std::string& name, SkinningType type, Ra::Engine::Entity* entity ) :
        Component( name, entity ),
        m_skinningType( type ),
        m_isReady( false ),
        m_forceUpdate( false ),
        m_weightBone( 0 ),
        m_weightType( 0 ),
        m_showingWeights( false ) {}

    virtual ~SkinningComponent() {}

    virtual void initialize() override;

    /// Apply the Skinning Method.
    void skin();

    /// Update internal data and apply postprocesses to the mesh, e.g. normal computation.
    void endSkinning();

    /// Sets the Skinning method to use.
    void setSkinningType( SkinningType type );

    /// \returns the current skinning method.
    inline SkinningType getSkinningType() const { return m_skinningType; }

    /// Loads the skinning weights from the given Handledata.
    // TODO: for now, weights are stored in the AnimationComponent.
    virtual void handleWeightsLoading( const Ra::Core::Asset::HandleData* data,
                                       const std::string& meshName );

    /// @returns the reference skinning data.
    const Ra::Core::Skinning::RefData* getRefData() const { return &m_refData; }

    /// @returns the current Pose data.
    const Ra::Core::Skinning::FrameData* getFrameData() const { return &m_frameData; }

    /// @returns the list of DualQuaternions used for DQS.
    const Ra::Core::AlignedStdVector<Ra::Core::DualQuaternion>* getDQ() const { return &m_DQ; }

    /// Toggles display of skinning weights.
    void showWeights( bool on );

    /// Set the type of skinning weight to display:
    ///  - 0 for standard skinning weights
    ///  - 1 for stbs weights
    void showWeightsType( int type );

    /// Set the bone to show the weights of.
    void setWeightBone( uint bone );

  public:
    /// Registers the Entity name for Component communication (out).
    void setupIO( const std::string& id );

    /// Computes internal data related to the Skinning method.
    void setupSkinningType( SkinningType type );

    /// Registers the Entity name for Component communication (in/out).
    void setContentsName( const std::string& name );

  public:
    /// The Entity name for Component communication.
    std::string m_contentsName;

  private:
    // Internal function to create the skinning weights.
    void createWeightMatrix();

    /// Skinning Weight Matrix getter for CC.
    const Ra::Core::Animation::WeightMatrix* getWeightsOutput() const;

  private:
    /// The mesh name for Component communication.
    std::string m_meshName;

    /// The refrence Skinning data.
    Ra::Core::Skinning::RefData m_refData;

    /// The current Pose data.
    Ra::Core::Skinning::FrameData m_frameData;

    /// Getter for the animation skeletton.
    Ra::Engine::ComponentMessenger::CallbackTypes<Ra::Core::Animation::Skeleton>::Getter
        m_skeletonGetter;

    /// Getter/Setter for the mesh vertices.
    Ra::Engine::ComponentMessenger::CallbackTypes<Ra::Core::Vector3Array>::ReadWrite
        m_verticesWriter;

    /// Getter/Setter for the mesh normals.
    Ra::Engine::ComponentMessenger::CallbackTypes<Ra::Core::Vector3Array>::ReadWrite
        m_normalsWriter;

    // Read FMC's RO idx.
    Ra::Engine::ComponentMessenger::CallbackTypes<Ra::Core::Utils::Index>::Getter
        m_renderObjectReader;

    // Getter/Setter to the mesh
    Ra::Engine::ComponentMessenger::CallbackTypes<Ra::Core::Geometry::TriangleMesh>::ReadWrite
        m_meshWritter;

    /// The Skinning Method.
    SkinningType m_skinningType;

    /// The Skinning Weight Matrix.
    Ra::Core::Animation::WeightMatrix m_weights;

    /// Are all the required data available.
    bool m_isReady;

    /// Whether skinning is mandatory for the current frame.
    bool m_forceUpdate;

    /// The list of DualQuaternions used for DQS.
    Ra::Core::AlignedStdVector<Ra::Core::DualQuaternion> m_DQ;

    /// The duplicate vertices map, used to recompute smooth normals.
    std::vector<Ra::Core::Utils::Index> m_duplicatesMap;

    /// The skinning weights, stored per bone.
    std::map<std::string, std::vector<std::pair<uint, Scalar>>> m_loadedWeights;

    /// The STBS weights.
    Ra::Core::Animation::WeightMatrix m_weightSTBS;

    /// Initial RO shader config when not showing skinning weights.
    std::shared_ptr<Ra::Engine::RenderTechnique> m_baseTechnique;
    std::shared_ptr<Ra::Engine::RenderTechnique> m_weightTechnique;
    Ra::Core::Vector3Array m_baseUV;
    Ra::Core::Vector3Array m_weightsUV;
    uint m_weightBone;
    uint m_weightType;
    bool m_showingWeights;
};
} // namespace SkinningPlugin

#endif //  SKINPLUGIN_SKINNING_COMPONENT_HPP_
<commit_msg>Add fixme for skinning normal ;<commit_after>#ifndef SKINPLUGIN_SKINNING_COMPONENT_HPP_
#define SKINPLUGIN_SKINNING_COMPONENT_HPP_

#include <SkinningPluginMacros.hpp>

#include <Core/Animation/HandleWeight.hpp>
#include <Core/Animation/Pose.hpp>
#include <Core/Animation/SkinningData.hpp>
#include <Core/Asset/HandleData.hpp>
#include <Core/Geometry/TriangleMesh.hpp>
#include <Core/Math/DualQuaternion.hpp>
#include <Core/Utils/Index.hpp>

#include <Engine/Component/Component.hpp>
#include <Engine/Managers/ComponentMessenger/ComponentMessenger.hpp>
#include <Engine/Renderer/RenderTechnique/RenderTechnique.hpp>

namespace SkinningPlugin {

/// The SkinningComponent class is responsible for applying Geometric Skinning Methods
/// on an animated object's mesh.
class SKIN_PLUGIN_API SkinningComponent : public Ra::Engine::Component {
  public:
    /// The Geometric Skinning Method.
    enum SkinningType {
        LBS = 0,  ///< Linear Blend Skinning
        DQS,      ///< Dual Quaternion Skinning
        COR,      ///< Center of Rotation skinning
        STBS_LBS, ///< Stretchable Twistable Bone Skinning with LBS
        STBS_DQS  ///< Stretchable Twistable Bone Skinning with DQS
    };

    SkinningComponent( const std::string& name, SkinningType type, Ra::Engine::Entity* entity ) :
        Component( name, entity ),
        m_skinningType( type ),
        m_isReady( false ),
        m_forceUpdate( false ),
        m_weightBone( 0 ),
        m_weightType( 0 ),
        m_showingWeights( false ) {}

    virtual ~SkinningComponent() {}

    virtual void initialize() override;

    /// Apply the Skinning Method.
    void skin();

    /// Update internal data and apply postprocesses to the mesh, e.g. normal computation.
    void endSkinning();

    /// Sets the Skinning method to use.
    void setSkinningType( SkinningType type );

    /// \returns the current skinning method.
    inline SkinningType getSkinningType() const { return m_skinningType; }

    /// Loads the skinning weights from the given Handledata.
    // TODO: for now, weights are stored in the AnimationComponent.
    virtual void handleWeightsLoading( const Ra::Core::Asset::HandleData* data,
                                       const std::string& meshName );

    /// @returns the reference skinning data.
    const Ra::Core::Skinning::RefData* getRefData() const { return &m_refData; }

    /// @returns the current Pose data.
    const Ra::Core::Skinning::FrameData* getFrameData() const { return &m_frameData; }

    /// @returns the list of DualQuaternions used for DQS.
    const Ra::Core::AlignedStdVector<Ra::Core::DualQuaternion>* getDQ() const { return &m_DQ; }

    /// Toggles display of skinning weights.
    void showWeights( bool on );

    /// Set the type of skinning weight to display:
    ///  - 0 for standard skinning weights
    ///  - 1 for stbs weights
    void showWeightsType( int type );

    /// Set the bone to show the weights of.
    void setWeightBone( uint bone );

  public:
    /// Registers the Entity name for Component communication (out).
    void setupIO( const std::string& id );

    /// Computes internal data related to the Skinning method.
    void setupSkinningType( SkinningType type );

    /// Registers the Entity name for Component communication (in/out).
    void setContentsName( const std::string& name );

  public:
    /// The Entity name for Component communication.
    std::string m_contentsName;

  private:
    // Internal function to create the skinning weights.
    void createWeightMatrix();

    /// Skinning Weight Matrix getter for CC.
    const Ra::Core::Animation::WeightMatrix* getWeightsOutput() const;

  private:
    /// The mesh name for Component communication.
    std::string m_meshName;

    /// The refrence Skinning data.
    Ra::Core::Skinning::RefData m_refData;

    /// The current Pose data.
    Ra::Core::Skinning::FrameData m_frameData;

    /// Getter for the animation skeletton.
    Ra::Engine::ComponentMessenger::CallbackTypes<Ra::Core::Animation::Skeleton>::Getter
        m_skeletonGetter;

    /// Getter/Setter for the mesh vertices.
    Ra::Engine::ComponentMessenger::CallbackTypes<Ra::Core::Vector3Array>::ReadWrite
        m_verticesWriter;

    /// Getter/Setter for the mesh normals.
    Ra::Engine::ComponentMessenger::CallbackTypes<Ra::Core::Vector3Array>::ReadWrite
        m_normalsWriter;

    // Read FMC's RO idx.
    Ra::Engine::ComponentMessenger::CallbackTypes<Ra::Core::Utils::Index>::Getter
        m_renderObjectReader;

    // Getter/Setter to the mesh
    Ra::Engine::ComponentMessenger::CallbackTypes<Ra::Core::Geometry::TriangleMesh>::ReadWrite
        m_meshWritter;

    /// The Skinning Method.
    SkinningType m_skinningType;

    /// The Skinning Weight Matrix.
    Ra::Core::Animation::WeightMatrix m_weights;

    /// Are all the required data available.
    bool m_isReady;

    /// Whether skinning is mandatory for the current frame.
    bool m_forceUpdate;

    /// The list of DualQuaternions used for DQS.
    Ra::Core::AlignedStdVector<Ra::Core::DualQuaternion> m_DQ;

    /// The duplicate vertices map, used to recompute smooth normals.
    // FIXME: implement proper normal skinning such as http://vcg.isti.cnr.it/deformFactors/
    std::vector<Ra::Core::Utils::Index> m_duplicatesMap;

    /// The skinning weights, stored per bone.
    std::map<std::string, std::vector<std::pair<uint, Scalar>>> m_loadedWeights;

    /// The STBS weights.
    Ra::Core::Animation::WeightMatrix m_weightSTBS;

    /// Initial RO shader config when not showing skinning weights.
    std::shared_ptr<Ra::Engine::RenderTechnique> m_baseTechnique;
    std::shared_ptr<Ra::Engine::RenderTechnique> m_weightTechnique;
    Ra::Core::Vector3Array m_baseUV;
    Ra::Core::Vector3Array m_weightsUV;
    uint m_weightBone;
    uint m_weightType;
    bool m_showingWeights;
};
} // namespace SkinningPlugin

#endif //  SKINPLUGIN_SKINNING_COMPONENT_HPP_
<|endoftext|>


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

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include "./gtest.h"
#include "../src/fluent/message.hpp"
#include "../src/fluent/exception.hpp"
#include "../src/debug.h"

class MessageTest : public ::testing::Test {
private:
  enum { RP = 0, WP = 1 };

protected:
  msgpack::sbuffer sbuf_;
  msgpack::packer<msgpack::sbuffer> pkr_;
  MessageTest() : pkr_(&(this->sbuf_)) {}
  virtual ~MessageTest() {}
  virtual void SetUp() {}
  virtual void TearDown() {}

  std::string encode_msgpack(const std::string ruby_code) {
    std::stringstream ss;
    ss << "d=" << ruby_code << ";" <<
      "require 'msgpack'; STDOUT.write(d.to_msgpack) ";

    int pipe_c2p[2], pipe_p2c[2];
    pipe(pipe_c2p);
    pipe(pipe_p2c);

    pid_t pid = fork();
    if (pid == 0) {
      // Running as child.
      std::vector<std::string> arg = {"ruby"};
      char **argv = new char*[arg.size() + 1];
      for (size_t i = 0; i < arg.size(); i++) {
        argv[i] = const_cast<char*>(arg[i].c_str());
      }
      argv[arg.size()] = NULL;

      close(pipe_p2c[WP]);
      close(pipe_c2p[RP]);

      dup2(pipe_p2c[RP], 0);
      dup2(pipe_c2p[WP], 1);
      close(pipe_p2c[RP]);
      close(pipe_c2p[WP]);

      if (execvp("ruby", static_cast<char *const *>(argv)) < 0) {
        perror("execvp");
      }
    }

    // Running as parent.
    write(pipe_p2c[WP], ss.str().c_str(), ss.str().length());
    close(pipe_p2c[WP]);
    char buf[BUFSIZ];
    int stat;
    int rsize = read(pipe_c2p[RP], buf, BUFSIZ);
    int rc = waitpid(pid, &stat, 0);
    EXPECT_EQ(pid, rc);

    std::string res(buf, rsize);
    return res;
  }
};

TEST(Message, basic) {
  fluent::Message::Map *obj = new fluent::Message::Map();
  msgpack::sbuffer sbuf;
  msgpack::packer<msgpack::sbuffer> pkr(&sbuf);

  EXPECT_TRUE(obj->set("abc", 1));

  /*
    require 'msgpack'; a=[]; {'abc'=>1}.to_msgpack.each_byte{|v|
    a.push(sprintf("0x%02X", v))};puts "{#{a.join(', ')}};"
  */
  uint8_t data[] = {0x81, 0xa3, 0x61, 0x62, 0x63, 0x01};
  obj->to_msgpack(&pkr);
  EXPECT_EQ(sbuf.size(), sizeof(data));
  EXPECT_TRUE(0 == memcmp(sbuf.data(), data, sizeof(data)));
}

TEST_F(MessageTest, Map) {
  fluent::Message::Map *obj = new fluent::Message::Map();
  // Bool
  EXPECT_TRUE(obj->set("bool", true));
  // Float
  EXPECT_TRUE(obj->set("float", 34.567));
  // Fixnum
  EXPECT_TRUE(obj->set("int", 2345));
  // String
  EXPECT_TRUE(obj->set("str", "test"));

  std::string expect = encode_msgpack("{'bool'=>true, 'float'=>34.567, "
                                      "'int'=>2345, 'str'=>'test', }");
  obj->to_msgpack(&pkr_);
  EXPECT_EQ(sbuf_.size(), expect.length());
  EXPECT_TRUE(0 == memcmp(sbuf_.data(), expect.data(), sbuf_.size()));
}

TEST_F(MessageTest, Array) {
  fluent::Message::Array *obj = new fluent::Message::Array();
  // Bool
  obj->push(true);
  // Float
  obj->push(34.567);
  // Fixnum
  obj->push(2345);
  // String
  obj->push("test");

  std::string expect = encode_msgpack("[true, 34.567, 2345, 'test']");
  obj->to_msgpack(&pkr_);
  EXPECT_EQ(sbuf_.size(), expect.length());
  EXPECT_TRUE(0 == memcmp(sbuf_.data(), expect.data(), sbuf_.size()));
}

TEST_F(MessageTest, NestArray) {
  fluent::Message::Array *obj = new fluent::Message::Array();
  obj->push("a");  // ["a"]
  fluent::Message::Array *arr = obj->retain_array(); // ["a", []]
  ASSERT_TRUE(arr != nullptr);
  arr->push("b"); // ["a", ["b"]]
  arr->push(1);   // ["a", ["b", 1]]
  fluent::Message::Map *map = obj->retain_map();  // ["a", ["b", 1], {}]
  ASSERT_TRUE(map != nullptr);
  map->set("c", 1); // ["a", ["b", 1], {"c": 1}}]

  std::string expect = encode_msgpack("['a',['b', 1],{'c'=>1}]");
  obj->to_msgpack(&pkr_);
  EXPECT_EQ(sbuf_.size(), expect.length());
  EXPECT_TRUE(0 == memcmp(sbuf_.data(), expect.data(), sbuf_.size()));
}

TEST_F(MessageTest, NestMap) {
  fluent::Message::Map *obj = new fluent::Message::Map();

  obj->set("a", 1);  // {"a":1}
  fluent::Message::Array *arr = obj->retain_array("b"); // {"a":1, "b": []}
  ASSERT_TRUE(arr != nullptr);
  arr->push(2); // {"a":1, "b": [2]}
  arr->push(3); // {"a":1, "b": [2, 3]}
  fluent::Message::Map *map = obj->retain_map("c");
  // {"a":1, "b": [2, 3], "c": {}}
  ASSERT_TRUE(map != nullptr);
  map->set("d", 4);   // {"a":1, "b": [2, 3], "c": {"d":4}}

  std::string expect = encode_msgpack("{'a'=>1, 'b'=>[2,3], 'c'=>{'d'=>4}}");
  obj->to_msgpack(&pkr_);
  EXPECT_EQ(sbuf_.size(), expect.length());
  EXPECT_TRUE(0 == memcmp(sbuf_.data(), expect.data(), sbuf_.size()));
}

TEST_F(MessageTest, NotOverwriteMap) {
  fluent::Message::Map *obj = new fluent::Message::Map();

  EXPECT_TRUE(obj->set("a", 1));
  EXPECT_FALSE(obj->set("a", 2));

  std::string expect = encode_msgpack("{'a'=>1}");

  obj->to_msgpack(&pkr_);
  EXPECT_EQ(sbuf_.size(), expect.length());
  EXPECT_TRUE(0 == memcmp(sbuf_.data(), expect.data(), sbuf_.size()));
}

TEST(Message, link) {
  // TODO: add tests
}

TEST(Message, MapGetObject) {
  fluent::Message::Map *obj = new fluent::Message::Map();
  obj->set("i", 1);
  obj->set("s", "test");
  obj->set("f", 3.141592);
  obj->set("b", true);
  fluent::Message::Map *map = obj->retain_map("m");
  map->set("gnome", 1);
  fluent::Message::Array *arr = obj->retain_array("a");
  arr->push("druid");

  // Check Key.
  EXPECT_TRUE(obj->has_key("i"));
  EXPECT_TRUE(obj->has_key("s"));
  EXPECT_TRUE(obj->has_key("f"));
  EXPECT_TRUE(obj->has_key("b"));
  EXPECT_TRUE(obj->has_key("m"));
  EXPECT_TRUE(obj->has_key("a"));
  EXPECT_FALSE(obj->has_key("x"));

  // Get objects.
  const fluent::Message::Object &obj_i = obj->get("i");
  const fluent::Message::Object &obj_s = obj->get("s");
  const fluent::Message::Object &obj_f = obj->get("f");
  const fluent::Message::Object &obj_b = obj->get("b");
  const fluent::Message::Object &obj_m = obj->get("m");
  const fluent::Message::Object &obj_a = obj->get("a");
  EXPECT_THROW(obj->get("x"), fluent::Exception::KeyError);

  // Check types.
  EXPECT_TRUE(obj_i.is<fluent::Message::Fixnum>());
  EXPECT_TRUE(obj_s.is<fluent::Message::String>());
  EXPECT_TRUE(obj_f.is<fluent::Message::Float>());
  EXPECT_TRUE(obj_b.is<fluent::Message::Bool>());
  EXPECT_TRUE(obj_m.is<fluent::Message::Map>());
  EXPECT_TRUE(obj_a.is<fluent::Message::Array>());

  // Convert to appropriate type.
  const fluent::Message::Fixnum &i = obj_i.as<fluent::Message::Fixnum>();
  const fluent::Message::String &s = obj_s.as<fluent::Message::String>();
  const fluent::Message::Float &f = obj_f.as<fluent::Message::Float>();
  const fluent::Message::Bool &b = obj_b.as<fluent::Message::Bool>();
  const fluent::Message::Map &m = obj_m.as<fluent::Message::Map>();
  const fluent::Message::Array &a = obj_a.as<fluent::Message::Array>();
  EXPECT_THROW(obj_i.as<fluent::Message::String>(),
               fluent::Exception::TypeError);
  EXPECT_THROW(obj_i.as<fluent::Message::Float>(),
               fluent::Exception::TypeError);

  // Check values.
  EXPECT_EQ(i.val(), 1);
  EXPECT_EQ(s.val(), "test");
  EXPECT_EQ(f.val(), 3.141592);
  EXPECT_EQ(b.val(), true);

  EXPECT_TRUE(m.has_key("gnome"));
  EXPECT_FALSE(m.has_key("x"));
  EXPECT_EQ(m.get("gnome").as<fluent::Message::Fixnum>().val(), 1);
  EXPECT_EQ(a.size(), 1);
  EXPECT_EQ(a.get(0).as<fluent::Message::String>().val(), "druid");

  EXPECT_THROW(a.get(1), fluent::Exception::IndexError);
}
<commit_msg>add Message::clone test<commit_after>/*-
 * Copyright (c) 2015 Masayoshi Mizutani <mizutani@sfc.wide.ad.jp>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include "./gtest.h"
#include "../src/fluent/message.hpp"
#include "../src/fluent/exception.hpp"
#include "../src/debug.h"

class MessageTest : public ::testing::Test {
private:
  enum { RP = 0, WP = 1 };

protected:
  msgpack::sbuffer sbuf_;
  msgpack::packer<msgpack::sbuffer> pkr_;
  MessageTest() : pkr_(&(this->sbuf_)) {}
  virtual ~MessageTest() {}
  virtual void SetUp() {}
  virtual void TearDown() {}

  std::string encode_msgpack(const std::string ruby_code) {
    std::stringstream ss;
    ss << "d=" << ruby_code << ";" <<
      "require 'msgpack'; STDOUT.write(d.to_msgpack) ";

    int pipe_c2p[2], pipe_p2c[2];
    pipe(pipe_c2p);
    pipe(pipe_p2c);

    pid_t pid = fork();
    if (pid == 0) {
      // Running as child.
      std::vector<std::string> arg = {"ruby"};
      char **argv = new char*[arg.size() + 1];
      for (size_t i = 0; i < arg.size(); i++) {
        argv[i] = const_cast<char*>(arg[i].c_str());
      }
      argv[arg.size()] = NULL;

      close(pipe_p2c[WP]);
      close(pipe_c2p[RP]);

      dup2(pipe_p2c[RP], 0);
      dup2(pipe_c2p[WP], 1);
      close(pipe_p2c[RP]);
      close(pipe_c2p[WP]);

      if (execvp("ruby", static_cast<char *const *>(argv)) < 0) {
        perror("execvp");
      }
    }

    // Running as parent.
    write(pipe_p2c[WP], ss.str().c_str(), ss.str().length());
    close(pipe_p2c[WP]);
    char buf[BUFSIZ];
    int stat;
    int rsize = read(pipe_c2p[RP], buf, BUFSIZ);
    int rc = waitpid(pid, &stat, 0);
    EXPECT_EQ(pid, rc);

    std::string res(buf, rsize);
    return res;
  }
};

TEST(Message, basic) {
  fluent::Message::Map *obj = new fluent::Message::Map();
  msgpack::sbuffer sbuf;
  msgpack::packer<msgpack::sbuffer> pkr(&sbuf);

  EXPECT_TRUE(obj->set("abc", 1));

  /*
    require 'msgpack'; a=[]; {'abc'=>1}.to_msgpack.each_byte{|v|
    a.push(sprintf("0x%02X", v))};puts "{#{a.join(', ')}};"
  */
  uint8_t data[] = {0x81, 0xa3, 0x61, 0x62, 0x63, 0x01};
  obj->to_msgpack(&pkr);
  EXPECT_EQ(sbuf.size(), sizeof(data));
  EXPECT_TRUE(0 == memcmp(sbuf.data(), data, sizeof(data)));
}

TEST_F(MessageTest, Map) {
  fluent::Message::Map *obj = new fluent::Message::Map();
  // Bool
  EXPECT_TRUE(obj->set("bool", true));
  // Float
  EXPECT_TRUE(obj->set("float", 34.567));
  // Fixnum
  EXPECT_TRUE(obj->set("int", 2345));
  // String
  EXPECT_TRUE(obj->set("str", "test"));

  std::string expect = encode_msgpack("{'bool'=>true, 'float'=>34.567, "
                                      "'int'=>2345, 'str'=>'test', }");
  obj->to_msgpack(&pkr_);
  EXPECT_EQ(sbuf_.size(), expect.length());
  EXPECT_TRUE(0 == memcmp(sbuf_.data(), expect.data(), sbuf_.size()));
}

TEST_F(MessageTest, Array) {
  fluent::Message::Array *obj = new fluent::Message::Array();
  // Bool
  obj->push(true);
  // Float
  obj->push(34.567);
  // Fixnum
  obj->push(2345);
  // String
  obj->push("test");

  std::string expect = encode_msgpack("[true, 34.567, 2345, 'test']");
  obj->to_msgpack(&pkr_);
  EXPECT_EQ(sbuf_.size(), expect.length());
  EXPECT_TRUE(0 == memcmp(sbuf_.data(), expect.data(), sbuf_.size()));
}

TEST_F(MessageTest, NestArray) {
  fluent::Message::Array *obj = new fluent::Message::Array();
  obj->push("a");  // ["a"]
  fluent::Message::Array *arr = obj->retain_array(); // ["a", []]
  ASSERT_TRUE(arr != nullptr);
  arr->push("b"); // ["a", ["b"]]
  arr->push(1);   // ["a", ["b", 1]]
  fluent::Message::Map *map = obj->retain_map();  // ["a", ["b", 1], {}]
  ASSERT_TRUE(map != nullptr);
  map->set("c", 1); // ["a", ["b", 1], {"c": 1}}]

  std::string expect = encode_msgpack("['a',['b', 1],{'c'=>1}]");
  obj->to_msgpack(&pkr_);
  EXPECT_EQ(sbuf_.size(), expect.length());
  EXPECT_TRUE(0 == memcmp(sbuf_.data(), expect.data(), sbuf_.size()));
}

TEST_F(MessageTest, NestMap) {
  fluent::Message::Map *obj = new fluent::Message::Map();

  obj->set("a", 1);  // {"a":1}
  fluent::Message::Array *arr = obj->retain_array("b"); // {"a":1, "b": []}
  ASSERT_TRUE(arr != nullptr);
  arr->push(2); // {"a":1, "b": [2]}
  arr->push(3); // {"a":1, "b": [2, 3]}
  fluent::Message::Map *map = obj->retain_map("c");
  // {"a":1, "b": [2, 3], "c": {}}
  ASSERT_TRUE(map != nullptr);
  map->set("d", 4);   // {"a":1, "b": [2, 3], "c": {"d":4}}

  std::string expect = encode_msgpack("{'a'=>1, 'b'=>[2,3], 'c'=>{'d'=>4}}");
  obj->to_msgpack(&pkr_);
  EXPECT_EQ(sbuf_.size(), expect.length());
  EXPECT_TRUE(0 == memcmp(sbuf_.data(), expect.data(), sbuf_.size()));
}

TEST_F(MessageTest, NotOverwriteMap) {
  fluent::Message::Map *obj = new fluent::Message::Map();

  EXPECT_TRUE(obj->set("a", 1));
  EXPECT_FALSE(obj->set("a", 2));

  std::string expect = encode_msgpack("{'a'=>1}");

  obj->to_msgpack(&pkr_);
  EXPECT_EQ(sbuf_.size(), expect.length());
  EXPECT_TRUE(0 == memcmp(sbuf_.data(), expect.data(), sbuf_.size()));
}

TEST(Message, linkedMessage) {
  // TODO: add tests
}

TEST(Message, MapGetObject) {
  fluent::Message::Map *obj = new fluent::Message::Map();
  obj->set("i", 1);
  obj->set("s", "test");
  obj->set("f", 3.141592);
  obj->set("b", true);
  fluent::Message::Map *map = obj->retain_map("m");
  map->set("gnome", 1);
  fluent::Message::Array *arr = obj->retain_array("a");
  arr->push("druid");

  // Check Key.
  EXPECT_TRUE(obj->has_key("i"));
  EXPECT_TRUE(obj->has_key("s"));
  EXPECT_TRUE(obj->has_key("f"));
  EXPECT_TRUE(obj->has_key("b"));
  EXPECT_TRUE(obj->has_key("m"));
  EXPECT_TRUE(obj->has_key("a"));
  EXPECT_FALSE(obj->has_key("x"));

  // Get objects.
  const fluent::Message::Object &obj_i = obj->get("i");
  const fluent::Message::Object &obj_s = obj->get("s");
  const fluent::Message::Object &obj_f = obj->get("f");
  const fluent::Message::Object &obj_b = obj->get("b");
  const fluent::Message::Object &obj_m = obj->get("m");
  const fluent::Message::Object &obj_a = obj->get("a");
  EXPECT_THROW(obj->get("x"), fluent::Exception::KeyError);

  // Check types.
  EXPECT_TRUE(obj_i.is<fluent::Message::Fixnum>());
  EXPECT_TRUE(obj_s.is<fluent::Message::String>());
  EXPECT_TRUE(obj_f.is<fluent::Message::Float>());
  EXPECT_TRUE(obj_b.is<fluent::Message::Bool>());
  EXPECT_TRUE(obj_m.is<fluent::Message::Map>());
  EXPECT_TRUE(obj_a.is<fluent::Message::Array>());

  // Convert to appropriate type.
  const fluent::Message::Fixnum &i = obj_i.as<fluent::Message::Fixnum>();
  const fluent::Message::String &s = obj_s.as<fluent::Message::String>();
  const fluent::Message::Float &f = obj_f.as<fluent::Message::Float>();
  const fluent::Message::Bool &b = obj_b.as<fluent::Message::Bool>();
  const fluent::Message::Map &m = obj_m.as<fluent::Message::Map>();
  const fluent::Message::Array &a = obj_a.as<fluent::Message::Array>();
  EXPECT_THROW(obj_i.as<fluent::Message::String>(),
               fluent::Exception::TypeError);
  EXPECT_THROW(obj_i.as<fluent::Message::Float>(),
               fluent::Exception::TypeError);

  // Check values.
  EXPECT_EQ(i.val(), 1);
  EXPECT_EQ(s.val(), "test");
  EXPECT_EQ(f.val(), 3.141592);
  EXPECT_EQ(b.val(), true);

  EXPECT_TRUE(m.has_key("gnome"));
  EXPECT_FALSE(m.has_key("x"));
  EXPECT_EQ(m.get("gnome").as<fluent::Message::Fixnum>().val(), 1);
  EXPECT_EQ(a.size(), 1);
  EXPECT_EQ(a.get(0).as<fluent::Message::String>().val(), "druid");

  EXPECT_THROW(a.get(1), fluent::Exception::IndexError);
}

TEST(Message, clone) {
  fluent::Message *msg1 = new fluent::Message("race.gnome");
  msg1->set("i", 1);
  msg1->set("s", "warlock");
  msg1->set("f", 3.141592);
  msg1->set("b", true);
  fluent::Message::Map *map = msg1->retain_map("m");
  map->set("hunter", 1);
  fluent::Message::Array *arr = msg1->retain_array("a");
  arr->push("druid");

  fluent::Message *msg2 = msg1->clone();
  // other pointer
  EXPECT_NE(msg1, msg2);
  EXPECT_EQ(msg1->tag(), msg2->tag());
  EXPECT_EQ(msg1->ts(),  msg2->ts());

  // Get objects.
  const fluent::Message::Object &obj_i = msg2->get("i");
  const fluent::Message::Object &obj_s = msg2->get("s");
  const fluent::Message::Object &obj_f = msg2->get("f");
  const fluent::Message::Object &obj_b = msg2->get("b");
  const fluent::Message::Object &obj_m = msg2->get("m");
  const fluent::Message::Object &obj_a = msg2->get("a");
  EXPECT_THROW(msg2->get("x"), fluent::Exception::KeyError);

  // Check types.
  EXPECT_TRUE(obj_i.is<fluent::Message::Fixnum>());
  EXPECT_TRUE(obj_s.is<fluent::Message::String>());
  EXPECT_TRUE(obj_f.is<fluent::Message::Float>());
  EXPECT_TRUE(obj_b.is<fluent::Message::Bool>());
  EXPECT_TRUE(obj_m.is<fluent::Message::Map>());
  EXPECT_TRUE(obj_a.is<fluent::Message::Array>());

  // Convert to appropriate type.
  const fluent::Message::Fixnum &i = obj_i.as<fluent::Message::Fixnum>();
  const fluent::Message::String &s = obj_s.as<fluent::Message::String>();
  const fluent::Message::Float &f = obj_f.as<fluent::Message::Float>();
  const fluent::Message::Bool &b = obj_b.as<fluent::Message::Bool>();
  const fluent::Message::Map &m = obj_m.as<fluent::Message::Map>();
  const fluent::Message::Array &a = obj_a.as<fluent::Message::Array>();
  EXPECT_THROW(obj_i.as<fluent::Message::String>(),
               fluent::Exception::TypeError);
  EXPECT_THROW(obj_i.as<fluent::Message::Float>(),
               fluent::Exception::TypeError);

  // Check values.
  EXPECT_EQ(i.val(), 1);
  EXPECT_EQ(s.val(), "warlock");
  EXPECT_EQ(f.val(), 3.141592);
  EXPECT_EQ(b.val(), true);

  EXPECT_TRUE(m.has_key("hunter"));
  EXPECT_FALSE(m.has_key("x"));
  EXPECT_EQ(m.get("hunter").as<fluent::Message::Fixnum>().val(), 1);
  EXPECT_EQ(a.size(), 1);
  EXPECT_EQ(a.get(0).as<fluent::Message::String>().val(), "druid");

  EXPECT_THROW(a.get(1), fluent::Exception::IndexError);

  // Check independece among the original message and copied one.
  msg1->set("new", "priest");
  EXPECT_EQ("priest", msg1->get("new").as<fluent::Message::String>().val());
  EXPECT_THROW(msg2->get("new"), fluent::Exception::KeyError);
  delete msg1;
  delete msg2;
}
<|endoftext|>


<commit_before><commit_msg>Added support for pixel based LOD's and set the default priority scale to 1.0<commit_after><|endoftext|>