<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2017                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#ifndef CAF_FWD_HPP
#define CAF_FWD_HPP

#include <memory>
#include <cstdint>

namespace caf {

// -- 1 param templates --------------------------------------------------------

template <class> class param;
template <class> class stream;
template <class> class optional;
template <class> class expected;
template <class> class downstream;
template <class> class intrusive_ptr;
template <class> class behavior_type_of;
template <class> class trivial_match_case;
template <class> class weak_intrusive_ptr;

template <class> struct timeout_definition;

// -- 3 param templates --------------------------------------------------------

template <class, class, int> class actor_cast_access;

template <class, class, class> class broadcast_topic_scatterer;
template <class, class, class> class random_topic_scatterer;

// -- variadic templates -------------------------------------------------------

template <class...> class result;
template <class...> class delegated;
template <class...> class typed_actor;
template <class...> class typed_actor_pointer;
template <class...> class typed_response_promise;
template <class...> class typed_event_based_actor;

// -- variadic templates with 1 fixed argument ---------------------------------

template <class, class...> class fused_scatterer;
template <class, class...> class annotated_stream;

// -- classes ------------------------------------------------------------------

class actor;
class error;
class group;
class message;
class node_id;
class behavior;
class duration;
class resumable;
class stream_id;
class actor_addr;
class actor_pool;
class message_id;
class serializer;
class actor_proxy;
class local_actor;
class ref_counted;
class actor_config;
class actor_system;
class deserializer;
class group_module;
class message_view;
class scoped_actor;
class inbound_path;
class outbound_path;
class abstract_actor;
class abstract_group;
class actor_registry;
class blocking_actor;
class execution_unit;
class proxy_registry;
class stream_manager;
class random_gatherer;
class stream_gatherer;
class actor_companion;
class mailbox_element;
class message_handler;
class scheduled_actor;
class stream_scatterer;
class response_promise;
class event_based_actor;
class type_erased_tuple;
class type_erased_value;
class stream_msg_visitor;
class actor_control_block;
class actor_system_config;
class uniform_type_info_map;
class forwarding_actor_proxy;

// -- structs ------------------------------------------------------------------

struct unit_t;
struct exit_msg;
struct down_msg;
struct stream_msg;
struct timeout_msg;
struct group_down_msg;
struct invalid_actor_t;
struct invalid_actor_addr_t;
struct illegal_message_element;
struct prohibit_top_level_spawn_marker;

// -- enums --------------------------------------------------------------------

enum class stream_priority;
enum class atom_value : uint64_t;

// -- aliases ------------------------------------------------------------------

using actor_id = uint64_t;

// -- marker classes for mixins ------------------------------------------------

namespace mixin {

struct subscriber_base;

} // namespace mixin

// -- I/O classes --------------------------------------------------------------

namespace io {

class hook;
class broker;
class middleman;

namespace basp {

struct header;

} // namespace basp

} // namespace io

// -- OpenCL classes -----------------------------------------------------------

namespace opencl {

class manager;

} // namespace opencl

// -- scheduler classes --------------------------------------------------------

namespace scheduler {

class abstract_worker;
class abstract_coordinator;

} // namespace scheduler

// -- OpenSSL classes ----------------------------------------------------------

namespace openssl {

class manager;

} // namespace openssl

// -- detail classes -----------------------------------------------------------

namespace detail {

template <class> class type_erased_value_impl;
template <class> class stream_distribution_tree;

class disposer;
class message_data;
class group_manager;
class private_thread;
class dynamic_message_data;

} // namespace detail

// -- weak pointer aliases -----------------------------------------------------

using weak_actor_ptr = weak_intrusive_ptr<actor_control_block>;

// -- intrusive pointer aliases ------------------------------------------------

using strong_actor_ptr = intrusive_ptr<actor_control_block>;
using stream_manager_ptr = intrusive_ptr<stream_manager>;

// -- unique pointer aliases ---------------------------------------------------

using type_erased_value_ptr = std::unique_ptr<type_erased_value>;
using mailbox_element_ptr = std::unique_ptr<mailbox_element, detail::disposer>;

} // namespace caf

#endif // CAF_FWD_HPP
<commit_msg>Add forward declaration for test_coordinator<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2017                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#ifndef CAF_FWD_HPP
#define CAF_FWD_HPP

#include <memory>
#include <cstdint>

namespace caf {

// -- 1 param templates --------------------------------------------------------

template <class> class param;
template <class> class stream;
template <class> class optional;
template <class> class expected;
template <class> class downstream;
template <class> class intrusive_ptr;
template <class> class behavior_type_of;
template <class> class trivial_match_case;
template <class> class weak_intrusive_ptr;

template <class> struct timeout_definition;

// -- 3 param templates --------------------------------------------------------

template <class, class, int> class actor_cast_access;

template <class, class, class> class broadcast_topic_scatterer;
template <class, class, class> class random_topic_scatterer;

// -- variadic templates -------------------------------------------------------

template <class...> class result;
template <class...> class delegated;
template <class...> class typed_actor;
template <class...> class typed_actor_pointer;
template <class...> class typed_response_promise;
template <class...> class typed_event_based_actor;

// -- variadic templates with 1 fixed argument ---------------------------------

template <class, class...> class fused_scatterer;
template <class, class...> class annotated_stream;

// -- classes ------------------------------------------------------------------

class actor;
class error;
class group;
class message;
class node_id;
class behavior;
class duration;
class resumable;
class stream_id;
class actor_addr;
class actor_pool;
class message_id;
class serializer;
class actor_proxy;
class local_actor;
class ref_counted;
class actor_config;
class actor_system;
class deserializer;
class group_module;
class message_view;
class scoped_actor;
class inbound_path;
class outbound_path;
class abstract_actor;
class abstract_group;
class actor_registry;
class blocking_actor;
class execution_unit;
class proxy_registry;
class stream_manager;
class random_gatherer;
class stream_gatherer;
class actor_companion;
class mailbox_element;
class message_handler;
class scheduled_actor;
class stream_scatterer;
class response_promise;
class event_based_actor;
class type_erased_tuple;
class type_erased_value;
class stream_msg_visitor;
class actor_control_block;
class actor_system_config;
class uniform_type_info_map;
class forwarding_actor_proxy;

// -- structs ------------------------------------------------------------------

struct unit_t;
struct exit_msg;
struct down_msg;
struct stream_msg;
struct timeout_msg;
struct group_down_msg;
struct invalid_actor_t;
struct invalid_actor_addr_t;
struct illegal_message_element;
struct prohibit_top_level_spawn_marker;

// -- enums --------------------------------------------------------------------

enum class stream_priority;
enum class atom_value : uint64_t;

// -- aliases ------------------------------------------------------------------

using actor_id = uint64_t;

// -- marker classes for mixins ------------------------------------------------

namespace mixin {

struct subscriber_base;

} // namespace mixin

// -- I/O classes --------------------------------------------------------------

namespace io {

class hook;
class broker;
class middleman;

namespace basp {

struct header;

} // namespace basp

} // namespace io

// -- OpenCL classes -----------------------------------------------------------

namespace opencl {

class manager;

} // namespace opencl

// -- scheduler classes --------------------------------------------------------

namespace scheduler {

class abstract_worker;
class test_coordinator;
class abstract_coordinator;

} // namespace scheduler

// -- OpenSSL classes ----------------------------------------------------------

namespace openssl {

class manager;

} // namespace openssl

// -- detail classes -----------------------------------------------------------

namespace detail {

template <class> class type_erased_value_impl;
template <class> class stream_distribution_tree;

class disposer;
class message_data;
class group_manager;
class private_thread;
class dynamic_message_data;

} // namespace detail

// -- weak pointer aliases -----------------------------------------------------

using weak_actor_ptr = weak_intrusive_ptr<actor_control_block>;

// -- intrusive pointer aliases ------------------------------------------------

using strong_actor_ptr = intrusive_ptr<actor_control_block>;
using stream_manager_ptr = intrusive_ptr<stream_manager>;

// -- unique pointer aliases ---------------------------------------------------

using type_erased_value_ptr = std::unique_ptr<type_erased_value>;
using mailbox_element_ptr = std::unique_ptr<mailbox_element, detail::disposer>;

} // namespace caf

#endif // CAF_FWD_HPP
<|endoftext|>


<commit_before>
#pragma GCC diagnostic ignored "-Wconversion"
#include "JitVM.h"
#include <libevm/VM.h>
#include <libevm/VMFactory.h>
#include <libdevcrypto/SHA3.h>
#include <evmjit/libevmjit/ExecutionEngine.h>
#include "Utils.h"

namespace dev
{
namespace eth
{

extern "C" void env_sload(); // fake declaration for linker symbol stripping workaround, see a call below

bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _step)
{
	using namespace jit;

	auto rejected = false;
	// TODO: Rejecting transactions with gas limit > 2^63 can be used by attacker to take JIT out of scope
	rejected |= m_gas > std::numeric_limits<decltype(m_data.gas)>::max(); // Do not accept requests with gas > 2^63 (int64 max)
	rejected |= _ext.gasPrice > std::numeric_limits<decltype(m_data.gasPrice)>::max();
	rejected |= _ext.currentBlock.number > std::numeric_limits<decltype(m_data.number)>::max();
	rejected |= _ext.currentBlock.timestamp > std::numeric_limits<decltype(m_data.timestamp)>::max();

	if (rejected)
	{
		UNTESTED;
		std::cerr << "Rejected\n";
		VMFactory::setKind(VMKind::Interpreter);
		m_fallbackVM = VMFactory::create(m_gas);
		VMFactory::setKind(VMKind::JIT);
		return m_fallbackVM->go(_ext, _onOp, _step);
	}

	m_data.gas 			= static_cast<decltype(m_data.gas)>(m_gas);
	m_data.gasPrice		= static_cast<decltype(m_data.gasPrice)>(_ext.gasPrice);
	m_data.callData 	= _ext.data.data();
	m_data.callDataSize = _ext.data.size();
	m_data.address      = eth2llvm(fromAddress(_ext.myAddress));
	m_data.caller       = eth2llvm(fromAddress(_ext.caller));
	m_data.origin       = eth2llvm(fromAddress(_ext.origin));
	m_data.callValue    = eth2llvm(_ext.value);
	m_data.coinBase     = eth2llvm(fromAddress(_ext.currentBlock.coinbaseAddress));
	m_data.difficulty   = eth2llvm(_ext.currentBlock.difficulty);
	m_data.gasLimit     = eth2llvm(_ext.currentBlock.gasLimit);
	m_data.number 		= static_cast<decltype(m_data.number)>(_ext.currentBlock.number);
	m_data.timestamp 	= static_cast<decltype(m_data.timestamp)>(_ext.currentBlock.timestamp);
	m_data.code     	= _ext.code.data();
	m_data.codeSize 	= _ext.code.size();
	m_data.codeHash		= eth2llvm(sha3(_ext.code));

	auto env = reinterpret_cast<Env*>(&_ext);
	auto exitCode = m_engine.run(&m_data, env);
	switch (exitCode)
	{
	case ReturnCode::Suicide:
		_ext.suicide(right160(llvm2eth(m_data.address)));
		break;

	case ReturnCode::BadJumpDestination:
		BOOST_THROW_EXCEPTION(BadJumpDestination());
	case ReturnCode::OutOfGas:
		BOOST_THROW_EXCEPTION(OutOfGas());
	case ReturnCode::StackTooSmall:
		BOOST_THROW_EXCEPTION(StackTooSmall());
	case ReturnCode::BadInstruction:
		BOOST_THROW_EXCEPTION(BadInstruction());
	case ReturnCode::LinkerWorkaround:	// never happens
		env_sload();					// but forces linker to include env_* JIT callback functions
		break;
	default:
		break;
	}

	m_gas = m_data.gas; // TODO: Remove m_gas field
	return {std::get<0>(m_engine.returnData), std::get<1>(m_engine.returnData)};
}

}
}
<commit_msg>Correct and tested EVM JIT to Interpreter fallback in case of high gas limit<commit_after>
#pragma GCC diagnostic ignored "-Wconversion"

#include "JitVM.h"

#include <libdevcore/Log.h>
#include <libdevcrypto/SHA3.h>
#include <libevm/VM.h>
#include <libevm/VMFactory.h>
#include <evmjit/libevmjit/ExecutionEngine.h>

#include "Utils.h"

namespace dev
{
namespace eth
{

extern "C" void env_sload(); // fake declaration for linker symbol stripping workaround, see a call below

bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _step)
{
	using namespace jit;

	auto rejected = false;
	// TODO: Rejecting transactions with gas limit > 2^63 can be used by attacker to take JIT out of scope
	rejected |= m_gas > std::numeric_limits<decltype(m_data.gas)>::max(); // Do not accept requests with gas > 2^63 (int64 max)
	rejected |= _ext.gasPrice > std::numeric_limits<decltype(m_data.gasPrice)>::max();
	rejected |= _ext.currentBlock.number > std::numeric_limits<decltype(m_data.number)>::max();
	rejected |= _ext.currentBlock.timestamp > std::numeric_limits<decltype(m_data.timestamp)>::max();

	if (rejected)
	{
		cwarn << "Execution rejected by EVM JIT (gas limit: " << m_gas << "), executing with interpreter";
		VMFactory::setKind(VMKind::Interpreter);
		m_fallbackVM = VMFactory::create(m_gas);
		VMFactory::setKind(VMKind::JIT);
		auto&& output = m_fallbackVM->go(_ext, _onOp, _step);
		m_gas = m_fallbackVM->gas(); // copy remaining gas, Executive expects it
		return output;
	}

	m_data.gas 			= static_cast<decltype(m_data.gas)>(m_gas);
	m_data.gasPrice		= static_cast<decltype(m_data.gasPrice)>(_ext.gasPrice);
	m_data.callData 	= _ext.data.data();
	m_data.callDataSize = _ext.data.size();
	m_data.address      = eth2llvm(fromAddress(_ext.myAddress));
	m_data.caller       = eth2llvm(fromAddress(_ext.caller));
	m_data.origin       = eth2llvm(fromAddress(_ext.origin));
	m_data.callValue    = eth2llvm(_ext.value);
	m_data.coinBase     = eth2llvm(fromAddress(_ext.currentBlock.coinbaseAddress));
	m_data.difficulty   = eth2llvm(_ext.currentBlock.difficulty);
	m_data.gasLimit     = eth2llvm(_ext.currentBlock.gasLimit);
	m_data.number 		= static_cast<decltype(m_data.number)>(_ext.currentBlock.number);
	m_data.timestamp 	= static_cast<decltype(m_data.timestamp)>(_ext.currentBlock.timestamp);
	m_data.code     	= _ext.code.data();
	m_data.codeSize 	= _ext.code.size();
	m_data.codeHash		= eth2llvm(sha3(_ext.code));

	auto env = reinterpret_cast<Env*>(&_ext);
	auto exitCode = m_engine.run(&m_data, env);
	switch (exitCode)
	{
	case ReturnCode::Suicide:
		_ext.suicide(right160(llvm2eth(m_data.address)));
		break;

	case ReturnCode::BadJumpDestination:
		BOOST_THROW_EXCEPTION(BadJumpDestination());
	case ReturnCode::OutOfGas:
		BOOST_THROW_EXCEPTION(OutOfGas());
	case ReturnCode::StackTooSmall:
		BOOST_THROW_EXCEPTION(StackTooSmall());
	case ReturnCode::BadInstruction:
		BOOST_THROW_EXCEPTION(BadInstruction());
	case ReturnCode::LinkerWorkaround:	// never happens
		env_sload();					// but forces linker to include env_* JIT callback functions
		break;
	default:
		break;
	}

	m_gas = m_data.gas; // TODO: Remove m_gas field
	return {std::get<0>(m_engine.returnData), std::get<1>(m_engine.returnData)};
}

}
}
<|endoftext|>


<commit_before>// type_promotion.hpp
//
// Copyright (c) 2016 Piotr K. Semenov (piotr.k.semenov at gmail dot com)
// Distributed under the New BSD License. (See accompanying file LICENSE)

/*!
 \file type_promotion.hpp

 Provides the run-time overflow/underflow safety checks for basic arithmetics operations.
*/

#ifndef INC_LIBQ_TYPE_PROMOTION_HPP_
#define INC_LIBQ_TYPE_PROMOTION_HPP_

#include <boost/integer.hpp>
#include <boost/mpl/eval_if.hpp>

#include <limits>
#include <type_traits>

namespace libq {
namespace details {

/*!
 \brief
 \tparam T fixed-point type
 \tparam delta_n
 \tparam delta_f
*/
template<typename T, std::size_t delta_n, std::size_t delta_f, int delte_e>
class type_promotion_base {
  public:
    using promoted_type = T;
};

template<typename T, std::size_t n, std::size_t f, int e, class op, class up, std::size_t delta_n, std::size_t delta_f, int delta_e>  // NOLINT
class type_promotion_base<libq::fixed_point<T, n, f, e, op, up>, delta_n, delta_f, delta_e> {  // NOLINT
    using Q = libq::fixed_point<T, n, f, e, op, up>;
    using this_class = type_promotion_base<Q, delta_n, delta_f, delta_e>;

    using max_type = typename std::conditional<Q::is_signed,
                                               std::intmax_t,
                                               std::uintmax_t>::type;
    enum: std::size_t {
        sign_bit = static_cast<std::size_t>(Q::is_signed),

        n = Q::bits_for_integral,
        f = Q::bits_for_fractional
    };
    enum: int {
        e = Q::scaling_factor_exponent
    };

    // simple "type" wrapper for lazy instantiation of its "internal" type
    struct storage_type_promotion_traits {
        // Note, boost::int_t takes a sign bit into account
        using type = typename std::conditional<Q::is_signed,
                                               typename boost::int_t<(n + delta_n) + (f + delta_f) + this_class::sign_bit>::least,  // NOLINT
                                               typename boost::uint_t<(n + delta_n) + (f + delta_f)>::least>::type;  // NOLINT
    };
    struct storage_type_default_traits {
        using type = typename Q::storage_type;
    };

  public:
    enum: bool {
        is_expandable = ((n + delta_n) + (f + delta_f) <=
                            std::numeric_limits<max_type>::digits)
    };

    /*!
     \brief
    */
    using promoted_storage_type =
        typename boost::mpl::eval_if_c<this_class::is_expandable,
                                       typename this_class::storage_type_promotion_traits,  // NOLINT
                                       typename this_class::storage_type_default_traits>::type;  // NOLINT

    using promoted_type = typename std::conditional<this_class::is_expandable,
        libq::fixed_point<promoted_storage_type, n + delta_n, f + delta_f, e + delta_e, typename Q::overflow_policy, typename Q::underflow_policy>,  // NOLINT
        libq::fixed_point<promoted_storage_type, n, f, e, typename Q::overflow_policy, typename Q::underflow_policy> >::type;  // NOLINT
};

}  // namespace details
}  // namespace libq
#endif  // INC_LIBQ_TYPE_PROMOTION_HPP_
<commit_msg>[FIX] CPPLint compliance for type_promotion.hpp<commit_after>// type_promotion.hpp
//
// Copyright (c) 2016 Piotr K. Semenov (piotr.k.semenov at gmail dot com)
// Distributed under the New BSD License. (See accompanying file LICENSE)

/*!
 \file type_promotion.hpp

 Provides the run-time overflow/underflow safety checks for basic arithmetics operations.
*/

#ifndef INC_LIBQ_TYPE_PROMOTION_HPP_
#define INC_LIBQ_TYPE_PROMOTION_HPP_

#include <boost/integer.hpp>
#include <boost/mpl/eval_if.hpp>

#include <limits>
#include <type_traits>

namespace libq {
namespace details {

/*!
 \brief
 \tparam T fixed-point type
 \tparam delta_n
 \tparam delta_f
*/
template<typename T, std::size_t delta_n, std::size_t delta_f, int delte_e>
class type_promotion_base {
 public:
    using promoted_type = T;
};

template<typename T, std::size_t n, std::size_t f, int e, class op, class up, std::size_t delta_n, std::size_t delta_f, int delta_e>  // NOLINT
class type_promotion_base<libq::fixed_point<T, n, f, e, op, up>, delta_n, delta_f, delta_e> {  // NOLINT
    using Q = libq::fixed_point<T, n, f, e, op, up>;
    using this_class = type_promotion_base<Q, delta_n, delta_f, delta_e>;

    using max_type = typename std::conditional<Q::is_signed,
                                               std::intmax_t,
                                               std::uintmax_t>::type;
    enum: std::size_t {
        sign_bit = static_cast<std::size_t>(Q::is_signed),

        n = Q::bits_for_integral,
        f = Q::bits_for_fractional
    };
    enum: int {
        e = Q::scaling_factor_exponent
    };

    // simple "type" wrapper for lazy instantiation of its "internal" type
    struct storage_type_promotion_traits {
        // Note, boost::int_t takes a sign bit into account
        using type = typename std::conditional<Q::is_signed,
                                               typename boost::int_t<(n + delta_n) + (f + delta_f) + this_class::sign_bit>::least,  // NOLINT
                                               typename boost::uint_t<(n + delta_n) + (f + delta_f)>::least>::type;  // NOLINT
    };
    struct storage_type_default_traits {
        using type = typename Q::storage_type;
    };

 public:
    enum: bool {
        is_expandable = ((n + delta_n) + (f + delta_f) <=
                            std::numeric_limits<max_type>::digits)
    };

    /*!
     \brief
    */
    using promoted_storage_type =
        typename boost::mpl::eval_if_c<this_class::is_expandable,
                                       typename this_class::storage_type_promotion_traits,  // NOLINT
                                       typename this_class::storage_type_default_traits>::type;  // NOLINT

    using promoted_type = typename std::conditional<this_class::is_expandable,
        libq::fixed_point<promoted_storage_type, n + delta_n, f + delta_f, e + delta_e, typename Q::overflow_policy, typename Q::underflow_policy>,  // NOLINT
        libq::fixed_point<promoted_storage_type, n, f, e, typename Q::overflow_policy, typename Q::underflow_policy> >::type;  // NOLINT
};

}  // namespace details
}  // namespace libq
#endif  // INC_LIBQ_TYPE_PROMOTION_HPP_
<|endoftext|>


<commit_before>// This file is part of the VroomJs library.
//
// Author:
//     Federico Di Gregorio <fog@initd.org>
//
// Copyright © 2013 Federico Di Gregorio <fog@initd.org>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include "vroomjs.h"

using namespace v8;

extern "C" jsvalue jsvalue_alloc_array(const int32_t length);

static Handle<Value> managed_prop_get(Local<String> name, const AccessorInfo& info)
{
    Local<Object> self = info.Holder();
    Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
    ManagedRef* ref = (ManagedRef*)wrap->Value();
    return ref->GetPropertyValue(name);
}

static Handle<Value> managed_prop_set(Local<String> name, Local<Value> value, const AccessorInfo& info)
{
    Local<Object> self = info.Holder();
    Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
    ManagedRef* ref = (ManagedRef*)wrap->Value();
    return ref->SetPropertyValue(name, value);
}

static Handle<Value> managed_call(const Arguments& args)
{
    Local<Object> self = args.Holder();
    Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
    ManagedRef* ref = (ManagedRef*)wrap->Value();
    return ref->Invoke(args);
}

static void managed_destroy(Persistent<Value> object, void* parameter)
{
    Persistent<Object> self = Persistent<Object>::Cast(object);
    Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
    delete (ManagedRef*)wrap->Value();
    object.Dispose();
}

JsEngine* JsEngine::New()
{
    JsEngine* engine = new JsEngine();
    if (engine != NULL) {
        engine->isolate_ = Isolate::New();
        Locker locker(engine->isolate_);
        Isolate::Scope isolate_scope(engine->isolate_);
        engine->context_ = new Persistent<Context>(Context::New());

        (*(engine->context_))->Enter();

        // Setup the template we'll use for all managed object references.
        HandleScope scope;
        Handle<ObjectTemplate> o = ObjectTemplate::New();
        o->SetInternalFieldCount(1);
        o->SetNamedPropertyHandler(managed_prop_get, managed_prop_set);
        o->SetCallAsFunctionHandler(managed_call);
        Persistent<ObjectTemplate> p = Persistent<ObjectTemplate>::New(o);
        engine->managed_template_ = new Persistent<ObjectTemplate>(p);
    }

    return engine;
}

void JsEngine::Dispose()
{
    {
        Locker locker(isolate_);
        Isolate::Scope isolate_scope(isolate_);
        managed_template_->Dispose();
        delete managed_template_;
        context_->Dispose();
        delete context_;
    }

    isolate_->Dispose();
}

jsvalue JsEngine::Execute(const uint16_t* str)
{
    jsvalue v;

    Locker locker(isolate_);
    Isolate::Scope isolate_scope(isolate_);
    (*context_)->Enter();

    HandleScope scope;
    TryCatch trycatch;

    Handle<String> source = String::New(str);
    Handle<Script> script = Script::Compile(source);
    if (!script.IsEmpty()) {
        Local<Value> result = script->Run();
        if (result.IsEmpty())
            v = ErrorFromV8(trycatch);
        else
            v = AnyFromV8(result);
    }
    else {
        v = ErrorFromV8(trycatch);
    }

    (*context_)->Exit();

    return v;
}

jsvalue JsEngine::SetVariable(const uint16_t* name, jsvalue value)
{
    Locker locker(isolate_);
    Isolate::Scope isolate_scope(isolate_);
    (*context_)->Enter();

    HandleScope scope;

    Handle<Value> v = AnyToV8(value);

    if ((*context_)->Global()->Set(String::New(name), v) == false) {
        // TODO: Return an error if set failed.
    }

    (*context_)->Exit();

    return AnyFromV8(Null());
}

jsvalue JsEngine::GetVariable(const uint16_t* name)
{
    jsvalue v;

    Locker locker(isolate_);
    Isolate::Scope isolate_scope(isolate_);
    (*context_)->Enter();

    HandleScope scope;
    TryCatch trycatch;

    Local<Value> value = (*context_)->Global()->Get(String::New(name));
    if (!value.IsEmpty()) {
        v = AnyFromV8(value);
    }
    else {
        v = ErrorFromV8(trycatch);
    }

    (*context_)->Exit();

    return v;
}

jsvalue JsEngine::GetPropertyValue(Persistent<Object>* obj, const uint16_t* name)
{
    jsvalue v;

    Locker locker(isolate_);
    Isolate::Scope isolate_scope(isolate_);
    (*context_)->Enter();

    HandleScope scope;
    TryCatch trycatch;

    Local<Value> value = (*obj)->Get(String::New(name));
    if (!value.IsEmpty()) {
        v = AnyFromV8(value);
    }
    else {
        v = ErrorFromV8(trycatch);
    }

    (*context_)->Exit();

    return v;
}

jsvalue JsEngine::SetPropertyValue(Persistent<Object>* obj, const uint16_t* name, jsvalue value)
{
    Locker locker(isolate_);
    Isolate::Scope isolate_scope(isolate_);
    (*context_)->Enter();

    HandleScope scope;

    Handle<Value> v = AnyToV8(value);

    if ((*obj)->Set(String::New(name), v) == false) {
        // TODO: Return an error if set failed.
    }

    (*context_)->Exit();

    return AnyFromV8(Null());
}

jsvalue JsEngine::InvokeProperty(Persistent<Object>* obj, const uint16_t* name, jsvalue args)
{
    jsvalue v;

    Locker locker(isolate_);
    Isolate::Scope isolate_scope(isolate_);
    (*context_)->Enter();

    HandleScope scope;
    TryCatch trycatch;

    Local<Value> prop = (*obj)->Get(String::New(name));
    if (prop.IsEmpty() || !prop->IsFunction()) {
        v = StringFromV8(String::New("property not found or isn't a function"));
        v.type = JSVALUE_TYPE_ERROR;
    }
    else {
        Local<Value> argv[args.length];
        ArrayToV8Args(args, argv);
        // TODO: Check ArrayToV8Args return value (but right now can't fail, right?)
        Local<Function> func = Local<Function>::Cast(prop);
        Local<Value> value = func->Call(*obj, args.length, argv);
        if (!value.IsEmpty()) {
            v = AnyFromV8(value);
        }
        else {
            v = ErrorFromV8(trycatch);
        }
    }

    (*context_)->Exit();

    return v;
}

jsvalue JsEngine::ErrorFromV8(TryCatch& trycatch)
{
    jsvalue v;

    Local<Value> exception = trycatch.Exception();

    v.type = JSVALUE_TYPE_UNKNOWN_ERROR;
    v.value.str = 0;
    v.length = 0;

    // If this is a managed exception we need to place its ID inside the jsvalue
    // and set the type JSVALUE_TYPE_MANAGED_ERROR to make sure the CLR side will
    // throw on it. Else we just wrap and return the exception Object. Note that
    // this is far from perfect because we ignore both the Message object and the
    // stack stack trace. If the exception is not an object (but just a string,
    // for example) we convert it with toString() and return that as an Exception.
    // TODO: return a composite/special object with stack trace information.

    if (exception->IsObject()) {
        Local<Object> obj = Local<Object>::Cast(exception);
        if (obj->InternalFieldCount() == 1) {
            ManagedRef* ref = (ManagedRef*)obj->GetPointerFromInternalField(0);
            v.type = JSVALUE_TYPE_MANAGED_ERROR;
            v.length = ref->Id();
        }
        else  {
            v = WrappedFromV8(obj);
            v.type = JSVALUE_TYPE_WRAPPED_ERROR;
        }
    }
    else if (!exception.IsEmpty()) {
        v = StringFromV8(exception);
        v.type = JSVALUE_TYPE_ERROR;
    }

    return v;
}

jsvalue JsEngine::StringFromV8(Handle<Value> value)
{
    jsvalue v;

    Local<String> s = value->ToString();
    v.length = s->Length();
    v.value.str = new uint16_t[v.length+1];
    if (v.value.str != NULL) {
        s->Write(v.value.str);
        v.type = JSVALUE_TYPE_STRING;
    }

    return v;
}

jsvalue JsEngine::WrappedFromV8(Handle<Object> obj)
{
    jsvalue v;

    v.type = JSVALUE_TYPE_WRAPPED;
    v.length = 0;
    v.value.ptr = new Persistent<Object>(Persistent<Object>::New(obj));

    return v;
}

jsvalue JsEngine::ManagedFromV8(Handle<Object> obj)
{
    jsvalue v;

    ManagedRef* ref = (ManagedRef*)obj->GetPointerFromInternalField(0);
    v.type = JSVALUE_TYPE_MANAGED;
    v.length = ref->Id();
    v.value.str = 0;

    return v;
}

jsvalue JsEngine::AnyFromV8(Handle<Value> value)
{
    jsvalue v;

    // Initialize to a generic error.
    v.type = JSVALUE_TYPE_UNKNOWN_ERROR;
    v.length = 0;
    v.value.str = 0;

    if (value->IsNull() || value->IsUndefined()) {
        v.type = JSVALUE_TYPE_NULL;
    }
    else if (value->IsBoolean()) {
        v.type = JSVALUE_TYPE_BOOLEAN;
        v.value.i32 = value->BooleanValue() ? 1 : 0;
    }
    else if (value->IsInt32()) {
        v.type = JSVALUE_TYPE_INTEGER;
        v.value.i32 = value->Int32Value();
    }
    else if (value->IsUint32()) {
        v.type = JSVALUE_TYPE_INDEX;
        v.value.i64 = value->Uint32Value();
    }
    else if (value->IsNumber()) {
        v.type = JSVALUE_TYPE_NUMBER;
        v.value.num = value->NumberValue();
    }
    else if (value->IsString()) {
        v = StringFromV8(value);
    }
    else if (value->IsDate()) {
        v.type = JSVALUE_TYPE_DATE;
        v.value.num = value->NumberValue();
    }
    else if (value->IsArray()) {
        Handle<Array> object = Handle<Array>::Cast(value->ToObject());
        v.length = object->Length();
        jsvalue* array = new jsvalue[v.length];
        if (array != NULL) {
            for(int i = 0; i < v.length; i++) {
                array[i] = AnyFromV8(object->Get(i));
            }
            v.type = JSVALUE_TYPE_ARRAY;
            v.value.arr = array;
        }
    }
    else if (value->IsFunction()) {
        // TODO: how do we represent this on the CLR side? Delegate?
    }
    else if (value->IsObject()) {
        Handle<Object> obj = Handle<Object>::Cast(value);
        if (obj->InternalFieldCount() ==     1)
            v = ManagedFromV8(obj);
        else
            v = WrappedFromV8(obj);
    }

    return v;
}

Handle<Value> JsEngine::AnyToV8(jsvalue v)
{
    if (v.type == JSVALUE_TYPE_NULL) {
        return Null();
    }
    if (v.type == JSVALUE_TYPE_BOOLEAN) {
        return Boolean::New(v.value.i32);
    }
    if (v.type == JSVALUE_TYPE_INTEGER) {
        return Int32::New(v.value.i32);
    }
    if (v.type == JSVALUE_TYPE_NUMBER) {
        return Number::New(v.value.num);
    }
    if (v.type == JSVALUE_TYPE_STRING) {
        return String::New(v.value.str);
    }
    if (v.type == JSVALUE_TYPE_DATE) {
        return Date::New(v.value.num);
    }

    // This is an ID to a managed object that lives inside the JsEngine keep-alive
    // cache. We just wrap it and the pointer to the engine inside an External. A
    // managed error is still a CLR object so it is wrapped exactly as a normal
    // managed object.

    if (v.type == JSVALUE_TYPE_MANAGED || v.type == JSVALUE_TYPE_MANAGED_ERROR) {
        ManagedRef* ref = new ManagedRef(this, v.length);
        Persistent<Object> obj = Persistent<Object>::New((*(managed_template_))->NewInstance());
        obj->SetInternalField(0, External::New(ref));
        obj.MakeWeak(NULL, managed_destroy);
        return obj;
    }

    return Null();
}

int32_t JsEngine::ArrayToV8Args(jsvalue value, Handle<Value> preallocatedArgs[])
{
    if (value.type != JSVALUE_TYPE_ARRAY)
        return -1;

    for (int i=0 ; i < value.length ; i++) {
        preallocatedArgs[i] = AnyToV8(value.value.arr[i]);
    }

    return value.length;
}

jsvalue JsEngine::ArrayFromArguments(const Arguments& args)
{
    jsvalue v = jsvalue_alloc_array(args.Length());

    for (int i=0 ; i < v.length ; i++) {
        v.value.arr[i] = AnyFromV8(args[i]);
    }

    return v;
}<commit_msg>[libvroomjs] Added missing array conversion<commit_after>// This file is part of the VroomJs library.
//
// Author:
//     Federico Di Gregorio <fog@initd.org>
//
// Copyright © 2013 Federico Di Gregorio <fog@initd.org>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include "vroomjs.h"

using namespace v8;

extern "C" jsvalue jsvalue_alloc_array(const int32_t length);

static Handle<Value> managed_prop_get(Local<String> name, const AccessorInfo& info)
{
    Local<Object> self = info.Holder();
    Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
    ManagedRef* ref = (ManagedRef*)wrap->Value();
    return ref->GetPropertyValue(name);
}

static Handle<Value> managed_prop_set(Local<String> name, Local<Value> value, const AccessorInfo& info)
{
    Local<Object> self = info.Holder();
    Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
    ManagedRef* ref = (ManagedRef*)wrap->Value();
    return ref->SetPropertyValue(name, value);
}

static Handle<Value> managed_call(const Arguments& args)
{
    Local<Object> self = args.Holder();
    Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
    ManagedRef* ref = (ManagedRef*)wrap->Value();
    return ref->Invoke(args);
}

static void managed_destroy(Persistent<Value> object, void* parameter)
{
    Persistent<Object> self = Persistent<Object>::Cast(object);
    Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
    delete (ManagedRef*)wrap->Value();
    object.Dispose();
}

JsEngine* JsEngine::New()
{
    JsEngine* engine = new JsEngine();
    if (engine != NULL) {
        engine->isolate_ = Isolate::New();
        Locker locker(engine->isolate_);
        Isolate::Scope isolate_scope(engine->isolate_);
        engine->context_ = new Persistent<Context>(Context::New());

        (*(engine->context_))->Enter();

        // Setup the template we'll use for all managed object references.
        HandleScope scope;
        Handle<ObjectTemplate> o = ObjectTemplate::New();
        o->SetInternalFieldCount(1);
        o->SetNamedPropertyHandler(managed_prop_get, managed_prop_set);
        o->SetCallAsFunctionHandler(managed_call);
        Persistent<ObjectTemplate> p = Persistent<ObjectTemplate>::New(o);
        engine->managed_template_ = new Persistent<ObjectTemplate>(p);
    }

    return engine;
}

void JsEngine::Dispose()
{
    {
        Locker locker(isolate_);
        Isolate::Scope isolate_scope(isolate_);
        managed_template_->Dispose();
        delete managed_template_;
        context_->Dispose();
        delete context_;
    }

    isolate_->Dispose();
}

jsvalue JsEngine::Execute(const uint16_t* str)
{
    jsvalue v;

    Locker locker(isolate_);
    Isolate::Scope isolate_scope(isolate_);
    (*context_)->Enter();

    HandleScope scope;
    TryCatch trycatch;

    Handle<String> source = String::New(str);
    Handle<Script> script = Script::Compile(source);
    if (!script.IsEmpty()) {
        Local<Value> result = script->Run();
        if (result.IsEmpty())
            v = ErrorFromV8(trycatch);
        else
            v = AnyFromV8(result);
    }
    else {
        v = ErrorFromV8(trycatch);
    }

    (*context_)->Exit();

    return v;
}

jsvalue JsEngine::SetVariable(const uint16_t* name, jsvalue value)
{
    Locker locker(isolate_);
    Isolate::Scope isolate_scope(isolate_);
    (*context_)->Enter();

    HandleScope scope;

    Handle<Value> v = AnyToV8(value);

    if ((*context_)->Global()->Set(String::New(name), v) == false) {
        // TODO: Return an error if set failed.
    }

    (*context_)->Exit();

    return AnyFromV8(Null());
}

jsvalue JsEngine::GetVariable(const uint16_t* name)
{
    jsvalue v;

    Locker locker(isolate_);
    Isolate::Scope isolate_scope(isolate_);
    (*context_)->Enter();

    HandleScope scope;
    TryCatch trycatch;

    Local<Value> value = (*context_)->Global()->Get(String::New(name));
    if (!value.IsEmpty()) {
        v = AnyFromV8(value);
    }
    else {
        v = ErrorFromV8(trycatch);
    }

    (*context_)->Exit();

    return v;
}

jsvalue JsEngine::GetPropertyValue(Persistent<Object>* obj, const uint16_t* name)
{
    jsvalue v;

    Locker locker(isolate_);
    Isolate::Scope isolate_scope(isolate_);
    (*context_)->Enter();

    HandleScope scope;
    TryCatch trycatch;

    Local<Value> value = (*obj)->Get(String::New(name));
    if (!value.IsEmpty()) {
        v = AnyFromV8(value);
    }
    else {
        v = ErrorFromV8(trycatch);
    }

    (*context_)->Exit();

    return v;
}

jsvalue JsEngine::SetPropertyValue(Persistent<Object>* obj, const uint16_t* name, jsvalue value)
{
    Locker locker(isolate_);
    Isolate::Scope isolate_scope(isolate_);
    (*context_)->Enter();

    HandleScope scope;

    Handle<Value> v = AnyToV8(value);

    if ((*obj)->Set(String::New(name), v) == false) {
        // TODO: Return an error if set failed.
    }

    (*context_)->Exit();

    return AnyFromV8(Null());
}

jsvalue JsEngine::InvokeProperty(Persistent<Object>* obj, const uint16_t* name, jsvalue args)
{
    jsvalue v;

    Locker locker(isolate_);
    Isolate::Scope isolate_scope(isolate_);
    (*context_)->Enter();

    HandleScope scope;
    TryCatch trycatch;

    Local<Value> prop = (*obj)->Get(String::New(name));
    if (prop.IsEmpty() || !prop->IsFunction()) {
        v = StringFromV8(String::New("property not found or isn't a function"));
        v.type = JSVALUE_TYPE_ERROR;
    }
    else {
        Local<Value> argv[args.length];
        ArrayToV8Args(args, argv);
        // TODO: Check ArrayToV8Args return value (but right now can't fail, right?)
        Local<Function> func = Local<Function>::Cast(prop);
        Local<Value> value = func->Call(*obj, args.length, argv);
        if (!value.IsEmpty()) {
            v = AnyFromV8(value);
        }
        else {
            v = ErrorFromV8(trycatch);
        }
    }

    (*context_)->Exit();

    return v;
}

jsvalue JsEngine::ErrorFromV8(TryCatch& trycatch)
{
    jsvalue v;

    Local<Value> exception = trycatch.Exception();

    v.type = JSVALUE_TYPE_UNKNOWN_ERROR;
    v.value.str = 0;
    v.length = 0;

    // If this is a managed exception we need to place its ID inside the jsvalue
    // and set the type JSVALUE_TYPE_MANAGED_ERROR to make sure the CLR side will
    // throw on it. Else we just wrap and return the exception Object. Note that
    // this is far from perfect because we ignore both the Message object and the
    // stack stack trace. If the exception is not an object (but just a string,
    // for example) we convert it with toString() and return that as an Exception.
    // TODO: return a composite/special object with stack trace information.

    if (exception->IsObject()) {
        Local<Object> obj = Local<Object>::Cast(exception);
        if (obj->InternalFieldCount() == 1) {
            ManagedRef* ref = (ManagedRef*)obj->GetPointerFromInternalField(0);
            v.type = JSVALUE_TYPE_MANAGED_ERROR;
            v.length = ref->Id();
        }
        else  {
            v = WrappedFromV8(obj);
            v.type = JSVALUE_TYPE_WRAPPED_ERROR;
        }
    }
    else if (!exception.IsEmpty()) {
        v = StringFromV8(exception);
        v.type = JSVALUE_TYPE_ERROR;
    }

    return v;
}

jsvalue JsEngine::StringFromV8(Handle<Value> value)
{
    jsvalue v;

    Local<String> s = value->ToString();
    v.length = s->Length();
    v.value.str = new uint16_t[v.length+1];
    if (v.value.str != NULL) {
        s->Write(v.value.str);
        v.type = JSVALUE_TYPE_STRING;
    }

    return v;
}

jsvalue JsEngine::WrappedFromV8(Handle<Object> obj)
{
    jsvalue v;

    v.type = JSVALUE_TYPE_WRAPPED;
    v.length = 0;
    v.value.ptr = new Persistent<Object>(Persistent<Object>::New(obj));

    return v;
}

jsvalue JsEngine::ManagedFromV8(Handle<Object> obj)
{
    jsvalue v;

    ManagedRef* ref = (ManagedRef*)obj->GetPointerFromInternalField(0);
    v.type = JSVALUE_TYPE_MANAGED;
    v.length = ref->Id();
    v.value.str = 0;

    return v;
}

jsvalue JsEngine::AnyFromV8(Handle<Value> value)
{
    jsvalue v;

    // Initialize to a generic error.
    v.type = JSVALUE_TYPE_UNKNOWN_ERROR;
    v.length = 0;
    v.value.str = 0;

    if (value->IsNull() || value->IsUndefined()) {
        v.type = JSVALUE_TYPE_NULL;
    }
    else if (value->IsBoolean()) {
        v.type = JSVALUE_TYPE_BOOLEAN;
        v.value.i32 = value->BooleanValue() ? 1 : 0;
    }
    else if (value->IsInt32()) {
        v.type = JSVALUE_TYPE_INTEGER;
        v.value.i32 = value->Int32Value();
    }
    else if (value->IsUint32()) {
        v.type = JSVALUE_TYPE_INDEX;
        v.value.i64 = value->Uint32Value();
    }
    else if (value->IsNumber()) {
        v.type = JSVALUE_TYPE_NUMBER;
        v.value.num = value->NumberValue();
    }
    else if (value->IsString()) {
        v = StringFromV8(value);
    }
    else if (value->IsDate()) {
        v.type = JSVALUE_TYPE_DATE;
        v.value.num = value->NumberValue();
    }
    else if (value->IsArray()) {
        Handle<Array> object = Handle<Array>::Cast(value->ToObject());
        v.length = object->Length();
        jsvalue* array = new jsvalue[v.length];
        if (array != NULL) {
            for(int i = 0; i < v.length; i++) {
                array[i] = AnyFromV8(object->Get(i));
            }
            v.type = JSVALUE_TYPE_ARRAY;
            v.value.arr = array;
        }
    }
    else if (value->IsFunction()) {
        // TODO: how do we represent this on the CLR side? Delegate?
    }
    else if (value->IsObject()) {
        Handle<Object> obj = Handle<Object>::Cast(value);
        if (obj->InternalFieldCount() ==     1)
            v = ManagedFromV8(obj);
        else
            v = WrappedFromV8(obj);
    }

    return v;
}

Handle<Value> JsEngine::AnyToV8(jsvalue v)
{
    if (v.type == JSVALUE_TYPE_NULL) {
        return Null();
    }
    if (v.type == JSVALUE_TYPE_BOOLEAN) {
        return Boolean::New(v.value.i32);
    }
    if (v.type == JSVALUE_TYPE_INTEGER) {
        return Int32::New(v.value.i32);
    }
    if (v.type == JSVALUE_TYPE_NUMBER) {
        return Number::New(v.value.num);
    }
    if (v.type == JSVALUE_TYPE_STRING) {
        return String::New(v.value.str);
    }
    if (v.type == JSVALUE_TYPE_DATE) {
        return Date::New(v.value.num);
    }

    // Arrays are converted to JS native arrays.

    if (v.type == JSVALUE_TYPE_ARRAY) {
        Local<Array> a = Array::New(v.length);
        for(int i = 0; i < v.length; i++) {
            a->Set(i, AnyToV8(v.value.arr[i]));
        }
        return a;
    }

    // This is an ID to a managed object that lives inside the JsEngine keep-alive
    // cache. We just wrap it and the pointer to the engine inside an External. A
    // managed error is still a CLR object so it is wrapped exactly as a normal
    // managed object.

    if (v.type == JSVALUE_TYPE_MANAGED || v.type == JSVALUE_TYPE_MANAGED_ERROR) {
        ManagedRef* ref = new ManagedRef(this, v.length);
        Persistent<Object> obj = Persistent<Object>::New((*(managed_template_))->NewInstance());
        obj->SetInternalField(0, External::New(ref));
        obj.MakeWeak(NULL, managed_destroy);
        return obj;
    }

    return Null();
}

int32_t JsEngine::ArrayToV8Args(jsvalue value, Handle<Value> preallocatedArgs[])
{
    if (value.type != JSVALUE_TYPE_ARRAY)
        return -1;

    for (int i=0 ; i < value.length ; i++) {
        preallocatedArgs[i] = AnyToV8(value.value.arr[i]);
    }

    return value.length;
}

jsvalue JsEngine::ArrayFromArguments(const Arguments& args)
{
    jsvalue v = jsvalue_alloc_array(args.Length());

    for (int i=0 ; i < v.length ; i++) {
        v.value.arr[i] = AnyFromV8(args[i]);
    }

    return v;
}<|endoftext|>


<commit_before>/**
 * \file listnode.hpp
 * \author Dan Obermiller
 * \brief Implementation of a list node for a singly linked list.
 * \remarks Uses templates and operator overloading to provide an almost
 * enjoyable interface.
 */

#ifndef LISTNODE_HPP
#define LISTNODE_HPP 1

#include <string>
#include <iostream>

template <typename T>
class ListNode;

/**
 * \brief Overloads the << operator to allow writing a node's contents
 *  to a string or stream.
 **/
template <typename T> std::ostream& operator<<(
	std::ostream& str, const ListNode<T>& node);

template <typename T>
/**
 * \brief A node in a singly linked list.
 */
class ListNode
{
public:
	/**
	 * \brief The default constructor is disabled.
	 */
	ListNode() = delete;

	/**
	 * \brief All nodes must be value initialized.
	 */
	ListNode(T value);

	/**
	 * \brief Constructor that is provided the next node.
	 */
	ListNode(T value, ListNode<T>* node);

	/**
	 * \brief Returns the value within the node.
	 */
	 T& getValue();

	/**
	 * \brief Returns a pointer to the next node.
	 * \post The node is unchanged.
	 */
	ListNode* getNext() const;

	/**
	 * \brief Sets the next node in the list.
	 */
	void setNext(ListNode* node);

private:
	T value_;
	ListNode<T>* next_;
};

template <typename T> inline ListNode<T>::ListNode(T value) :
	value_(value), next_(nullptr) {
}

template <typename T> inline
ListNode<T>::ListNode(T value, ListNode<T>* node) :
	value_(value), next_(node) {
}

template <typename T> inline T& ListNode<T>::getValue()
{
	return value_;
}

template <typename T> inline ListNode<T>* ListNode<T>::getNext() const
{
	return next_;
}

template <typename T> inline
void ListNode<T>::setNext(ListNode<T>* node)
{
	next_ = node;
}

/**
 * \brief Overloads the << operator to allow writing a node's contents
 *  to a string or stream.
 **/
template <typename T> inline std::ostream& operator<<(
	std::ostream& str, const ListNode<T>& node)
{
	str << node.getValue();
	return str;
}

#endif
<commit_msg>Resolved the non-const function, hopefully<commit_after>/**
 * \file listnode.hpp
 * \author Dan Obermiller
 * \brief Implementation of a list node for a singly linked list.
 * \remarks Uses templates and operator overloading to provide an almost
 * enjoyable interface.
 */

#ifndef LISTNODE_HPP
#define LISTNODE_HPP 1

#include <string>
#include <iostream>

/**
 * \brief A node in a singly linked list.
 */
template <typename T>
class ListNode;

/**
 * \brief Overloads the << operator to allow writing a node's contents
 *  to a string or stream.
 **/
template <typename T> std::ostream& operator<<(
	std::ostream& str, const ListNode<T>& node);

template <typename T>
class ListNode
{
public:
	/**
	 * \brief The default constructor is disabled.
	 */
	ListNode() = delete;

	/**
	 * \brief All nodes must be value initialized.
	 */
	ListNode(T value);

	/**
	 * \brief Constructor that is provided the next node.
	 */
	ListNode(T value, ListNode<T>* node);

	/**
	 * \brief Returns the value within the node.
	 */
	 T& getValue();

	/**
	 * \brief Provides a const reference tot he value.
	 */
	T& getCValue() const;

	/**
	 * \brief Returns a pointer to the next node.
	 * \post The node is unchanged.
	 */
	ListNode* getNext() const;

	/**
	 * \brief Sets the next node in the list.
	 */
	void setNext(ListNode* node);

private:
	T value_;
	ListNode<T>* next_;
};

template <typename T> inline ListNode<T>::ListNode(T value) :
	value_(value), next_(nullptr) {
}

template <typename T> inline
ListNode<T>::ListNode(T value, ListNode<T>* node) :
	value_(value), next_(node) {
}

template <typename T> inline T& ListNode<T>::getValue()
{
	return value_;
}

template <typename T> inline T& ListNode<T>::getCValue() const
{
	return value_;
}

template <typename T> inline ListNode<T>* ListNode<T>::getNext() const
{
	return next_;
}

template <typename T> inline
void ListNode<T>::setNext(ListNode<T>* node)
{
	next_ = node;
}

template <typename T> inline std::ostream& operator<<(
	std::ostream& str, const ListNode<T>& node)
{
	str << node.getCValue();
	return str;
}

#endif
<|endoftext|>


<commit_before>#include "analogjoystick.hpp"

void setupJoystick()
{
	pinMode(joystickXADC, INPUT);
	pinMode(joystickXADC, INPUT);
	pinMode(joystickEnable, INPUT);
	digitalWrite(joystickEnable, HIGH);
}
/*
void disableJoystick()
{
	digitalWrite(joystickEnable, LOW);
}
*/
void getJoystickReading(int* X, int* Y)
{
	*X = analogRead(joystickXADC);
	*Y = analogRead(joystickYADC);
}

int sign(int n)
{
	if(n > 0)
	{
		return 1;
	}
	return -1;
}

/* Get joystick position and turn it into motor velocities */
//
//   +y
//  -x +x
//    -y
//
void joystickSetMotors()
{
	int xAxis = 0;
	int yAxis = 0;

	const int XMiddle = 1023 / 2;
	const int YMiddle = 1023 / 2;

	getJoystickReading(&xAxis, &yAxis);

	//shift 0
	xAxis -= XMiddle;
	yAxis -= YMiddle;

	//make x go the right dir
	//xAxis *= -1;

	/* Apply deadzones */
	if (abs(xAxis) < DEAD_ZONE)
	{
		xAxis = 0;
	}
	if (abs(yAxis) < DEAD_ZONE)
	{
		yAxis = 0;
	}

	/* Calculate drive outputs -- magic*/
	//int leftVelocity = .5*float(yAxis) + 2 * sign(xAxis) * sqrt(abs(xAxis));
	//int rightVelocity = .5*float(yAxis) - 2 * sign(xAxis) * sqrt(abs(xAxis));
	int leftVelocity = yAxis + 3 * sign(xAxis) * sqrt(abs(xAxis));
	int rightVelocity = yAxis - 3 * sign(xAxis) * sqrt(abs(xAxis));

	/* Limit drive velcocities to vaild values and convert them to drive speeds and directions */

	byte leftSpeed = min(abs(leftVelocity), 255);
	byte leftDir = (leftVelocity < 0) ? MC_MOTOR_REVERSE : MC_MOTOR_FORWARD;
	byte rightSpeed = min(abs(rightVelocity), 255);
	byte rightDir = (rightVelocity < 0) ? MC_MOTOR_REVERSE : MC_MOTOR_FORWARD;

	setLeftMotorDutyCycle(leftDir, leftSpeed);
	setRightMotorDutyCycle(rightDir, rightSpeed);

}
<commit_msg>John's joystick code<commit_after>#include "analogjoystick.hpp"

void setupJoystick()
{
	pinMode(joystickXADC, INPUT);
	pinMode(joystickXADC, INPUT);
	pinMode(joystickEnable, INPUT);
	digitalWrite(joystickEnable, HIGH);
}
/*
void disableJoystick()
{
	digitalWrite(joystickEnable, LOW);
}
*/
void getJoystickReading(int* X, int* Y)
{
	*X = analogRead(joystickXADC);
	*Y = analogRead(joystickYADC);
}

int sign(int n)
{
	if(n > 0)
	{
		return 1;
	}
	return -1;
}

/* Get joystick position and turn it into motor velocities */
//
//   +y
//  -x +x
//    -y
//
void joystickSetMotors()
{
	int xAxis = 0;
	int yAxis = 0;

	const int XMiddle = 1023 / 2;
	const int YMiddle = 1023 / 2;

	getJoystickReading(&xAxis, &yAxis);

	//shift 0
	xAxis -= XMiddle;
	yAxis -= YMiddle;

	//make x go the right dir
	//xAxis *= -1;

	/* Apply deadzones */
	if (abs(xAxis) < DEAD_ZONE)
	{
		xAxis = 0;
	}
	if (abs(yAxis) < DEAD_ZONE)
	{
		yAxis = 0;
	}

	/* Calculate drive outputs -- magic*/
	//int leftVelocity = .5*float(yAxis) + 2 * sign(xAxis) * sqrt(abs(xAxis));
	//int rightVelocity = .5*float(yAxis) - 2 * sign(xAxis) * sqrt(abs(xAxis));
	//int leftVelocity = yAxis + 3 * sign(xAxis) * sqrt(abs(xAxis));
	//int rightVelocity = yAxis - 3 * sign(xAxis) * sqrt(abs(xAxis));
	int leftVelocity;
	int rightVelocity;

	if ((yAxis > xAxis)&&(xAxis >= 0)) {
	  leftVelocity = 512;
	  rightVelocity = 512 - xAxis/2;
	}
	else if ((yAxis <= xAxis)&&(yAxis > 0)) {
	  leftVelocity = 256 + yAxis/2;
	  rightVelocity = yAxis - 256;
	}
	else if ((-yAxis < xAxis)&&(yAxis <= 0)) {
	  leftVelocity = 256 - yAxis;
	  rightVelocity = -256 - yAxis/2;
	}
	else if ((-yAxis >= xAxis)&&(xAxis > 0)) {
	  leftVelocity = -512 + xAxis/2;
	  rightVelocity = -512;
	}
	else if ((yAxis < xAxis)&&(xAxis <= 0)) {
	  leftVelocity = -512;
	  rightVelocity = -512 - xAxis/2;
	}
	else if ((yAxis >= xAxis)&&(yAxis < 0)) {
	  leftVelocity = -256 + yAxis/2;
	  rightVelocity = -256 + yAxis;
	}
	else if ((-yAxis < xAxis)&&(yAxis >= 0)) {
	  leftVelocity = -256 + yAxis;
	  rightVelocity = 256 + yAxis/2;
	}
	else if ((-yAxis >= xAxis)&&(xAxis < 0)) {
	  leftVelocity = 512 + xAxis/2;
	  rightVelocity = 512;
	}

	leftVelocity = float(leftVelocity/2)*abs(float(xAxis + yAxis)/float(1023 - abs(xAxis - yAxis)));
	rightVelocity = float(rightVelocity/2)*abs(float(xAxis + yAxis)/float(1023 - abs(xAxis - yAxis)));

	/* Limit drive velcocities to vaild values and convert them to drive speeds and directions */

	Serial.print("L/Rev: ");
	Serial.println(leftVelocity, DEC);

	Serial.print("R/Rev: ");
	Serial.println(rightVelocity, DEC);

	byte leftSpeed = min(abs(leftVelocity), 255);
	byte leftDir = (leftVelocity < 0) ? MC_MOTOR_REVERSE : MC_MOTOR_FORWARD;
	byte rightSpeed = min(abs(rightVelocity), 255);
	byte rightDir = (rightVelocity < 0) ? MC_MOTOR_REVERSE : MC_MOTOR_FORWARD;

	setLeftMotorDutyCycle(leftDir, leftSpeed);
	setRightMotorDutyCycle(rightDir, rightSpeed);

}
<|endoftext|>


<commit_before>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbOGRDataSourceToLabelImageFilter.h"
#include "itkImageRegionConstIterator.h"
#include "otbOGRDataSourceWrapper.h"

#include "itkImageRegionSplitter.h"
#include "otbStreamingTraits.h"

namespace otb
{
namespace Wrapper
{

class ComputeConfusionMatrix : public Application
{
public:
  /** Standard class typedefs. */
  typedef ComputeConfusionMatrix Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(ComputeConfusionMatrix, otb::Application);

  typedef itk::ImageRegionConstIterator<Int32ImageType> ImageIteratorType;

  typedef otb::OGRDataSourceToLabelImageFilter
    <Int32ImageType>                                    RasterizeFilterType;

  typedef otb::StreamingTraits<Int32ImageType>        StreamingTraitsType;

  typedef itk::ImageRegionSplitter<2>                 SplitterType;

  typedef Int32ImageType::RegionType                  RegionType;

private:
  void DoInit()
  {
  SetName("ComputeConfusionMatrix");
  SetDescription("Computes the confusion matrix of a classification");

  // Documentation
  SetDocName("Compute Confusion Matrix Application");
  SetDocLongDescription("This application computes the confusion matrix of a classification  relatively to a ground truth. This ground truth can be given as a raster or a vector data.");
  SetDocLimitations("None");
  SetDocAuthors("OTB-Team");
  SetDocSeeAlso(" ");

  AddDocTag(Tags::Learning);

  AddParameter(ParameterType_InputImage, "in", "Input Image");
  SetParameterDescription( "in", "The input classification image." );

  AddParameter(ParameterType_OutputFilename, "out", "Matrix output");
  SetParameterDescription("out", "Filename to store the output matrix (csv format)");

  AddParameter(ParameterType_Choice,"ref","Ground truth");
  SetParameterDescription("ref","Choice of ground truth format");

  AddChoice("ref.raster","Ground truth as a raster image");

  AddChoice("ref.vector","Ground truth as a vector data file");

  AddParameter(ParameterType_InputImage,"ref.raster.in","Input reference image");
  SetParameterDescription("ref.raster.in","Input image containing the ground truth labels");

  AddParameter(ParameterType_InputFilename,"ref.vector.in","Input reference vector data");
  SetParameterDescription("ref.vector.in", "Input vector data of the ground truth");

  AddParameter(ParameterType_String,"ref.vector.field","Field name");
  SetParameterDescription("ref.vector.field","Field name containing the label values");
  SetParameterString("ref.vector.field","dn");
  MandatoryOff("ref.vector.field");
  DisableParameter("ref.vector.field");

  AddParameter(ParameterType_Int,"labels","Number of labels");
  SetParameterDescription("labels","Number of labels in the classification. The label values shall be contiguous and start from 1.");
  SetDefaultParameterInt("labels",2);
  MandatoryOff("labels");
  DisableParameter("labels");

  AddParameter(ParameterType_Int,"nodata","Value for nodata pixels");
  SetParameterDescription("nodata","This value will be used to discard pixels from the ground truth");
  SetDefaultParameterInt("nodata",0);
  MandatoryOff("nodata");
  DisableParameter("nodata");

  AddRAMParameter();

  // Doc example parameter settings
  SetDocExampleParameterValue("in", "clLabeledImageQB1.tif");
  SetDocExampleParameterValue("out", "confusion.txt");
  SetDocExampleParameterValue("ref", "vector");
  SetDocExampleParameterValue("ref.vector.in","VectorData_QB1_bis.shp");
  SetDocExampleParameterValue("ref.vector.field","Class");
  SetDocExampleParameterValue("labels","4");
  }

  void DoUpdateParameters()
  {
    // Nothing to do here : all parameters are independent
  }

  void DoExecute()
  {
    Int32ImageType* input = this->GetParameterImage<Int32ImageType>("in");

    std::string field;
    int nodata = this->GetParameterInt("nodata");

    //Init Conf Matrix
    unsigned int nbClasses = this->GetParameterInt("labels");
    m_Matrix.resize(nbClasses);
    for(unsigned int i=0; i<nbClasses; i++ )
      {
      m_Matrix[i].assign(nbClasses,0);
      }

    Int32ImageType::Pointer reference;
    otb::ogr::DataSource::Pointer ogrRef;
    RasterizeFilterType::Pointer rasterizeReference = RasterizeFilterType::New();

    if (GetParameterString("ref") == "raster")
      {
      reference = this->GetParameterImage<Int32ImageType>("ref.raster.in");
      }
    else
      {
      ogrRef = otb::ogr::DataSource::New(GetParameterString("ref.vector.in"), otb::ogr::DataSource::Modes::Read);
      field = this->GetParameterString("ref.vector.field");

      rasterizeReference->AddOGRDataSource(ogrRef);
      rasterizeReference->SetOutputParametersFromImage(input);
      rasterizeReference->SetBackgroundValue(nodata);
      rasterizeReference->SetBurnAttribute(field.c_str());

      reference = rasterizeReference->GetOutput();
      reference->UpdateOutputInformation();
      }

    // Prepare local streaming
    SplitterType::Pointer splitter = SplitterType::New();
    unsigned int numberOfStreamDivisions = StreamingTraitsType::CalculateNumberOfStreamDivisions(
      input,
      input->GetLargestPossibleRegion(),
      splitter,
      otb::SET_BUFFER_MEMORY_SIZE,
      0, 1048576*GetParameterInt("ram"), 0);
    RegionType streamRegion;

    otbAppLogINFO("Number of stream divisions : "<<numberOfStreamDivisions);

    for (unsigned int index=0; index<numberOfStreamDivisions; index++)
      {
      streamRegion = splitter->GetSplit(index, numberOfStreamDivisions, input->GetLargestPossibleRegion());

      input->SetRequestedRegion(streamRegion);
      input->PropagateRequestedRegion();
      input->UpdateOutputData();

      reference->SetRequestedRegion(streamRegion);
      reference->PropagateRequestedRegion();
      reference->UpdateOutputData();

      ImageIteratorType itInput(input, streamRegion);
      itInput.GoToBegin();

      ImageIteratorType itRef(reference, streamRegion);
      itRef.GoToBegin();

      while (!itInput.IsAtEnd())
        {
        if (itRef.Get() != nodata)
          {
          if (itRef.Get()>0 && itRef.Get()<=static_cast<int>(nbClasses) &&
              itInput.Get()>0 && itInput.Get()<=static_cast<int>(nbClasses))
            {
            m_Matrix[itInput.Get()-1][itRef.Get()-1] ++;
            }
          }
        ++ itInput;
        ++ itRef;
        }
      }

    std::ofstream outFile;
    outFile.open(this->GetParameterString("out").c_str());
    outFile<<std::fixed;
    outFile.precision(10);
    for(unsigned int j=0; j<nbClasses; j++ )
      {
      for(unsigned int i=0; i<nbClasses; i++ )
        {
        outFile << m_Matrix[i][j];
        if (i<(nbClasses-1))
          {
          outFile<<"\t";
          }
        else
          {
          outFile<<std::endl;
          }
        }
      }
    outFile.close();

  }

  std::vector<std::vector<unsigned long> > m_Matrix;

};

}
}
OTB_APPLICATION_EXPORT(otb::Wrapper::ComputeConfusionMatrix)
<commit_msg>STYLE<commit_after>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbOGRDataSourceToLabelImageFilter.h"
#include "itkImageRegionConstIterator.h"
#include "otbOGRDataSourceWrapper.h"

#include "itkImageRegionSplitter.h"
#include "otbStreamingTraits.h"

namespace otb
{
namespace Wrapper
{

class ComputeConfusionMatrix : public Application
{
public:
  /** Standard class typedefs. */
  typedef ComputeConfusionMatrix Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(ComputeConfusionMatrix, otb::Application);

  typedef itk::ImageRegionConstIterator<Int32ImageType> ImageIteratorType;

  typedef otb::OGRDataSourceToLabelImageFilter
    <Int32ImageType>                                    RasterizeFilterType;

  typedef otb::StreamingTraits<Int32ImageType>        StreamingTraitsType;

  typedef itk::ImageRegionSplitter<2>                 SplitterType;

  typedef Int32ImageType::RegionType                  RegionType;

private:
  void DoInit()
  {
  SetName("ComputeConfusionMatrix");
  SetDescription("Computes the confusion matrix of a classification");

  // Documentation
  SetDocName("Compute Confusion Matrix Application");
  SetDocLongDescription("This application computes the confusion matrix of a classification  relatively to a ground truth. This ground truth can be given as a raster or a vector data.");
  SetDocLimitations("None");
  SetDocAuthors("OTB-Team");
  SetDocSeeAlso(" ");

  AddDocTag(Tags::Learning);

  AddParameter(ParameterType_InputImage, "in", "Input Image");
  SetParameterDescription( "in", "The input classification image." );

  AddParameter(ParameterType_OutputFilename, "out", "Matrix output");
  SetParameterDescription("out", "Filename to store the output matrix (csv format)");

  AddParameter(ParameterType_Choice,"ref","Ground truth");
  SetParameterDescription("ref","Choice of ground truth format");

  AddChoice("ref.raster","Ground truth as a raster image");

  AddChoice("ref.vector","Ground truth as a vector data file");

  AddParameter(ParameterType_InputImage,"ref.raster.in","Input reference image");
  SetParameterDescription("ref.raster.in","Input image containing the ground truth labels");

  AddParameter(ParameterType_InputFilename,"ref.vector.in","Input reference vector data");
  SetParameterDescription("ref.vector.in", "Input vector data of the ground truth");

  AddParameter(ParameterType_String,"ref.vector.field","Field name");
  SetParameterDescription("ref.vector.field","Field name containing the label values");
  SetParameterString("ref.vector.field","dn");
  MandatoryOff("ref.vector.field");
  DisableParameter("ref.vector.field");

  AddParameter(ParameterType_Int,"labels","Number of labels");
  SetParameterDescription("labels","Number of labels in the classification. The label values shall be contiguous and start from 1.");
  SetDefaultParameterInt("labels",2);
  MandatoryOff("labels");
  DisableParameter("labels");

  AddParameter(ParameterType_Int,"nodata","Value for nodata pixels");
  SetParameterDescription("nodata","This value will be used to discard pixels from the ground truth");
  SetDefaultParameterInt("nodata",0);
  MandatoryOff("nodata");
  DisableParameter("nodata");

  AddRAMParameter();

  // Doc example parameter settings
  SetDocExampleParameterValue("in", "clLabeledImageQB1.tif");
  SetDocExampleParameterValue("out", "confusion.txt");
  SetDocExampleParameterValue("ref", "vector");
  SetDocExampleParameterValue("ref.vector.in","VectorData_QB1_bis.shp");
  SetDocExampleParameterValue("ref.vector.field","Class");
  SetDocExampleParameterValue("labels","4");
  }

  void DoUpdateParameters()
  {
    // Nothing to do here : all parameters are independent
  }

  void DoExecute()
  {
    Int32ImageType* input = this->GetParameterImage<Int32ImageType>("in");

    std::string field;
    int nodata = this->GetParameterInt("nodata");

    //Init Conf Matrix
    unsigned int nbClasses = this->GetParameterInt("labels");
    m_Matrix.resize(nbClasses);
    for(unsigned int i=0; i<nbClasses; i++ )
      {
      m_Matrix[i].assign(nbClasses,0);
      }

    Int32ImageType::Pointer reference;
    otb::ogr::DataSource::Pointer ogrRef;
    RasterizeFilterType::Pointer rasterizeReference = RasterizeFilterType::New();

    if (GetParameterString("ref") == "raster")
      {
      reference = this->GetParameterImage<Int32ImageType>("ref.raster.in");
      }
    else
      {
      ogrRef = otb::ogr::DataSource::New(GetParameterString("ref.vector.in"), otb::ogr::DataSource::Modes::Read);
      field = this->GetParameterString("ref.vector.field");

      rasterizeReference->AddOGRDataSource(ogrRef);
      rasterizeReference->SetOutputParametersFromImage(input);
      rasterizeReference->SetBackgroundValue(nodata);
      rasterizeReference->SetBurnAttribute(field.c_str());

      reference = rasterizeReference->GetOutput();
      reference->UpdateOutputInformation();
      }

    // Prepare local streaming
    SplitterType::Pointer splitter = SplitterType::New();
    unsigned int numberOfStreamDivisions = StreamingTraitsType::CalculateNumberOfStreamDivisions(
      input,
      input->GetLargestPossibleRegion(),
      splitter,
      otb::SET_BUFFER_MEMORY_SIZE,
      0, 1048576*GetParameterInt("ram"), 0);
    RegionType streamRegion;

    otbAppLogINFO("Number of stream divisions : "<<numberOfStreamDivisions);

    for (unsigned int index=0; index<numberOfStreamDivisions; index++)
      {
      streamRegion = splitter->GetSplit(index, numberOfStreamDivisions, input->GetLargestPossibleRegion());

      input->SetRequestedRegion(streamRegion);
      input->PropagateRequestedRegion();
      input->UpdateOutputData();

      reference->SetRequestedRegion(streamRegion);
      reference->PropagateRequestedRegion();
      reference->UpdateOutputData();

      ImageIteratorType itInput(input, streamRegion);
      itInput.GoToBegin();

      ImageIteratorType itRef(reference, streamRegion);
      itRef.GoToBegin();

      while (!itInput.IsAtEnd())
        {
        if (itRef.Get() != nodata)
          {
          if (itRef.Get()>0 && itRef.Get()<=static_cast<int>(nbClasses) &&
              itInput.Get()>0 && itInput.Get()<=static_cast<int>(nbClasses))
            {
            m_Matrix[itInput.Get()-1][itRef.Get()-1] ++;
            }
          }
        ++ itInput;
        ++ itRef;
        }
      }

    std::ofstream outFile;
    outFile.open(this->GetParameterString("out").c_str());
    outFile<<std::fixed;
    outFile.precision(10);
    for(unsigned int j=0; j<nbClasses; j++ )
      {
      for(unsigned int i=0; i<nbClasses; i++ )
        {
        outFile << m_Matrix[i][j];
        if (i<(nbClasses-1))
          {
          outFile<<"\t";
          }
        else
          {
          outFile<<std::endl;
          }
        }
      }
    outFile.close();

  }

  std::vector<std::vector<unsigned long> > m_Matrix;

};

}
}
OTB_APPLICATION_EXPORT(otb::Wrapper::ComputeConfusionMatrix)
<|endoftext|>


<commit_before>#pragma once

#include <Components/Component.hh>
#include <glm/glm.hpp>
#include <Utils/GlmSerialization.hpp>
#include <Audio/Audio.hh>
#include <cereal/types/base_class.hpp>
#include <cereal/types/string.hpp>

namespace Component
{
	struct AudioListener : public Component::ComponentBase<AudioListener>
	{
		AudioListener();
		virtual ~AudioListener(void);
		void init();
		virtual void reset();

		//////
		////
		// Serialization

		template <typename Archive>
		Base *unserialize(Archive &ar, Entity e)
		{
			auto res = new AudioListener();
			res->setEntity(e);
			ar(*res);
			return res;
		}

		template <typename Archive>
		void serialize(Archive &ar)
		{
			ar(std::string("temporary"));
		}

		// !Serialization
		////
		//////
	private:
		AudioListener(AudioListener const &);
		AudioListener &operator=(AudioListener const &);
	};
}<commit_msg>Audio listener ser -> Close #106 Close #104<commit_after>#pragma once

#include <Components/Component.hh>
#include <glm/glm.hpp>
#include <Utils/GlmSerialization.hpp>
#include <Audio/Audio.hh>
#include <cereal/types/base_class.hpp>
#include <cereal/types/string.hpp>

namespace Component
{
	struct AudioListener : public Component::ComponentBase<AudioListener>
	{
		AudioListener();
		virtual ~AudioListener(void);
		void init();
		virtual void reset();

		//////
		////
		// Serialization

		template <typename Archive>
		Base *unserialize(Archive &ar, Entity e)
		{
			auto res = new AudioListener();
			res->setEntity(e);
			ar(*res);
			return res;
		}

		template <typename Archive>
		void serialize(Archive &ar)
		{
		}

		// !Serialization
		////
		//////
	private:
		AudioListener(AudioListener const &);
		AudioListener &operator=(AudioListener const &);
	};
}<|endoftext|>


<commit_before>#include "behaviour_ballfollowing.h"

#include <Module_ThrusterControlLoop/module_thrustercontrolloop.h>
#include <QtGui>
#include <Behaviour_BallFollowing/ballfollowingform.h>
#include <Behaviour_BallFollowing/blobs/blob.h>
#include <Behaviour_BallFollowing/blobs/BlobResult.h>
#include <opencv/highgui.h>
#include <Module_Compass/module_compass.h>

Behaviour_BallFollowing::Behaviour_BallFollowing(QString id, Module_ThrusterControlLoop *tcl,
                                                 Module_Webcams *cams, Module_Compass *compass)
    : RobotBehaviour(id)
{
    this->tcl = tcl;
    this->cams = cams;
    this->compass = compass;

    connect(&updateTimer,SIGNAL(timeout()),this,SLOT(newData()));
    connect(&timerNoBall,SIGNAL(timeout()),this,SLOT(timerSlot()));

    setEnabled(false);
    state = STATE_IDLE;

    targetHeading = compass->getHeading() - 45;
    if ( targetHeading < 0 )
    {
        targetHeading += 360;
    }
    QObject::connect( compass, SIGNAL(dataChanged(RobotModule*)),
                      this, SLOT(compassUpdate(RobotModule*)) );
}

bool Behaviour_BallFollowing::isActive()
{
    return isEnabled();
}

void Behaviour_BallFollowing::start()
{
    logger->debug( "Behaviour started" );
    this->setEnabled( true );
    state = STATE_TURN_45;
    targetHeading = compass->getHeading() - 45;
    if ( targetHeading < 0 )
    {
        targetHeading += 360;
    }
    tcl->setAngularSpeed( .4 );

    updateTimer.start( 100 );
}

void Behaviour_BallFollowing::newData()
{
    if( this->isEnabled() && state == STATE_TRACK_BALL )
    {
        Behaviour_BallFollowing::ctrBallFollowing();
    }
}

void Behaviour_BallFollowing::compassUpdate( RobotModule * )
{
    if ( isEnabled() && state == STATE_TURN_45 )
    {
        double currentHeading = compass->getHeading();
        double diffHeading = fabs( targetHeading - currentHeading );
        if ( diffHeading < 5 )
        {
            state = STATE_TRACK_BALL;
            tcl->setAngularSpeed( .0 );
            tcl->setForwardSpeed( .0 );
        }
    }
}

void Behaviour_BallFollowing::stop()
{
    logger->debug( "Behaviour stopped" );
    if (isEnabled()) {
        updateTimer.stop();
        this->tcl->setForwardSpeed(0.0);
        this->tcl->setAngularSpeed(0.0);
        setEnabled(false);
        emit finished(this,false);
   }
}

void Behaviour_BallFollowing::reset()
{
    logger->debug( "Behaviour reset" );
    RobotBehaviour::reset();
    this->tcl->setForwardSpeed(0.0);
    this->tcl->setAngularSpeed(0.0);
}

QList<RobotModule*> Behaviour_BallFollowing::getDependencies()
{
    QList<RobotModule*> ret;
    ret.append(tcl);
    ret.append( cams );
    ret.append( compass );
    return ret;
}

QWidget* Behaviour_BallFollowing::createView(QWidget* parent)
{
    return new BallFollowingForm(parent, this);
}

void Behaviour_BallFollowing::testBehaviour( QString path )
{
    QDir dir( path );
    dir.setFilter( QDir::Files );
    QStringList filters;
    filters << "*.jpg";
    dir.setNameFilters( filters );
    QStringList files = dir.entryList();

    cvNamedWindow("Dummy");
    for ( int i = 0; i < files.count(); i++ )
    {
        IplImage *gray = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 1 );
        IplImage *thresh = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 1 );
        IplImage *disp = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 3 );
        IplImage *hsv = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 3 );
        cvMerge( thresh, thresh, thresh, NULL, disp );

        QString filePath = path;
        filePath.append( "/" );
        filePath.append( files[i] );
        IplImage *left = cvLoadImage( filePath.toStdString().c_str(), 1 );

        // Apply threshold.
        cvCvtColor( left, gray, CV_RGB2GRAY );
        cvCvtColor( left, hsv, CV_RGB2HSV );
        cvSplit( hsv, NULL, gray, NULL, NULL );
        cvThreshold( gray, thresh, settings.value( "threshold", 100 ).toDouble(), 255, CV_THRESH_BINARY );
        cvMerge( thresh, thresh, thresh, NULL, disp );

        // Do blob filtering.
        CBlobResult blobs( thresh, NULL, 255 );
        blobs.Filter( blobs, B_EXCLUDE, CBlobGetArea(), B_LESS, 500 );

        // Get largest blobs x position.
        float x = -1;
        int maxArea = 0;
        int maxBlob = -1;
        for ( int j = 0; j < blobs.GetNumBlobs(); j++ )
        {
            CBlob *blob = blobs.GetBlob( j );
            if ( blob->Area() > maxArea )
            {
                maxArea = blob->Area();
                maxBlob = j;
            }
        }
        if ( maxBlob >= 0 )
        {
            x = blobs.GetBlob( maxBlob )->Moment( 1, 0 ) / blobs.GetBlob( maxBlob )->Moment( 0, 0 );
            blobs.GetBlob( maxBlob )->FillBlob( left, cvScalar( 0, 0, 255 ), 0, 0 );
        }

        emit printFrame( left );

        cvReleaseImage( &left );
        cvReleaseImage( &gray );
        cvReleaseImage( &thresh );
        cvReleaseImage( &disp );
        cvReleaseImage( &hsv );

        cvWaitKey( 200 );
    }
}

void Behaviour_BallFollowing::ctrBallFollowing()
{
    IplImage *gray = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 1 );
    IplImage *thresh = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 1 );
    IplImage *disp = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 3 );
    IplImage *hsv = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 3 );
    cvMerge( thresh, thresh, thresh, NULL, disp );
    IplImage *left = cvCreateImage( cvSize(WEBCAM_WIDTH,WEBCAM_HEIGHT), IPL_DEPTH_8U, 3 );
    cams->grabLeft( left );

    // Apply threshold.
    cvCvtColor( left, gray, CV_RGB2GRAY );
    cvCvtColor( left, hsv, CV_RGB2HSV );
    cvSplit( hsv, NULL, gray, NULL, NULL );
    cvThreshold( gray, thresh, settings.value( "threshold", 100 ).toDouble(), 255, CV_THRESH_BINARY );
    cvMerge( thresh, thresh, thresh, NULL, disp );

    // Do blob filtering.
    CBlobResult blobs( thresh, NULL, 255 );
    blobs.Filter( blobs, B_EXCLUDE, CBlobGetArea(), B_LESS, 500 );

    // Get largest blobs x position.
    float x = -1;
    int maxArea = 0;
    int maxBlob = -1;
    for ( int j = 0; j < blobs.GetNumBlobs(); j++ )
    {
        CBlob *blob = blobs.GetBlob( j );
        if ( blob->Area() > maxArea )
        {
            maxArea = blob->Area();
            maxBlob = j;
        }
    }
    if ( maxBlob >= 0 )
    {
        x = blobs.GetBlob( maxBlob )->Moment( 1, 0 ) / blobs.GetBlob( maxBlob )->Moment( 0, 0 );
        blobs.GetBlob( maxBlob )->FillBlob( left, cvScalar( 0, 0, 255 ), 0, 0 );
    }

    emit printFrame( left );

    if ( x > 0 )
    {
        timerNoBall.stop();
        float robCenterX = this->getSettings().value("robCenterX").toFloat();
        float diff = robCenterX - x;
        float angleSpeed = 0.0;
        diff < 0.0 ? diff *= (-1) : diff;
        if(diff > this->getSettings().value("deltaBall").toFloat())
        {
            angleSpeed = this->getSettings().value("kpBall").toFloat() * ((robCenterX - x)/this->getSettings().value("maxDistance").toFloat());
        }
        tcl->setAngularSpeed(angleSpeed);
        tcl->setForwardSpeed(this->getSettings().value("fwSpeed").toFloat());

        data["ball_area"] = maxArea;
        data["ball_x"] = x;
        data["position_difference"] = diff;
        data["angular_speed"] = angleSpeed;
        data["forward_speed"] = this->getSettings().value("fwSpeed").toFloat();
        dataChanged( this );
        timerNoBall.start( 10000 );
    }
    else
    {
        tcl->setAngularSpeed( .0 );
        tcl->setForwardSpeed( .6 );
    }

    cvReleaseImage( &left );
    cvReleaseImage( &gray );
    cvReleaseImage( &thresh );
    cvReleaseImage( &hsv );
    cvReleaseImage( &left );
}

void Behaviour_BallFollowing::timerSlot()
{
    timerNoBall.stop();
    stop();
}
<commit_msg><commit_after>#include "behaviour_ballfollowing.h"

#include <Module_ThrusterControlLoop/module_thrustercontrolloop.h>
#include <QtGui>
#include <Behaviour_BallFollowing/ballfollowingform.h>
#include <Behaviour_BallFollowing/blobs/blob.h>
#include <Behaviour_BallFollowing/blobs/BlobResult.h>
#include <opencv/highgui.h>
#include <Module_Compass/module_compass.h>

Behaviour_BallFollowing::Behaviour_BallFollowing(QString id, Module_ThrusterControlLoop *tcl,
                                                 Module_Webcams *cams, Module_Compass *compass)
    : RobotBehaviour(id)
{
    this->tcl = tcl;
    this->cams = cams;
    this->compass = compass;

    connect(&updateTimer,SIGNAL(timeout()),this,SLOT(newData()));
    connect(&timerNoBall,SIGNAL(timeout()),this,SLOT(timerSlot()));

    setEnabled(false);
    state = STATE_IDLE;

    targetHeading = compass->getHeading() - 45;
    if ( targetHeading < 0 )
    {
        targetHeading += 360;
    }
    QObject::connect( compass, SIGNAL(dataChanged(RobotModule*)),
                      this, SLOT(compassUpdate(RobotModule*)) );
}

bool Behaviour_BallFollowing::isActive()
{
    return isEnabled();
}

void Behaviour_BallFollowing::start()
{
    logger->debug( "Behaviour started" );
    this->setEnabled( true );
    state = STATE_TURN_45;
    targetHeading = compass->getHeading() - 45;
    if ( targetHeading < 0 )
    {
        targetHeading += 360;
    }
    tcl->setAngularSpeed( -0.4 );

    updateTimer.start( 100 );
}

void Behaviour_BallFollowing::newData()
{
    if( this->isEnabled() && state == STATE_TRACK_BALL )
    {
        Behaviour_BallFollowing::ctrBallFollowing();
    }
}

void Behaviour_BallFollowing::compassUpdate( RobotModule * )
{
    if ( isEnabled() && state == STATE_TURN_45 )
    {
        double currentHeading = compass->getHeading();
        double diffHeading = fabs( targetHeading - currentHeading );
        if ( diffHeading < 5 )
        {
            state = STATE_TRACK_BALL;
            tcl->setAngularSpeed( .0 );
            tcl->setForwardSpeed( .0 );
        }
    }
}

void Behaviour_BallFollowing::stop()
{
    logger->debug( "Behaviour stopped" );
    if (isEnabled()) {
        state = STATE_IDLE;
        updateTimer.stop();
        this->tcl->setForwardSpeed(0.0);
        this->tcl->setAngularSpeed(0.0);
        setEnabled(false);
        emit finished(this,false);
   }
}

void Behaviour_BallFollowing::reset()
{
    logger->debug( "Behaviour reset" );
    RobotBehaviour::reset();
    this->tcl->setForwardSpeed(0.0);
    this->tcl->setAngularSpeed(0.0);
}

QList<RobotModule*> Behaviour_BallFollowing::getDependencies()
{
    QList<RobotModule*> ret;
    ret.append(tcl);
    ret.append( cams );
    ret.append( compass );
    return ret;
}

QWidget* Behaviour_BallFollowing::createView(QWidget* parent)
{
    return new BallFollowingForm(parent, this);
}

void Behaviour_BallFollowing::testBehaviour( QString path )
{
    QDir dir( path );
    dir.setFilter( QDir::Files );
    QStringList filters;
    filters << "*.jpg";
    dir.setNameFilters( filters );
    QStringList files = dir.entryList();

    cvNamedWindow("Dummy");
    for ( int i = 0; i < files.count(); i++ )
    {
        IplImage *gray = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 1 );
        IplImage *thresh = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 1 );
        IplImage *disp = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 3 );
        IplImage *hsv = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 3 );
        cvMerge( thresh, thresh, thresh, NULL, disp );

        QString filePath = path;
        filePath.append( "/" );
        filePath.append( files[i] );
        IplImage *left = cvLoadImage( filePath.toStdString().c_str(), 1 );

        // Apply threshold.
        cvCvtColor( left, gray, CV_RGB2GRAY );
        cvCvtColor( left, hsv, CV_RGB2HSV );
        cvSplit( hsv, NULL, gray, NULL, NULL );
        cvThreshold( gray, thresh, settings.value( "threshold", 100 ).toDouble(), 255, CV_THRESH_BINARY );
        cvMerge( thresh, thresh, thresh, NULL, disp );

        // Do blob filtering.
        CBlobResult blobs( thresh, NULL, 255 );
        blobs.Filter( blobs, B_EXCLUDE, CBlobGetArea(), B_LESS, 500 );

        // Get largest blobs x position.
        float x = -1;
        int maxArea = 0;
        int maxBlob = -1;
        for ( int j = 0; j < blobs.GetNumBlobs(); j++ )
        {
            CBlob *blob = blobs.GetBlob( j );
            if ( blob->Area() > maxArea )
            {
                maxArea = blob->Area();
                maxBlob = j;
            }
        }
        if ( maxBlob >= 0 )
        {
            x = blobs.GetBlob( maxBlob )->Moment( 1, 0 ) / blobs.GetBlob( maxBlob )->Moment( 0, 0 );
            blobs.GetBlob( maxBlob )->FillBlob( left, cvScalar( 0, 0, 255 ), 0, 0 );
        }

        emit printFrame( left );

        cvReleaseImage( &left );
        cvReleaseImage( &gray );
        cvReleaseImage( &thresh );
        cvReleaseImage( &disp );
        cvReleaseImage( &hsv );

        cvWaitKey( 200 );
    }
}

void Behaviour_BallFollowing::ctrBallFollowing()
{
    IplImage *gray = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 1 );
    IplImage *thresh = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 1 );
    IplImage *disp = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 3 );
    IplImage *hsv = cvCreateImage( cvSize( WEBCAM_WIDTH, WEBCAM_HEIGHT ), IPL_DEPTH_8U, 3 );
    cvMerge( thresh, thresh, thresh, NULL, disp );
    IplImage *left = cvCreateImage( cvSize(WEBCAM_WIDTH,WEBCAM_HEIGHT), IPL_DEPTH_8U, 3 );
    cams->grabLeft( left );

    // Apply threshold.
    cvCvtColor( left, gray, CV_RGB2GRAY );
    cvCvtColor( left, hsv, CV_RGB2HSV );
    cvSplit( hsv, NULL, gray, NULL, NULL );
    cvThreshold( gray, thresh, settings.value( "threshold", 100 ).toDouble(), 255, CV_THRESH_BINARY );
    cvMerge( thresh, thresh, thresh, NULL, disp );

    // Do blob filtering.
    CBlobResult blobs( thresh, NULL, 255 );
    blobs.Filter( blobs, B_EXCLUDE, CBlobGetArea(), B_LESS, 500 );

    // Get largest blobs x position.
    float x = -1;
    int maxArea = 0;
    int maxBlob = -1;
    for ( int j = 0; j < blobs.GetNumBlobs(); j++ )
    {
        CBlob *blob = blobs.GetBlob( j );
        if ( blob->Area() > maxArea )
        {
            maxArea = blob->Area();
            maxBlob = j;
        }
    }
    if ( maxBlob >= 0 )
    {
        x = blobs.GetBlob( maxBlob )->Moment( 1, 0 ) / blobs.GetBlob( maxBlob )->Moment( 0, 0 );
        blobs.GetBlob( maxBlob )->FillBlob( left, cvScalar( 0, 0, 255 ), 0, 0 );
    }

    emit printFrame( left );

    if ( x > 0 )
    {
        timerNoBall.stop();
        float robCenterX = this->getSettings().value("robCenterX").toFloat();
        float diff = robCenterX - x;
        float angleSpeed = 0.0;
        diff < 0.0 ? diff *= (-1) : diff;
        if(diff > this->getSettings().value("deltaBall").toFloat())
        {
            angleSpeed = this->getSettings().value("kpBall").toFloat() * ((robCenterX - x)/this->getSettings().value("maxDistance").toFloat());
        }
        tcl->setAngularSpeed(angleSpeed);
        tcl->setForwardSpeed(this->getSettings().value("fwSpeed").toFloat());

        data["ball_area"] = maxArea;
        data["ball_x"] = x;
        data["position_difference"] = diff;
        data["angular_speed"] = angleSpeed;
        data["forward_speed"] = this->getSettings().value("fwSpeed").toFloat();
        dataChanged( this );
        timerNoBall.start( 10000 );
    }
    else
    {
        tcl->setAngularSpeed( .0 );
        tcl->setForwardSpeed( .6 );
    }

    cvReleaseImage( &left );
    cvReleaseImage( &gray );
    cvReleaseImage( &thresh );
    cvReleaseImage( &hsv );
    cvReleaseImage( &left );
}

void Behaviour_BallFollowing::timerSlot()
{
    timerNoBall.stop();
    stop();
}
<|endoftext|>


<commit_before><commit_msg>increased sleep times to make test more reliable<commit_after><|endoftext|>