<commit_before>/**
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/bitcoin/error.hpp>

#include <boost/system/error_code.hpp>
#include <bitcoin/bitcoin/compat.hpp>

using namespace bc;

class error_category_impl
  : public std::error_category
{
public:
    virtual const char* name() const BC_NOEXCEPT;
    virtual std::string message(int ev) const BC_NOEXCEPT;
    virtual std::error_condition default_error_condition(int ev)
        const BC_NOEXCEPT;
};

static const error_category_impl& get_error_category_instance()
{
    static error_category_impl instance;
    return instance;
}

const char* error_category_impl::name() const BC_NOEXCEPT
{
    return "bitcoin";
}

std::string error_category_impl::message(int ev) const BC_NOEXCEPT
{
    // This text mapping may change without notice.
    switch (ev)
    {
        case error::success:
            return "success";

        // network errors
        case error::service_stopped:
            return "connection terminated";
        case error::operation_failed:
            return "operation failed";

        // blockchain errors
        case error::not_found:
            return "object does not exist";
        case error::duplicate:
            return "matching previous object found";
        case error::unspent_output:
            return "unspent output";
        case error::unsupported_payment_type:
            return "unsupport payment type";

        // network errors (more)
        case error::resolve_failed:
            return "resolving hostname failed";
        case error::network_unreachable:
            return "unable to reach remote network";
        case error::address_in_use:
            return "address already in use";
        case error::listen_failed:
            return "listen incoming connections failed";
        case error::accept_failed:
            return "accept connection failed";
        case error::bad_stream:
            return "bad stream";
        case error::channel_timeout:
            return "channel timed out";

        // transaction pool
        case error::blockchain_reorganized:
            return "transactions invalidated from blockchain reorganization";
        case error::pool_filled:
            return "forced removal of old transaction from full pool";

        // validate tx
        case error::coinbase_transaction:
            return "memory pool coinbase transaction";
        case error::is_not_standard:
            return "transaction is not standard";
        case error::double_spend:
            return "double spend of input";
        case error::input_not_found:
            return "spent input not found";

        // check_transaction()
        case error::empty_transaction:
            return "transaction inputs or outputs are empty";
        case error::output_value_overflow:
            return "overflow in output value outside range";
        case error::invalid_coinbase_script_size:
            return "coinbase script is too small or large";
        case error::previous_output_null:
            return "non-coinbase transaction has null previous in an input";

        // validate block
        case error::previous_block_invalid:
            return "previous block failed to validate";

        // check_block()
        case error::size_limits:
            return "size limits failed";
        case error::proof_of_work:
            return "proof of work failed";
        case error::futuristic_timestamp:
            return "timestamp too far in the future";
        case error::first_not_coinbase:
            return "first transaction is not a coinbase";
        case error::extra_coinbases:
            return "more than one coinbase";
        case error::too_many_sigs:
            return "too many script signatures";
        case error::merkle_mismatch:
            return "merkle root mismatch";

        // accept_block()
        case error::incorrect_proof_of_work:
            return "proof of work does not match bits field";
        case error::timestamp_too_early:
            return "block timestamp is too early";
        case error::non_final_transaction:
            return "contains a non-final transaction";
        case error::checkpoints_failed:
            return "block hash rejected by checkpoint lockins";
        case error::old_version_block:
            return "reject version=1 block";
        case error::coinbase_height_mismatch:
            return "block height mismatch in coinbase";

        // connect_block()
        case error::duplicate_or_spent:
            return "duplicate transaction when with unspent outputs";
        case error::validate_inputs_failed:
            return "validation of inputs failed";
        case error::fees_out_of_range:
            return "fees are out of range";
        case error::coinbase_too_large:
            return "reported coinbase value is too large";

        // file system errors
        case error::file_system:
            return "file system error";

        // unknown errors
        case error::unknown:
        default:
            return "unknown error";
    }
}

std::error_condition error_category_impl::default_error_condition(int ev)
    const BC_NOEXCEPT
{
    switch (ev)
    {
        // validate tx
        case error::coinbase_transaction:
        case error::is_not_standard:
        case error::double_spend:
        case error::input_not_found:

        // check_transaction()
        case error::empty_transaction:
        case error::output_value_overflow:
        case error::invalid_coinbase_script_size:
        case error::previous_output_null:

        // validate block
        case error::previous_block_invalid:

        // check_block()
        case error::size_limits:
        case error::proof_of_work:
        case error::futuristic_timestamp:
        case error::first_not_coinbase:
        case error::extra_coinbases:
        case error::too_many_sigs:
        case error::merkle_mismatch:

        // accept_block()
        case error::incorrect_proof_of_work:
        case error::timestamp_too_early:
        case error::non_final_transaction:
        case error::checkpoints_failed:
        case error::old_version_block:
        case error::coinbase_height_mismatch:

        // connect_block()
        case error::duplicate_or_spent:
        case error::validate_inputs_failed:
        case error::fees_out_of_range:
        case error::coinbase_too_large:
            return error::validate_failed;

        // transaction pool
        case error::blockchain_reorganized:
        case error::pool_filled:
            return error::forced_removal;

        default:
            return std::error_condition(ev, *this);
    }
}

namespace libbitcoin {
namespace error {

    std::error_code make_error_code(error_code_t e)
    {
        return std::error_code(e, get_error_category_instance());
    }

    std::error_condition make_error_condition(error_condition_t e)
    {
        return std::error_condition(e, get_error_category_instance());
    }

    error_code_t boost_to_error_code(const boost::system::error_code& ec)
    {
        namespace boost_error = boost::system::errc;
        switch (ec.value())
        {
            case boost_error::success:
                return error::success;

            // network errors
            case boost_error::connection_aborted:
            case boost_error::connection_refused:
            case boost_error::connection_reset:
            case boost_error::not_connected:
            case boost_error::operation_canceled:
                return error::service_stopped;

            case boost_error::operation_not_permitted:
            case boost_error::operation_not_supported:
            case boost_error::owner_dead:
            case boost_error::permission_denied:
                return error::operation_failed;

            case boost_error::address_family_not_supported:
            case boost_error::address_not_available:
            case boost_error::bad_address:
            case boost_error::destination_address_required:
                return error::resolve_failed;

            case boost_error::broken_pipe:
            case boost_error::host_unreachable:
            case boost_error::network_down:
            case boost_error::network_reset:
            case boost_error::network_unreachable:
            case boost_error::no_link:
            case boost_error::no_protocol_option:
            case boost_error::no_such_file_or_directory:
            case boost_error::not_a_socket:
            case boost_error::protocol_not_supported:
            case boost_error::wrong_protocol_type:
                return error::network_unreachable;

            case boost_error::address_in_use:
            case boost_error::already_connected:
            case boost_error::connection_already_in_progress:
            case boost_error::operation_in_progress:
                return error::address_in_use;

            case boost_error::bad_message:
            case boost_error::illegal_byte_sequence:
            case boost_error::io_error:
            case boost_error::message_size:
            case boost_error::no_message_available:
            case boost_error::no_message:
            case boost_error::no_stream_resources:
            case boost_error::not_a_stream:
            case boost_error::protocol_error:
                return error::bad_stream;

            case boost_error::stream_timeout:
            case boost_error::timed_out:
                return error::channel_timeout;

            // file system errors
            case boost_error::cross_device_link:
            case boost_error::bad_file_descriptor:
            case boost_error::device_or_resource_busy:
            case boost_error::directory_not_empty:
            case boost_error::executable_format_error:
            case boost_error::file_exists:
            case boost_error::file_too_large:
            case boost_error::filename_too_long:
            case boost_error::invalid_seek:
            case boost_error::is_a_directory:
            case boost_error::no_space_on_device:
            case boost_error::no_such_device:
            case boost_error::no_such_device_or_address:
            case boost_error::read_only_file_system:
            case boost_error::resource_unavailable_try_again:
            case boost_error::text_file_busy:
            case boost_error::too_many_files_open:
            case boost_error::too_many_files_open_in_system:
            case boost_error::too_many_links:
            case boost_error::too_many_symbolic_link_levels:
                return error::file_system;

            // unknown errors
            case boost_error::argument_list_too_long:
            case boost_error::argument_out_of_domain:
            case boost_error::function_not_supported:
            case boost_error::identifier_removed:
            case boost_error::inappropriate_io_control_operation:
            case boost_error::interrupted:
            case boost_error::invalid_argument:
            case boost_error::no_buffer_space:
            case boost_error::no_child_process:
            case boost_error::no_lock_available:
            case boost_error::no_such_process:
            case boost_error::not_a_directory:
            case boost_error::not_enough_memory:
            case boost_error::not_supported:
            case boost_error::operation_would_block:
            case boost_error::resource_deadlock_would_occur:
            case boost_error::result_out_of_range:
            case boost_error::state_not_recoverable:
            case boost_error::value_too_large:
            default:
                return error::unknown;
        }
    }

} // namespace error
} // namespace libbitcoin
<commit_msg>Refine error text mapping.<commit_after>/**
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/bitcoin/error.hpp>

#include <boost/system/error_code.hpp>
#include <bitcoin/bitcoin/compat.hpp>

using namespace bc;

class error_category_impl
  : public std::error_category
{
public:
    virtual const char* name() const BC_NOEXCEPT;
    virtual std::string message(int ev) const BC_NOEXCEPT;
    virtual std::error_condition default_error_condition(int ev)
        const BC_NOEXCEPT;
};

static const error_category_impl& get_error_category_instance()
{
    static error_category_impl instance;
    return instance;
}

const char* error_category_impl::name() const BC_NOEXCEPT
{
    return "bitcoin";
}

std::string error_category_impl::message(int ev) const BC_NOEXCEPT
{
    // This text mapping may change without notice.
    switch (ev)
    {
        case error::success:
            return "success";

        // network errors
        case error::service_stopped:
            return "connection terminated";
        case error::operation_failed:
            return "operation failed";

        // blockchain errors
        case error::not_found:
            return "object does not exist";
        case error::duplicate:
            return "matching previous object found";
        case error::unspent_output:
            return "unspent output";
        case error::unsupported_payment_type:
            return "unsupport payment type";

        // network errors (more)
        case error::resolve_failed:
            return "resolving hostname failed";
        case error::network_unreachable:
            return "unable to reach remote host";
        case error::address_in_use:
            return "address already in use";
        case error::listen_failed:
            return "incoming connection failed";
        case error::accept_failed:
            return "connection acceptance failed";
        case error::bad_stream:
            return "bad data stream";
        case error::channel_timeout:
            return "connection timed out";

        // transaction pool
        case error::blockchain_reorganized:
            return "transactions invalidated by blockchain reorganization";
        case error::pool_filled:
            return "forced removal of old transaction from pool overflow";

        // validate tx
        case error::coinbase_transaction:
            return "coinbase transaction disallowed in memory pool";
        case error::is_not_standard:
            return "transaction is not standard";
        case error::double_spend:
            return "double spend of input";
        case error::input_not_found:
            return "spent input not found";

        // check_transaction()
        case error::empty_transaction:
            return "transaction inputs or outputs are empty";
        case error::output_value_overflow:
            return "output value outside valid range";
        case error::invalid_coinbase_script_size:
            return "coinbase script is too small or large";
        case error::previous_output_null:
            return "non-coinbase transaction has input with null previous output";

        // validate block
        case error::previous_block_invalid:
            return "previous block failed to validate";

        // check_block()
        case error::size_limits:
            return "size limits failed";
        case error::proof_of_work:
            return "proof of work failed";
        case error::futuristic_timestamp:
            return "timestamp too far in the future";
        case error::first_not_coinbase:
            return "first transaction is not a coinbase";
        case error::extra_coinbases:
            return "more than one coinbase";
        case error::too_many_sigs:
            return "too many script signatures";
        case error::merkle_mismatch:
            return "merkle root mismatch";

        // accept_block()
        case error::incorrect_proof_of_work:
            return "proof of work does not match bits field";
        case error::timestamp_too_early:
            return "block timestamp is too early";
        case error::non_final_transaction:
            return "block contains a non-final transaction";
        case error::checkpoints_failed:
            return "block hash rejected by checkpoint lockins";
        case error::old_version_block:
            return "block version one rejected at current height";
        case error::coinbase_height_mismatch:
            return "block height mismatch in coinbase";

        // connect_block()
        case error::duplicate_or_spent:
            return "duplicate transaction with unspent outputs";
        case error::validate_inputs_failed:
            return "validation of inputs failed";
        case error::fees_out_of_range:
            return "fees are out of range";
        case error::coinbase_too_large:
            return "coinbase value is too large";

        // file system errors
        case error::file_system:
            return "file system error";

        // unknown errors
        case error::unknown:
        default:
            return "unknown error";
    }
}

std::error_condition error_category_impl::default_error_condition(int ev)
    const BC_NOEXCEPT
{
    switch (ev)
    {
        // validate tx
        case error::coinbase_transaction:
        case error::is_not_standard:
        case error::double_spend:
        case error::input_not_found:

        // check_transaction()
        case error::empty_transaction:
        case error::output_value_overflow:
        case error::invalid_coinbase_script_size:
        case error::previous_output_null:

        // validate block
        case error::previous_block_invalid:

        // check_block()
        case error::size_limits:
        case error::proof_of_work:
        case error::futuristic_timestamp:
        case error::first_not_coinbase:
        case error::extra_coinbases:
        case error::too_many_sigs:
        case error::merkle_mismatch:

        // accept_block()
        case error::incorrect_proof_of_work:
        case error::timestamp_too_early:
        case error::non_final_transaction:
        case error::checkpoints_failed:
        case error::old_version_block:
        case error::coinbase_height_mismatch:

        // connect_block()
        case error::duplicate_or_spent:
        case error::validate_inputs_failed:
        case error::fees_out_of_range:
        case error::coinbase_too_large:
            return error::validate_failed;

        // transaction pool
        case error::blockchain_reorganized:
        case error::pool_filled:
            return error::forced_removal;

        default:
            return std::error_condition(ev, *this);
    }
}

namespace libbitcoin {
namespace error {

    std::error_code make_error_code(error_code_t e)
    {
        return std::error_code(e, get_error_category_instance());
    }

    std::error_condition make_error_condition(error_condition_t e)
    {
        return std::error_condition(e, get_error_category_instance());
    }

    error_code_t boost_to_error_code(const boost::system::error_code& ec)
    {
        namespace boost_error = boost::system::errc;
        switch (ec.value())
        {
            case boost_error::success:
                return error::success;

            // network errors
            case boost_error::connection_aborted:
            case boost_error::connection_refused:
            case boost_error::connection_reset:
            case boost_error::not_connected:
            case boost_error::operation_canceled:
                return error::service_stopped;

            case boost_error::operation_not_permitted:
            case boost_error::operation_not_supported:
            case boost_error::owner_dead:
            case boost_error::permission_denied:
                return error::operation_failed;

            case boost_error::address_family_not_supported:
            case boost_error::address_not_available:
            case boost_error::bad_address:
            case boost_error::destination_address_required:
                return error::resolve_failed;

            case boost_error::broken_pipe:
            case boost_error::host_unreachable:
            case boost_error::network_down:
            case boost_error::network_reset:
            case boost_error::network_unreachable:
            case boost_error::no_link:
            case boost_error::no_protocol_option:
            case boost_error::no_such_file_or_directory:
            case boost_error::not_a_socket:
            case boost_error::protocol_not_supported:
            case boost_error::wrong_protocol_type:
                return error::network_unreachable;

            case boost_error::address_in_use:
            case boost_error::already_connected:
            case boost_error::connection_already_in_progress:
            case boost_error::operation_in_progress:
                return error::address_in_use;

            case boost_error::bad_message:
            case boost_error::illegal_byte_sequence:
            case boost_error::io_error:
            case boost_error::message_size:
            case boost_error::no_message_available:
            case boost_error::no_message:
            case boost_error::no_stream_resources:
            case boost_error::not_a_stream:
            case boost_error::protocol_error:
                return error::bad_stream;

            case boost_error::stream_timeout:
            case boost_error::timed_out:
                return error::channel_timeout;

            // file system errors
            case boost_error::cross_device_link:
            case boost_error::bad_file_descriptor:
            case boost_error::device_or_resource_busy:
            case boost_error::directory_not_empty:
            case boost_error::executable_format_error:
            case boost_error::file_exists:
            case boost_error::file_too_large:
            case boost_error::filename_too_long:
            case boost_error::invalid_seek:
            case boost_error::is_a_directory:
            case boost_error::no_space_on_device:
            case boost_error::no_such_device:
            case boost_error::no_such_device_or_address:
            case boost_error::read_only_file_system:
            case boost_error::resource_unavailable_try_again:
            case boost_error::text_file_busy:
            case boost_error::too_many_files_open:
            case boost_error::too_many_files_open_in_system:
            case boost_error::too_many_links:
            case boost_error::too_many_symbolic_link_levels:
                return error::file_system;

            // unknown errors
            case boost_error::argument_list_too_long:
            case boost_error::argument_out_of_domain:
            case boost_error::function_not_supported:
            case boost_error::identifier_removed:
            case boost_error::inappropriate_io_control_operation:
            case boost_error::interrupted:
            case boost_error::invalid_argument:
            case boost_error::no_buffer_space:
            case boost_error::no_child_process:
            case boost_error::no_lock_available:
            case boost_error::no_such_process:
            case boost_error::not_a_directory:
            case boost_error::not_enough_memory:
            case boost_error::not_supported:
            case boost_error::operation_would_block:
            case boost_error::resource_deadlock_would_occur:
            case boost_error::result_out_of_range:
            case boost_error::state_not_recoverable:
            case boost_error::value_too_large:
            default:
                return error::unknown;
        }
    }

} // namespace error
} // namespace libbitcoin
<|endoftext|>


<commit_before><commit_msg>Play with elastic<commit_after><|endoftext|>


<commit_before>/*******************************************************************************
Copyright (c) 2014, Jan Koester jan.koester@gmx.net
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/

#include "event.h"
#include "threadpool.h"

libhttppp::Event::ConnectionContext::ConnectionContext(){
  _CurConnection=NULL;
  _CurCPool=NULL;
  _CurEvent=NULL;
  _Mutex=new Mutex;
  _nextConnectionContext=NULL;
}

libhttppp::Event::ConnectionContext::~ConnectionContext(){
  delete _Mutex;
  delete _nextConnectionContext;
}

libhttppp::Event::ConnectionContext * libhttppp::Event::ConnectionContext::nextConnectionContext(){
  return _nextConnectionContext;
}

void libhttppp::Event::addConnectionContext(libhttppp::Event::ConnectionContext **addcon){
if(!_firstConnectionContext){
#ifdef DEBUG_MUTEX
    _httpexception.Note("delConnection","Lock MainMutex");
#endif
    _Mutex->lock();
    _firstConnectionContext=new ConnectionContext();
    _lastConnectionContext=_firstConnectionContext;
#ifdef DEBUG_MUTEX
    _httpexception.Note("delConnection","unlock MainMutex");
#endif
    _Mutex->unlock();
  }else{
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Lock ConnectionMutex");
#endif
    ConnectionContext *prevcon=_lastConnectionContext;
    prevcon->_Mutex->lock();
    _lastConnectionContext->_nextConnectionContext=new ConnectionContext();
    _lastConnectionContext=_lastConnectionContext->_nextConnectionContext;
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Unlock ConnectionMutex");
#endif
    prevcon->_Mutex->unlock();
  }
 #ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Lock ConnectionMutex");
#endif
  _lastConnectionContext->_Mutex->lock();
  _lastConnectionContext->_CurConnection=_Cpool->addConnection();
  _lastConnectionContext->_CurCPool=_Cpool;
  _lastConnectionContext->_CurEvent=this;
  *addcon=_lastConnectionContext;
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Unlock ConnectionMutex");
#endif
  _lastConnectionContext->_Mutex->unlock();
}

void libhttppp::Event::delConnectionContext(libhttppp::Event::ConnectionContext *delctx,
                                            libhttppp::Event::ConnectionContext **nextcxt){
  ConnectionContext *prevcontext=NULL;
#ifdef DEBUG_MUTEX
  _httpexception.Note("delConnection","Lock MainMutex");
#endif
  _Mutex->lock();
  for(ConnectionContext *curcontext=_firstConnectionContext; curcontext;
      curcontext=curcontext->nextConnectionContext()){
    if(curcontext==delctx){
#ifdef DEBUG_MUTEX
      _httpexception.Note("delConnection","Lock ConnectionMutex");
#endif
      curcontext->_Mutex->lock();
      _Cpool->delConnection(curcontext->_CurConnection);
      if(prevcontext){
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","Lock prevConnectionMutex");
#endif
        prevcontext->_Mutex->lock();
        prevcontext->_nextConnectionContext=curcontext->_nextConnectionContext;
        if(_lastConnectionContext==curcontext){
          _lastConnectionContext=prevcontext;
        }
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","unlock prevConnectionMutex");
#endif
        prevcontext->_Mutex->unlock();
      }else{
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","lock firstConnectionMutex");
#endif
        _firstConnectionContext->_Mutex->lock();
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","lock lastConnectionMutex");
#endif
        _lastConnectionContext->_Mutex->lock();
        _firstConnectionContext=curcontext->_nextConnectionContext;
        if(_lastConnectionContext==delctx)
          _lastConnectionContext=_firstConnectionContext;
        if(_firstConnectionContext){
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","unlock firstConnectionMutex");
#endif
        _firstConnectionContext->_Mutex->unlock();
        }
        if(_lastConnectionContext){
#ifdef DEBUG_MUTEX
     _httpexception.Note("delConnection","unlock lastConnectionMutex");
#endif
        _lastConnectionContext->_Mutex->unlock();
        }
      }
#ifdef DEBUG_MUTEX
      _httpexception.Note("delConnection","Unlock ConnectionMutex");
#endif
      curcontext->_Mutex->unlock();
      curcontext->_nextConnectionContext=NULL;
      delete curcontext;
      break;
    }
    prevcontext=curcontext;
  }
#ifdef DEBUG_MUTEX
  _httpexception.Note("delConnection","unlock MainMutex");
#endif
  _Mutex->unlock();
  if(prevcontext && prevcontext->_nextConnectionContext){
    *nextcxt= prevcontext->_nextConnectionContext;
  }else{
    *nextcxt=_firstConnectionContext;
  }
}

libhttppp::Event::WorkerContext::WorkerContext(){
    _CurEvent=NULL;
    _CurThread=NULL;
    _nextWorkerContext=NULL;
}

libhttppp::Event::WorkerContext::~WorkerContext(){
    delete _nextWorkerContext;
}

libhttppp::Event::WorkerContext *libhttppp::Event::addWorkerContext(){
    if(_firstWorkerContext){
        _lastWorkerContext->_nextWorkerContext=new WorkerContext;
        _lastWorkerContext=_lastWorkerContext->_nextWorkerContext;
    }else{
        _firstWorkerContext=new WorkerContext;
        _lastWorkerContext = _firstWorkerContext;
    }
    _lastWorkerContext->_CurEvent=this;
    _lastWorkerContext->_CurThread=_WorkerPool->addThread();
    return _lastWorkerContext;
}

libhttppp::Event::WorkerContext *libhttppp::Event::delWorkerContext(
    libhttppp::Event::WorkerContext *delwrkctx){
    WorkerContext *prevwrk=NULL;
    for(WorkerContext *curwrk=_firstWorkerContext; curwrk; curwrk=curwrk->_nextWorkerContext){
        if(curwrk==delwrkctx){
            if(prevwrk){
                prevwrk->_nextWorkerContext=curwrk->_nextWorkerContext;
            }
            if(curwrk==_firstWorkerContext){
              _firstWorkerContext=curwrk->_nextWorkerContext;
            }
            if(curwrk==_lastWorkerContext){
              _lastWorkerContext=prevwrk;
            }
            curwrk->_nextWorkerContext=NULL;
            delete curwrk;
        }
        prevwrk=curwrk;
    }
    if(prevwrk)
        return prevwrk->_nextWorkerContext;
    else
        return _firstWorkerContext;
}

/*Event Handlers*/
void libhttppp::Event::RequestEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::ResponseEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::ConnectEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::DisconnectEvent(libhttppp::Connection *curcon) {
    return;
}
<commit_msg>fixed addevent<commit_after>/*******************************************************************************
Copyright (c) 2014, Jan Koester jan.koester@gmx.net
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/

#include "event.h"
#include "threadpool.h"

libhttppp::Event::ConnectionContext::ConnectionContext(){
  _CurConnection=NULL;
  _CurCPool=NULL;
  _CurEvent=NULL;
  _Mutex=new Mutex;
  _nextConnectionContext=NULL;
}

libhttppp::Event::ConnectionContext::~ConnectionContext(){
  delete _Mutex;
  delete _nextConnectionContext;
}

libhttppp::Event::ConnectionContext * libhttppp::Event::ConnectionContext::nextConnectionContext(){
  return _nextConnectionContext;
}

void libhttppp::Event::addConnectionContext(libhttppp::Event::ConnectionContext **addcon){
if(!_firstConnectionContext){
#ifdef DEBUG_MUTEX
    _httpexception.Note("delConnection","Lock MainMutex");
#endif
    _Mutex->lock();
    _firstConnectionContext=new ConnectionContext();
    _lastConnectionContext=_firstConnectionContext;
#ifdef DEBUG_MUTEX
    _httpexception.Note("delConnection","unlock MainMutex");
#endif
    _Mutex->unlock();
  }else{
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Lock ConnectionMutex");
#endif
    ConnectionContext *prevcon=_lastConnectionContext;
    prevcon->_Mutex->lock();
    _lastConnectionContext->_nextConnectionContext=new ConnectionContext();
    _lastConnectionContext=_lastConnectionContext->_nextConnectionContext;
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Unlock ConnectionMutex");
#endif
    prevcon->_Mutex->unlock();
  }
 #ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Lock ConnectionMutex");
#endif
  _lastConnectionContext->_Mutex->lock();
  _lastConnectionContext->_CurConnection=_Cpool->addConnection();
  _lastConnectionContext->_CurCPool=_Cpool;
  _lastConnectionContext->_CurEvent=this;
  *addcon=_lastConnectionContext;
#ifdef DEBUG_MUTEX
    _httpexception.Note("addConnection","Unlock ConnectionMutex");
#endif
  _lastConnectionContext->_Mutex->unlock();
}

void libhttppp::Event::delConnectionContext(libhttppp::Event::ConnectionContext *delctx,
                                            libhttppp::Event::ConnectionContext **nextcxt){
  ConnectionContext *prevcontext=NULL;
#ifdef DEBUG_MUTEX
  _httpexception.Note("delConnection","Lock MainMutex");
#endif
  _Mutex->lock();
  for(ConnectionContext *curcontext=_firstConnectionContext; curcontext;
      curcontext=curcontext->nextConnectionContext()){
    if(curcontext==delctx){
#ifdef DEBUG_MUTEX
      _httpexception.Note("delConnection","Lock ConnectionMutex");
#endif
      curcontext->_Mutex->lock();
      _Cpool->delConnection(curcontext->_CurConnection);
      if(prevcontext){
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","Lock prevConnectionMutex");
#endif
        prevcontext->_Mutex->lock();
        prevcontext->_nextConnectionContext=curcontext->_nextConnectionContext;
        if(_lastConnectionContext==curcontext){
          _lastConnectionContext=prevcontext;
        }
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","unlock prevConnectionMutex");
#endif
        prevcontext->_Mutex->unlock();
      }else{
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","lock firstConnectionMutex");
#endif
        _firstConnectionContext->_Mutex->lock();
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","lock lastConnectionMutex");
#endif
        _lastConnectionContext->_Mutex->lock();
        _firstConnectionContext=curcontext->_nextConnectionContext;
        if(_lastConnectionContext==delctx)
          _lastConnectionContext=_firstConnectionContext;
        if(_firstConnectionContext){
#ifdef DEBUG_MUTEX
        _httpexception.Note("delConnection","unlock firstConnectionMutex");
#endif
        _firstConnectionContext->_Mutex->unlock();
        }
        if(_lastConnectionContext){
#ifdef DEBUG_MUTEX
     _httpexception.Note("delConnection","unlock lastConnectionMutex");
#endif
        _lastConnectionContext->_Mutex->unlock();
        }
      }
#ifdef DEBUG_MUTEX
      _httpexception.Note("delConnection","Unlock ConnectionMutex");
#endif
      curcontext->_Mutex->unlock();
      curcontext->_nextConnectionContext=NULL;
      delete curcontext;
      break;
    }
    prevcontext=curcontext;
  }
#ifdef DEBUG_MUTEX
  _httpexception.Note("delConnection","unlock MainMutex");
#endif
  _Mutex->unlock();
  if(prevcontext && prevcontext->_nextConnectionContext){
    *nextcxt= prevcontext->_nextConnectionContext;
  }else{
      if(_firstConnectionContext)
        *nextcxt=_firstConnectionContext;
      else
        *nextcxt=NULL;
  }
}

libhttppp::Event::WorkerContext::WorkerContext(){
    _CurEvent=NULL;
    _CurThread=NULL;
    _nextWorkerContext=NULL;
}

libhttppp::Event::WorkerContext::~WorkerContext(){
    delete _nextWorkerContext;
}

libhttppp::Event::WorkerContext *libhttppp::Event::addWorkerContext(){
    if(_firstWorkerContext){
        _lastWorkerContext->_nextWorkerContext=new WorkerContext;
        _lastWorkerContext=_lastWorkerContext->_nextWorkerContext;
    }else{
        _firstWorkerContext=new WorkerContext;
        _lastWorkerContext = _firstWorkerContext;
    }
    _lastWorkerContext->_CurEvent=this;
    _lastWorkerContext->_CurThread=_WorkerPool->addThread();
    return _lastWorkerContext;
}

libhttppp::Event::WorkerContext *libhttppp::Event::delWorkerContext(
    libhttppp::Event::WorkerContext *delwrkctx){
    WorkerContext *prevwrk=NULL;
    for(WorkerContext *curwrk=_firstWorkerContext; curwrk; curwrk=curwrk->_nextWorkerContext){
        if(curwrk==delwrkctx){
            if(prevwrk){
                prevwrk->_nextWorkerContext=curwrk->_nextWorkerContext;
            }
            if(curwrk==_firstWorkerContext){
              _firstWorkerContext=curwrk->_nextWorkerContext;
            }
            if(curwrk==_lastWorkerContext){
              _lastWorkerContext=prevwrk;
            }
            curwrk->_nextWorkerContext=NULL;
            delete curwrk;
        }
        prevwrk=curwrk;
    }
    if(prevwrk)
        return prevwrk->_nextWorkerContext;
    else
        return _firstWorkerContext;
}

/*Event Handlers*/
void libhttppp::Event::RequestEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::ResponseEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::ConnectEvent(libhttppp::Connection *curcon) {
    return;
}

void libhttppp::Event::DisconnectEvent(libhttppp::Connection *curcon) {
    return;
}
<|endoftext|>


<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2009 Scientific Computing and Imaging Institute,
   University of Utah.

   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.
   */

// Testing libraries
#include <Testing/ModuleTestBase/ModuleTestBase.h>
#include <Testing/Utils/MatrixTestUtilities.h>
#include <Testing/Utils/SCIRunUnitTests.h>

// General Libraries
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>

// DataType libraries
#include <Core/Datatypes/DenseMatrix.h>
#include <Core/Datatypes/DenseColumnMatrix.h>

// Tikhonov specific
#include <Modules/Legacy/Inverse/SolveInverseProblemWithTikhonovImpl.h>
#include <Modules/Legacy/Inverse/SolveInverseProblemWithTikhonov.h>

using namespace SCIRun;
using namespace SCIRun::Testing;
using namespace SCIRun::Modules;
//  using namespace SCIRun::Modules::Math;
using namespace SCIRun::Core::Datatypes;
using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Dataflow::Networks;
using namespace SCIRun::TestUtils;
using ::testing::_;
using ::testing::NiceMock;
using ::testing::DefaultValue;
using ::testing::Return;

class TikhonovFunctionalTest : public ModuleTest
{
};

// NULL fwd matrix + NULL measure data
TEST_F(TikhonovFunctionalTest, loadNullFwdMatrixANDNullData)
{
  // create inputs
  auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
  MatrixHandle nullMatrix, nullColumnMatrix;
  // input data
  stubPortNWithThisData(tikAlgImp, 0, nullMatrix);
  stubPortNWithThisData(tikAlgImp, 2, nullColumnMatrix);
  // check result
  EXPECT_THROW(tikAlgImp->execute(), NullHandleOnPortException);

}

// ID fwd matrix + null measured data
TEST_F(TikhonovFunctionalTest, loadIDFwdMatrixANDNullData)
{
  // create inputs
  auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
  MatrixHandle fwdMatrix(new DenseMatrix(DenseMatrix::Identity(3, 3)));    // forward matrix (IDentityt)
  MatrixHandle nullColumnMatrix;              // measurement data (null)

  // input data
  stubPortNWithThisData(tikAlgImp, 0, fwdMatrix);
  stubPortNWithThisData(tikAlgImp, 2, nullColumnMatrix);
  // check result
  EXPECT_THROW(tikAlgImp->execute(), NullHandleOnPortException);

}

// NULL fwd matrix + RANF measured data
TEST_F(TikhonovFunctionalTest, loadNullFwdMatrixANDRandData)
{
  // create inputs
  auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
  MatrixHandle fwdMatrix;    // forward matrix (IDentityt)
  MatrixHandle measuredData(new DenseMatrix(DenseMatrix::Random(3, 1)));    // measurement data (rand)

  // input data
  stubPortNWithThisData(tikAlgImp, 0, fwdMatrix);
  stubPortNWithThisData(tikAlgImp, 2, measuredData);
  // check result
  EXPECT_THROW(tikAlgImp->execute(), NullHandleOnPortException);

}

// ID fwd matrix + RAND measured data
TEST_F(TikhonovFunctionalTest, loadIDFwdMatrixANDRandData)
{
  // create inputs
  auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
  MatrixHandle fwdMatrix(new DenseMatrix(DenseMatrix::Identity(3, 3)));    // forward matrix (IDentityt)
  MatrixHandle measuredData(new DenseMatrix(DenseMatrix::Random(3, 1)));   // measurement data (rand)

  // input data
  stubPortNWithThisData(tikAlgImp, 0, fwdMatrix);
  stubPortNWithThisData(tikAlgImp, 2, measuredData);
  // check result
  EXPECT_NO_THROW(tikAlgImp->execute());

}

// ID non-square fwd matrix + RAND measured data  (underdetermined)
// TODO: FAILS TEST: fails test when it shouldn't. The sizes of forward matrix and data are the same
TEST_F(TikhonovFunctionalTest, DISABLED_loadIDNonSquareFwdMatrixANDRandData)
{
  // create inputs
  auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
  MatrixHandle fwdMatrix(new DenseMatrix(DenseMatrix::Identity(3, 4)));    // forward matrix (IDentityt)
  MatrixHandle measuredData(new DenseMatrix(DenseMatrix::Random(4, 1)));   // measurement data (rand)

  // input data
  stubPortNWithThisData(tikAlgImp, 0, fwdMatrix);
  stubPortNWithThisData(tikAlgImp, 2, measuredData);
  // check result
  EXPECT_NO_THROW(tikAlgImp->execute());
}

// ID non-square fwd matrix + RAND measured data  (overdetermined)
TEST_F(TikhonovFunctionalTest, loadIDNonSquareFwdMatrixANDRandData2)
{
  // create inputs
  auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
  MatrixHandle fwdMatrix(new DenseMatrix(DenseMatrix::Identity(4, 3)));    // forward matrix (IDentityt)
  MatrixHandle measuredData(new DenseMatrix(DenseMatrix::Random(3, 1)));   // measurement data (rand)

  // input data
  stubPortNWithThisData(tikAlgImp, 0, fwdMatrix);
  stubPortNWithThisData(tikAlgImp, 2, measuredData);
  // check result
  EXPECT_NO_THROW(tikAlgImp->execute());
}

// ID square fwd matrix + RAND measured data  - different sizes
TEST_F(TikhonovFunctionalTest, loadIDSquareFwdMatrixANDRandDataDiffSizes)
{
  // create inputs
  auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
  MatrixHandle fwdMatrix(new DenseMatrix(DenseMatrix::Identity(3, 3)));    // forward matrix (IDentityt)
  MatrixHandle measuredData(new DenseMatrix(DenseMatrix::Random(4, 1)));   // measurement data (rand)

  // input data
  stubPortNWithThisData(tikAlgImp, 0, fwdMatrix);
  stubPortNWithThisData(tikAlgImp, 2, measuredData);
  // check result
  EXPECT_THROW(tikAlgImp->execute(), SCIRun::Core::DimensionMismatch);
}

// ID non-square fwd matrix + RAND measured data  - different sizes
// TODO: FAILS TEST: does not fail test when it shouldn't. The sizes of forward matrix and data are the different (note that this is only for size(fwd,2) < size(data,1) )!
TEST_F(TikhonovFunctionalTest, DISABLED_loadIDNonSquareFwdMatrixANDRandDataDiffSizes)
{
  // create inputs
  auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
  MatrixHandle fwdMatrix(new DenseMatrix(DenseMatrix::Identity(3, 4)));    // forward matrix (IDentityt)
  MatrixHandle measuredData(new DenseMatrix(DenseMatrix::Random(3, 1)));   // measurement data (rand)

  // input data
  stubPortNWithThisData(tikAlgImp, 0, fwdMatrix);
  stubPortNWithThisData(tikAlgImp, 2, measuredData);
  // check result
  EXPECT_THROW(tikAlgImp->execute(), SCIRun::Core::DimensionMismatch);
}
<commit_msg>started adding functional tests. need to figure how to extract results<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2009 Scientific Computing and Imaging Institute,
   University of Utah.

   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.
   */

// Testing libraries
#include <Testing/ModuleTestBase/ModuleTestBase.h>
#include <Testing/Utils/MatrixTestUtilities.h>
#include <Testing/Utils/SCIRunUnitTests.h>

// General Libraries
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>

// DataType libraries
#include <Core/Datatypes/DenseMatrix.h>
#include <Core/Datatypes/DenseColumnMatrix.h>

// Tikhonov specific
#include <Modules/Legacy/Inverse/SolveInverseProblemWithTikhonovImpl.h>
#include <Modules/Legacy/Inverse/SolveInverseProblemWithTikhonov.h>

using namespace SCIRun;
using namespace SCIRun::Testing;
using namespace SCIRun::Modules;
//  using namespace SCIRun::Modules::Math;
using namespace SCIRun::Core::Datatypes;
using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Dataflow::Networks;
using namespace SCIRun::TestUtils;
using namespace SCIRun::Modules::Inverse;
using ::testing::_;
using ::testing::NiceMock;
using ::testing::DefaultValue;
using ::testing::Return;
using ::testing::Values;
using ::testing::Combine;
using ::testing::Range;

class TikhonovFunctionalTest : public ModuleTest
{
};

namespace  {
    const double abs_error = 0.000001;
}

/// -------- INPUTS TESTS ------------ ///

// NULL fwd matrix + NULL measure data
TEST_F(TikhonovFunctionalTest, loadNullFwdMatrixANDNullData)
{
  // create inputs
  auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
  MatrixHandle nullMatrix, nullColumnMatrix;
  // input data
  stubPortNWithThisData(tikAlgImp, 0, nullMatrix);
  stubPortNWithThisData(tikAlgImp, 2, nullColumnMatrix);
  // check result
  EXPECT_THROW(tikAlgImp->execute(), NullHandleOnPortException);

}

// ID fwd matrix + null measured data
TEST_F(TikhonovFunctionalTest, loadIDFwdMatrixANDNullData)
{
  // create inputs
  auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
  MatrixHandle fwdMatrix(new DenseMatrix(DenseMatrix::Identity(3, 3)));    // forward matrix (IDentityt)
  MatrixHandle nullColumnMatrix;              // measurement data (null)

  // input data
  stubPortNWithThisData(tikAlgImp, 0, fwdMatrix);
  stubPortNWithThisData(tikAlgImp, 2, nullColumnMatrix);
  // check result
  EXPECT_THROW(tikAlgImp->execute(), NullHandleOnPortException);

}

// NULL fwd matrix + RANF measured data
TEST_F(TikhonovFunctionalTest, loadNullFwdMatrixANDRandData)
{
  // create inputs
  auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
  MatrixHandle fwdMatrix;    // forward matrix (IDentityt)
  MatrixHandle measuredData(new DenseMatrix(DenseMatrix::Random(3, 1)));    // measurement data (rand)

  // input data
  stubPortNWithThisData(tikAlgImp, 0, fwdMatrix);
  stubPortNWithThisData(tikAlgImp, 2, measuredData);
  // check result
  EXPECT_THROW(tikAlgImp->execute(), NullHandleOnPortException);

}

// ID squared fwd matrix + RAND measured data
TEST_F(TikhonovFunctionalTest, loadIDFwdMatrixANDRandData)
{
  // create inputs
  auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
  MatrixHandle fwdMatrix(new DenseMatrix(DenseMatrix::Identity(3, 3)));    // forward matrix (IDentityt)
  MatrixHandle measuredData(new DenseMatrix(DenseMatrix::Random(3, 1)));   // measurement data (rand)

  // input data
  stubPortNWithThisData(tikAlgImp, 0, fwdMatrix);
  stubPortNWithThisData(tikAlgImp, 2, measuredData);
  // check result
  EXPECT_NO_THROW(tikAlgImp->execute());

}

// ID non-square fwd matrix + RAND measured data  (underdetermined)
// TODO: FAILS TEST: fails test when it shouldn't. The sizes of forward matrix and data are the same
TEST_F(TikhonovFunctionalTest, DISABLED_loadIDNonSquareFwdMatrixANDRandData)
{
  // create inputs
  auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
  MatrixHandle fwdMatrix(new DenseMatrix(DenseMatrix::Identity(3, 4)));    // forward matrix (IDentityt)
  MatrixHandle measuredData(new DenseMatrix(DenseMatrix::Random(4, 1)));   // measurement data (rand)

  // input data
  stubPortNWithThisData(tikAlgImp, 0, fwdMatrix);
  stubPortNWithThisData(tikAlgImp, 2, measuredData);
  // check result
  EXPECT_NO_THROW(tikAlgImp->execute());
}

// ID non-square fwd matrix + RAND measured data  (overdetermined)
TEST_F(TikhonovFunctionalTest, loadIDNonSquareFwdMatrixANDRandData2)
{
  // create inputs
  auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
  MatrixHandle fwdMatrix(new DenseMatrix(DenseMatrix::Identity(4, 3)));    // forward matrix (IDentityt)
  MatrixHandle measuredData(new DenseMatrix(DenseMatrix::Random(3, 1)));   // measurement data (rand)

  // input data
  stubPortNWithThisData(tikAlgImp, 0, fwdMatrix);
  stubPortNWithThisData(tikAlgImp, 2, measuredData);
  // check result
  EXPECT_NO_THROW(tikAlgImp->execute());
}

// ID square fwd matrix + RAND measured data  - different sizes
TEST_F(TikhonovFunctionalTest, loadIDSquareFwdMatrixANDRandDataDiffSizes)
{
  // create inputs
  auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
  MatrixHandle fwdMatrix(new DenseMatrix(DenseMatrix::Identity(3, 3)));    // forward matrix (IDentityt)
  MatrixHandle measuredData(new DenseMatrix(DenseMatrix::Random(4, 1)));   // measurement data (rand)

  // input data
  stubPortNWithThisData(tikAlgImp, 0, fwdMatrix);
  stubPortNWithThisData(tikAlgImp, 2, measuredData);
  // check result
  EXPECT_THROW(tikAlgImp->execute(), SCIRun::Core::DimensionMismatch);
}

// ID non-square fwd matrix + RAND measured data  - different sizes
// TODO: FAILS TEST: does not fail test when it should. The sizes of forward matrix and data are the different (note that this is only for size(fwd,2) < size(data,1) )!
TEST_F(TikhonovFunctionalTest, DISABLED_loadIDNonSquareFwdMatrixANDRandDataDiffSizes)
{
  // create inputs
  auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
  MatrixHandle fwdMatrix(new DenseMatrix(DenseMatrix::Identity(3, 4)));    // forward matrix (IDentityt)
  MatrixHandle measuredData(new DenseMatrix(DenseMatrix::Random(3, 1)));   // measurement data (rand)

  // input data
  stubPortNWithThisData(tikAlgImp, 0, fwdMatrix);
  stubPortNWithThisData(tikAlgImp, 2, measuredData);
  // check result
  EXPECT_THROW(tikAlgImp->execute(), SCIRun::Core::DimensionMismatch);
}

/// -------- BASIC FUNCTIONS TESTS ------------ ///

// ID square forward matrix with ZERO regularization, RAND input
//TEST_F(TikhonovFunctionalTest, functionTestIDFwdMatrixANDRandData)
//{
//    // create inputs
//    auto tikAlgImp = makeModule("SolveInverseProblemWithTikhonov");
//    MatrixHandle fwdMatrix(new DenseMatrix(DenseMatrix::Identity(3, 3)));    // forward matrix (IDentityt)
//    MatrixHandle measuredData(new DenseMatrix(DenseMatrix::Random(3, 1)));   // measurement data (rand)
//
//    // input data
//    stubPortNWithThisData(tikAlgImp, 0, fwdMatrix);
//    stubPortNWithThisData(tikAlgImp, 2, measuredData);
//
//    // change params
//    tikAlgImp->setStateDefaults();                                                  // set default params
//    tikAlgImp->get_state()->setValue(SolveInverseProblemWithTikhonov::RegularizationMethod, std::string("single"));  // select single lambda
//    tikAlgImp->get_state()->setValue(SolveInverseProblemWithTikhonov::LambdaFromDirectEntry, 0 );                    // change lambda
//
//    // execute
//    tikAlgImp->execute();
//
//    MatrixHandle inverseSolution = tikAlgImp->outputPorts()[0];//getDataOnThisOutputPort(tikAlgImp, 0);
//
//    // check result
//    ASSERT_NEAR( inverseSolution.norm(), measuredData.norm(),  abs_error );
//}

<|endoftext|>


<commit_before><commit_msg>Disable line smoothing in plotter on GLES<commit_after><|endoftext|>


<commit_before>#ifndef RBX_BUILTIN_TUPLE_HPP
#define RBX_BUILTIN_TUPLE_HPP

#include "builtin/object.hpp"
#include "builtin/exception.hpp"
#include "type_info.hpp"

namespace rubinius {
  class Tuple : public Object {
  public:
    const static object_type type = TupleType;

    /* Body access */
    Object* field[];

    static Tuple* create(STATE, size_t fields);
    static Tuple* from(STATE, size_t fields, ...);

    // Ruby.primitive :tuple_allocate
    static Tuple* allocate(STATE, Fixnum* fields);

    // Ruby.primitive :tuple_at
    Object* at_prim(STATE, Fixnum* pos);

    Object* put(STATE, size_t idx, Object* val);

    // Ruby.primitive :tuple_put
    Object* put_prim(STATE, Fixnum* idx, Object* val);

    // Ruby.primitive :tuple_fields
    Object* fields_prim(STATE);

    // Ruby.primitive :tuple_pattern
    static Tuple* pattern(STATE, Fixnum* size, Object* val);

    // Ruby.primitive :tuple_copy_from
    Tuple* copy_from(STATE, Tuple* other, Fixnum *start, Fixnum *length, Fixnum *dest);

    // Ruby.primitive :tuple_delete_inplace
    Fixnum* delete_inplace(STATE, Fixnum *start, Fixnum *length, Object *obj);

    // Ruby.primitive :tuple_create_weakref
    static Tuple* create_weakref(STATE, Object* obj);

  public: // Inline Functions
    Object* at(STATE, size_t index) {
      if(num_fields() <= index) {
        Exception::object_bounds_exceeded_error(state, this, index);
      }
      return field[index];
    }

  public: // Rubinius Type stuff
    class Info : public TypeInfo {
    public:
      Info(object_type type, bool cleanup = false) : TypeInfo(type, cleanup) { }
      virtual void mark(Object* t, ObjectMark& mark);
      virtual void show(STATE, Object* self, int level);
      virtual void show_simple(STATE, Object* self, int level);
    };
  };
};

#endif
<commit_msg>Signal the exception properly<commit_after>#ifndef RBX_BUILTIN_TUPLE_HPP
#define RBX_BUILTIN_TUPLE_HPP

#include "builtin/object.hpp"
#include "builtin/exception.hpp"
#include "type_info.hpp"

namespace rubinius {
  class Tuple : public Object {
  public:
    const static object_type type = TupleType;

    /* Body access */
    Object* field[];

    static Tuple* create(STATE, size_t fields);
    static Tuple* from(STATE, size_t fields, ...);

    // Ruby.primitive :tuple_allocate
    static Tuple* allocate(STATE, Fixnum* fields);

    // Ruby.primitive :tuple_at
    Object* at_prim(STATE, Fixnum* pos);

    Object* put(STATE, size_t idx, Object* val);

    // Ruby.primitive :tuple_put
    Object* put_prim(STATE, Fixnum* idx, Object* val);

    // Ruby.primitive :tuple_fields
    Object* fields_prim(STATE);

    // Ruby.primitive :tuple_pattern
    static Tuple* pattern(STATE, Fixnum* size, Object* val);

    // Ruby.primitive :tuple_copy_from
    Tuple* copy_from(STATE, Tuple* other, Fixnum *start, Fixnum *length, Fixnum *dest);

    // Ruby.primitive :tuple_delete_inplace
    Fixnum* delete_inplace(STATE, Fixnum *start, Fixnum *length, Object *obj);

    // Ruby.primitive :tuple_create_weakref
    static Tuple* create_weakref(STATE, Object* obj);

  public: // Inline Functions
    Object* at(STATE, size_t index) {
      if(num_fields() <= index) {
        Exception::object_bounds_exceeded_error(state, this, index);
        return NULL;
      }
      return field[index];
    }

  public: // Rubinius Type stuff
    class Info : public TypeInfo {
    public:
      Info(object_type type, bool cleanup = false) : TypeInfo(type, cleanup) { }
      virtual void mark(Object* t, ObjectMark& mark);
      virtual void show(STATE, Object* self, int level);
      virtual void show_simple(STATE, Object* self, int level);
    };
  };
};

#endif
<|endoftext|>


<commit_before>
/**
 * This file is part of the boostcache package.
 *
 * (c) Azat Khuzhin <a3at.mail@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#include "commands.h"
#include "util/compiler.h"

#include <boost/format.hpp>

namespace PlaceHolders = std::placeholders;

Commands::Callback Commands::find(const std::string& commandName,
                                  int numberOfArguments) const
{
    HashTable::const_iterator command = m_commands.find(commandName);

    if (command == m_commands.end()) {
        return std::bind(&Commands::notImplementedYetCallback,
                         PlaceHolders::_1);
    }

    const int expectedArguments = command->second.numberOfArguments;
    if ((expectedArguments >= 0) && (expectedArguments != numberOfArguments)) {
        return std::bind(malformedArgumentsCallback,
                         PlaceHolders::_1, numberOfArguments, expectedArguments);
    }

    return command->second.callback;
}

Commands::Commands()
{
    addGenericCommands();
    addDbCommands();
}

void Commands::addGenericCommands()
{
    m_commands["COMMANDS"] =       CallbackInfo(std::bind(&Commands::commandsList,
                                                          this,
                                                          PlaceHolders::_1),
                                                0);
}

void Commands::addDbCommands()
{
    /* hashtable */
    m_commands["HGET"] =           CallbackInfo(std::bind(&Db::HashTable::get,
                                                          &m_dbHashTable,
                                                          PlaceHolders::_1),
                                                1);
    m_commands["HSET"] =           CallbackInfo(std::bind(&Db::HashTable::set,
                                                          &m_dbHashTable,
                                                          PlaceHolders::_1),
                                                2);
    m_commands["HDEL"] =           CallbackInfo(std::bind(&Db::HashTable::del,
                                                          &m_dbHashTable,
                                                          PlaceHolders::_1),
                                                1);
    /* avltree */
    m_commands["ATGET"] =          CallbackInfo(std::bind(&Db::AvlTree::get,
                                                          &m_dbAvlTree,
                                                          PlaceHolders::_1),
                                                1);
    m_commands["ATSET"] =          CallbackInfo(std::bind(&Db::AvlTree::set,
                                                          &m_dbAvlTree,
                                                          PlaceHolders::_1),
                                                2);
    m_commands["ATDEL"] =          CallbackInfo(std::bind(&Db::AvlTree::del,
                                                          &m_dbAvlTree,
                                                          PlaceHolders::_1),
                                                1);
}

std::string Commands::notImplementedYetCallback(const Command::Arguments& arguments)
{
    boost::format format = boost::format("%s is not implemented") % arguments[0];
    return Command::toErrorReplyString(boost::str(format));
}

std::string Commands::malformedArgumentsCallback(const Command::Arguments& arguments,
                                                 int inputArguments, int expectedArguments)
{
    boost::format format = boost::format("%s malformed number of arguments (%i vs %i)")
                                         % arguments[0]
                                         % inputArguments
                                         % expectedArguments;
    return Command::toErrorReplyString(boost::str(format));
}

std::string Commands::commandsList(const Command::Arguments& UNUSED(arguments))
{
    std::string asString;
    for (const HashTablePair &pair : m_commands) {
        asString += pair.first;
        asString += "\n";
    }
    return Command::toReplyString(asString);
}<commit_msg>[kernel/commands] add ADD_COMMAND() macros to avoid long lines.<commit_after>
/**
 * This file is part of the boostcache package.
 *
 * (c) Azat Khuzhin <a3at.mail@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#include "commands.h"
#include "util/compiler.h"

#include <boost/format.hpp>

namespace PlaceHolders = std::placeholders;

#define ADD_COMMAND(callback, objectPtr, argsNum) \
    CallbackInfo(std::bind(callback, objectPtr, PlaceHolders::_1), argsNum);

Commands::Callback Commands::find(const std::string& commandName,
                                  int numberOfArguments) const
{
    HashTable::const_iterator command = m_commands.find(commandName);

    if (command == m_commands.end()) {
        return std::bind(&Commands::notImplementedYetCallback,
                         PlaceHolders::_1);
    }

    const int expectedArguments = command->second.numberOfArguments;
    if ((expectedArguments >= 0) && (expectedArguments != numberOfArguments)) {
        return std::bind(malformedArgumentsCallback,
                         PlaceHolders::_1, numberOfArguments, expectedArguments);
    }

    return command->second.callback;
}

Commands::Commands()
{
    addGenericCommands();
    addDbCommands();
}

void Commands::addGenericCommands()
{
    m_commands["COMMANDS"] = ADD_COMMAND(&Commands::commandsList, this, 0);
}

void Commands::addDbCommands()
{
    /* hashtable */
    m_commands["HGET"] =   ADD_COMMAND(&Db::HashTable::get, &m_dbHashTable, 1);
    m_commands["HSET"] =   ADD_COMMAND(&Db::HashTable::set, &m_dbHashTable, 2);
    m_commands["HDEL"] =   ADD_COMMAND(&Db::HashTable::del, &m_dbHashTable, 1);
    /* avltree */
    m_commands["ATGET"] =  ADD_COMMAND(&Db::AvlTree::get, &m_dbAvlTree, 1);
    m_commands["ATSET"] =  ADD_COMMAND(&Db::AvlTree::set, &m_dbAvlTree, 2);
    m_commands["ATDEL"] =  ADD_COMMAND(&Db::AvlTree::del, &m_dbAvlTree, 1);
}

std::string Commands::notImplementedYetCallback(const Command::Arguments& arguments)
{
    boost::format format = boost::format("%s is not implemented") % arguments[0];
    return Command::toErrorReplyString(boost::str(format));
}

std::string Commands::malformedArgumentsCallback(const Command::Arguments& arguments,
                                                 int inputArguments, int expectedArguments)
{
    boost::format format = boost::format("%s malformed number of arguments (%i vs %i)")
                                         % arguments[0]
                                         % inputArguments
                                         % expectedArguments;
    return Command::toErrorReplyString(boost::str(format));
}

std::string Commands::commandsList(const Command::Arguments& UNUSED(arguments))
{
    std::string asString;
    for (const HashTablePair &pair : m_commands) {
        asString += pair.first;
        asString += "\n";
    }
    return Command::toReplyString(asString);
}<|endoftext|>


<commit_before>// TODO: resolve after importing Oniguruma from MRI
#include <stddef.h>
#include "capi/19/include/ruby/oniguruma.h"
#include "capi/19/include/ruby/transcoder.h"
#include "capi/19/include/ruby/regenc.h"

#include "builtin/array.hpp"
#include "builtin/encoding.hpp"
#include "builtin/nativemethod.hpp"
#include "builtin/regexp.hpp"

#include "capi/capi.hpp"

#include "capi/19/include/ruby/ruby.h"
#include "capi/19/include/ruby/encoding.h"

using namespace rubinius;
using namespace rubinius::capi;

extern "C" {
  int rb_enc_coderange_asciionly_p(VALUE obj) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Object* val = env->get_object(obj);

    if(String* str = try_as<String>(val)) {
      if(CBOOL(str->ascii_only_p(env->state()))) return Qtrue;
    } else {
      rb_raise(rb_eArgError, "ENC_CODERANGE_ASCIIONLY is only defined for String");
    }

    return Qfalse;
  }

  int rb_encdb_alias(const char *alias, const char *orig) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Encoding::alias(env->state(), alias, orig);

    return Encoding::find_index(env->state(), alias);
  }

  rb_encoding* rb_utf8_encoding() {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    return Encoding::utf8_encoding(env->state())->get_encoding();
  }

  int rb_utf8_encindex(void) {
    return Encoding::eUtf8;
  }

  rb_encoding* rb_usascii_encoding() {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    return Encoding::usascii_encoding(env->state())->get_encoding();
  }

  int rb_usascii_encindex(void) {
    return Encoding::eAscii;
  }

  rb_encoding* rb_ascii8bit_encoding() {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    return Encoding::ascii8bit_encoding(env->state())->get_encoding();
  }

  int rb_ascii8bit_encindex(void) {
    return Encoding::eBinary;
  }

  rb_encoding* rb_locale_encoding(void) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    Encoding* enc = Encoding::find(env->state(), "locale");
    if(enc->nil_p()) {
      return rb_usascii_encoding();
    } else {
      return enc->get_encoding();
    }
  }

  int rb_locale_encindex(void) {
    return rb_enc_find_index(rb_locale_encoding()->name);
  }

  rb_encoding* rb_filesystem_encoding(void) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    Encoding* enc = Encoding::find(env->state(), "filesystem");
    if(enc->nil_p()) {
      return rb_ascii8bit_encoding();
    } else {
      return enc->get_encoding();
    }
  }

  int rb_filesystem_encindex(void) {
    return rb_enc_find_index(rb_filesystem_encoding()->name);
  }

  rb_encoding *rb_default_internal_encoding(void) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    Encoding* enc = Encoding::find(env->state(), "internal");
    if(enc->nil_p()) {
      return 0;
    } else {
      return enc->get_encoding();
    }
  }

  rb_encoding *rb_default_external_encoding(void) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    Encoding* enc = Encoding::find(env->state(), "external");
    if(enc->nil_p()) {
      return 0;
    } else {
      return enc->get_encoding();
    }
  }

  rb_encoding* rb_enc_get(VALUE obj) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    int index = rb_enc_get_index(obj);
    if(index < 0) return 0;

    Encoding* enc = try_as<Encoding>(
        Encoding::encoding_list(env->state())->get(env->state(), index));

    if(!enc) return 0;

    return enc->get_encoding();
  }

  VALUE rb_obj_encoding(VALUE obj) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    Object* val = env->get_object(obj);
    Encoding* enc = Encoding::get_object_encoding(env->state(), val);
    return env->get_handle(enc);
  }

  int rb_enc_get_index(VALUE obj) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Object* val = env->get_object(obj);
    if(!val->reference_p() && !val->symbol_p()) return -1;

    Encoding* enc = Encoding::get_object_encoding(env->state(), val);

    if(enc->nil_p()) return 0;

    return Encoding::find_index(env->state(), enc->get_encoding()->name);
  }

  void rb_enc_set_index(VALUE obj, int index) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Encoding* enc = Encoding::from_index(env->state(), index);
    Object* val = env->get_object(obj);

    Encoding::set_object_encoding(env->state(), val, enc);
  }

  rb_encoding* rb_enc_compatible(VALUE str1, VALUE str2) {
    // TODO
    return rb_enc_get(str1);
  }

  rb_encoding* rb_to_encoding(VALUE obj) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    int index = rb_to_encoding_index(obj);
    if(index < 0) return 0;

    Encoding* enc = try_as<Encoding>(
        Encoding::encoding_list(env->state())->get(env->state(), index));

    if(!enc) return 0;
    return enc->get_encoding();
  }

  int rb_to_encoding_index(VALUE obj) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    Encoding* enc = nil<Encoding>();

    switch(TYPE(obj)) {
    case T_ENCODING:
      enc = c_as<Encoding>(env->get_object(obj));
      break;
    case T_STRING:
      enc = Encoding::find(env->state(), RSTRING_PTR(obj));
      break;
    default:
      obj = rb_funcall(obj, rb_intern("to_str"), 0);
      enc = Encoding::find(env->state(), RSTRING_PTR(obj));
    }

    if(enc->nil_p()) return -1;

    return Encoding::find_index(env->state(), enc->get_encoding()->name);
  }

  int rb_enc_dummy_p(rb_encoding *enc) {
    // TODO
    return 0;
  }

  VALUE rb_enc_associate(VALUE obj, rb_encoding *enc) {
    return rb_enc_associate_index(obj, rb_enc_to_index(enc));
  }

  VALUE rb_enc_associate_index(VALUE obj, int index) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Encoding* enc = try_as<Encoding>(
        Encoding::encoding_list(env->state())->get(env->state(), index));

    if(!enc) return obj;

    Object* val = env->get_object(obj);

    if(String* str = try_as<String>(val)) {
      str->encoding(env->state(), enc);
    } else if(Regexp* reg = try_as<Regexp>(val)) {
      reg->encoding(env->state(), enc);
    } else if(Symbol* sym = try_as<Symbol>(val)) {
      sym->encoding(env->state(), enc);
    } else {
      rb_raise(rb_eArgError, "object does not have an associated Encoding");
    }

    return obj;
  }

  void rb_enc_copy(VALUE dest, VALUE src) {
    rb_enc_associate(dest, rb_enc_get(src));
  }

  int rb_define_dummy_encoding(const char *) {
    // TODO
    return 1;
  }

  rb_encoding* rb_enc_find(const char* name) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Encoding* enc = Encoding::find(env->state(), name);
    if(enc->nil_p()) return 0;
    return enc->get_encoding();
  }

  int rb_enc_find_index(const char *name) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    return Encoding::find_index(env->state(), name);
  }

  rb_encoding* rb_enc_from_index(int index) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Encoding* enc = Encoding::from_index(env->state(), index);
    if(enc->nil_p()) return 0;
    return enc->get_encoding();
  }

  int rb_enc_to_index(rb_encoding* enc) {
    if(enc) {
      return rb_enc_find_index(rb_enc_name(enc));
    } else {
      return Encoding::eBinary;
    }
  }

  VALUE rb_enc_from_encoding(rb_encoding *enc) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    return env->get_handle(Encoding::find(env->state(), enc->name));
  }

  int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc) {
    int n = ONIGENC_PRECISE_MBC_ENC_LEN(enc, (UChar*)p, (UChar*)e);
    if (ONIGENC_MBCLEN_CHARFOUND_P(n) && ONIGENC_MBCLEN_CHARFOUND_LEN(n) <= e-p)
      return ONIGENC_MBCLEN_CHARFOUND_LEN(n);
    else {
      int min = rb_enc_mbminlen(enc);
      return min <= e-p ? min : (int)(e-p);
    }
  }

  int rb_enc_precise_mbclen(const char* p, const char* e, rb_encoding *enc) {
    int n;
    if(e <= p) {
      return ONIGENC_CONSTRUCT_MBCLEN_NEEDMORE(1);
    }

    n = ONIGENC_PRECISE_MBC_ENC_LEN(enc, (UChar*)p, (UChar*)e);
    if(e-p < n) {
      return ONIGENC_CONSTRUCT_MBCLEN_NEEDMORE(n-(int)(e-p));
    }

    return n;
  }

  int rb_enc_codelen(int c, rb_encoding* enc)
  {
    int n = ONIGENC_CODE_TO_MBCLEN(enc, c);
    if (n == 0) {
      rb_raise(rb_eArgError, "invalid codepoint 0x%x in %s", c, rb_enc_name(enc));
    }
    return n;
  }

  char* rb_enc_nth(const char* p, const char* e, long nth, rb_encoding* enc) {
    if (rb_enc_mbmaxlen(enc) == 1) {
      p += nth;
    } else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
      p += nth * rb_enc_mbmaxlen(enc);
    } else {
      p += Encoding::find_character_byte_index((uint8_t*)p, (uint8_t*)e, nth, enc);
    }
    if (p > e) p = e;
    return (char*)p;
  }

#define ctype_test(c, ctype)  (rb_isascii(c) && ONIGENC_IS_ASCII_CODE_CTYPE((c), ctype))

  int rb_isalnum(int c) {
    return ctype_test(c, ONIGENC_CTYPE_ALNUM);
  }

  int rb_isalpha(int c) {
    return ctype_test(c, ONIGENC_CTYPE_ALPHA);
  }

  int rb_isblank(int c) {
    return ctype_test(c, ONIGENC_CTYPE_BLANK);
  }

  int rb_iscntrl(int c) {
    return ctype_test(c, ONIGENC_CTYPE_CNTRL);
  }

  int rb_isdigit(int c) {
    return ctype_test(c, ONIGENC_CTYPE_DIGIT);
  }

  int rb_isgraph(int c) {
    return ctype_test(c, ONIGENC_CTYPE_GRAPH);
  }

  int rb_islower(int c) {
    return ctype_test(c, ONIGENC_CTYPE_LOWER);
  }

  int rb_isprint(int c) {
    return ctype_test(c, ONIGENC_CTYPE_PRINT);
  }

  int rb_ispunct(int c) {
    return ctype_test(c, ONIGENC_CTYPE_PUNCT);
  }

  int rb_isspace(int c) {
    return ctype_test(c, ONIGENC_CTYPE_SPACE);
  }

  int rb_isupper(int c) {
    return ctype_test(c, ONIGENC_CTYPE_UPPER);
  }

  int rb_isxdigit(int c) {
    return ctype_test(c, ONIGENC_CTYPE_XDIGIT);
  }

  int rb_tolower(int c) {
    return rb_isascii(c) ? ONIGENC_ASCII_CODE_TO_LOWER_CASE(c) : c;
  }

  int rb_toupper(int c) {
    return rb_isascii(c) ? ONIGENC_ASCII_CODE_TO_UPPER_CASE(c) : c;
  }

  void rb_declare_transcoder(const char* from, const char* to, const char* lib) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Transcoding::declare(env->state(), from, to, lib);
  }

  void rb_register_transcoder(const rb_transcoder* trans) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Transcoding::define(env->state(), (OnigTranscodingType*)trans);
  }
}
<commit_msg>Fixed rb_enc_compatible.<commit_after>// TODO: resolve after importing Oniguruma from MRI
#include <stddef.h>
#include "capi/19/include/ruby/oniguruma.h"
#include "capi/19/include/ruby/transcoder.h"
#include "capi/19/include/ruby/regenc.h"

#include "builtin/array.hpp"
#include "builtin/encoding.hpp"
#include "builtin/nativemethod.hpp"
#include "builtin/regexp.hpp"

#include "capi/capi.hpp"

#include "capi/19/include/ruby/ruby.h"
#include "capi/19/include/ruby/encoding.h"

using namespace rubinius;
using namespace rubinius::capi;

extern "C" {
  int rb_enc_coderange_asciionly_p(VALUE obj) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Object* val = env->get_object(obj);

    if(String* str = try_as<String>(val)) {
      if(CBOOL(str->ascii_only_p(env->state()))) return Qtrue;
    } else {
      rb_raise(rb_eArgError, "ENC_CODERANGE_ASCIIONLY is only defined for String");
    }

    return Qfalse;
  }

  int rb_encdb_alias(const char *alias, const char *orig) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Encoding::alias(env->state(), alias, orig);

    return Encoding::find_index(env->state(), alias);
  }

  rb_encoding* rb_utf8_encoding() {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    return Encoding::utf8_encoding(env->state())->get_encoding();
  }

  int rb_utf8_encindex(void) {
    return Encoding::eUtf8;
  }

  rb_encoding* rb_usascii_encoding() {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    return Encoding::usascii_encoding(env->state())->get_encoding();
  }

  int rb_usascii_encindex(void) {
    return Encoding::eAscii;
  }

  rb_encoding* rb_ascii8bit_encoding() {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    return Encoding::ascii8bit_encoding(env->state())->get_encoding();
  }

  int rb_ascii8bit_encindex(void) {
    return Encoding::eBinary;
  }

  rb_encoding* rb_locale_encoding(void) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    Encoding* enc = Encoding::find(env->state(), "locale");
    if(enc->nil_p()) {
      return rb_usascii_encoding();
    } else {
      return enc->get_encoding();
    }
  }

  int rb_locale_encindex(void) {
    return rb_enc_find_index(rb_locale_encoding()->name);
  }

  rb_encoding* rb_filesystem_encoding(void) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    Encoding* enc = Encoding::find(env->state(), "filesystem");
    if(enc->nil_p()) {
      return rb_ascii8bit_encoding();
    } else {
      return enc->get_encoding();
    }
  }

  int rb_filesystem_encindex(void) {
    return rb_enc_find_index(rb_filesystem_encoding()->name);
  }

  rb_encoding *rb_default_internal_encoding(void) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    Encoding* enc = Encoding::find(env->state(), "internal");
    if(enc->nil_p()) {
      return 0;
    } else {
      return enc->get_encoding();
    }
  }

  rb_encoding *rb_default_external_encoding(void) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    Encoding* enc = Encoding::find(env->state(), "external");
    if(enc->nil_p()) {
      return 0;
    } else {
      return enc->get_encoding();
    }
  }

  rb_encoding* rb_enc_get(VALUE obj) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    int index = rb_enc_get_index(obj);
    if(index < 0) return 0;

    Encoding* enc = try_as<Encoding>(
        Encoding::encoding_list(env->state())->get(env->state(), index));

    if(!enc) return 0;

    return enc->get_encoding();
  }

  VALUE rb_obj_encoding(VALUE obj) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    Object* val = env->get_object(obj);
    Encoding* enc = Encoding::get_object_encoding(env->state(), val);
    return env->get_handle(enc);
  }

  int rb_enc_get_index(VALUE obj) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Object* val = env->get_object(obj);
    if(!val->reference_p() && !val->symbol_p()) return -1;

    Encoding* enc = Encoding::get_object_encoding(env->state(), val);

    if(enc->nil_p()) return 0;

    return Encoding::find_index(env->state(), enc->get_encoding()->name);
  }

  void rb_enc_set_index(VALUE obj, int index) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Encoding* enc = Encoding::from_index(env->state(), index);
    Object* val = env->get_object(obj);

    Encoding::set_object_encoding(env->state(), val, enc);
  }

  rb_encoding* rb_enc_compatible(VALUE a, VALUE b) {
    VALUE result = rb_funcall(rb_cEncoding, rb_intern("compatible?"), 2, a, b);

    if(result == Qnil) {
      return 0;
    } else {
      return rb_to_encoding(result);
    }
  }

  rb_encoding* rb_to_encoding(VALUE obj) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    int index = rb_to_encoding_index(obj);
    if(index < 0) return 0;

    Encoding* enc = try_as<Encoding>(
        Encoding::encoding_list(env->state())->get(env->state(), index));

    if(!enc) return 0;
    return enc->get_encoding();
  }

  int rb_to_encoding_index(VALUE obj) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();
    Encoding* enc = nil<Encoding>();

    switch(TYPE(obj)) {
    case T_ENCODING:
      enc = c_as<Encoding>(env->get_object(obj));
      break;
    case T_STRING:
      enc = Encoding::find(env->state(), RSTRING_PTR(obj));
      break;
    default:
      obj = rb_funcall(obj, rb_intern("to_str"), 0);
      enc = Encoding::find(env->state(), RSTRING_PTR(obj));
    }

    if(enc->nil_p()) return -1;

    return Encoding::find_index(env->state(), enc->get_encoding()->name);
  }

  int rb_enc_dummy_p(rb_encoding *enc) {
    // TODO
    return 0;
  }

  VALUE rb_enc_associate(VALUE obj, rb_encoding *enc) {
    return rb_enc_associate_index(obj, rb_enc_to_index(enc));
  }

  VALUE rb_enc_associate_index(VALUE obj, int index) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Encoding* enc = try_as<Encoding>(
        Encoding::encoding_list(env->state())->get(env->state(), index));

    if(!enc) return obj;

    Object* val = env->get_object(obj);

    if(String* str = try_as<String>(val)) {
      str->encoding(env->state(), enc);
    } else if(Regexp* reg = try_as<Regexp>(val)) {
      reg->encoding(env->state(), enc);
    } else if(Symbol* sym = try_as<Symbol>(val)) {
      sym->encoding(env->state(), enc);
    } else {
      rb_raise(rb_eArgError, "object does not have an associated Encoding");
    }

    return obj;
  }

  void rb_enc_copy(VALUE dest, VALUE src) {
    rb_enc_associate(dest, rb_enc_get(src));
  }

  int rb_define_dummy_encoding(const char *) {
    // TODO
    return 1;
  }

  rb_encoding* rb_enc_find(const char* name) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Encoding* enc = Encoding::find(env->state(), name);
    if(enc->nil_p()) return 0;
    return enc->get_encoding();
  }

  int rb_enc_find_index(const char *name) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    return Encoding::find_index(env->state(), name);
  }

  rb_encoding* rb_enc_from_index(int index) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Encoding* enc = Encoding::from_index(env->state(), index);
    if(enc->nil_p()) return 0;
    return enc->get_encoding();
  }

  int rb_enc_to_index(rb_encoding* enc) {
    if(enc) {
      return rb_enc_find_index(rb_enc_name(enc));
    } else {
      return Encoding::eBinary;
    }
  }

  VALUE rb_enc_from_encoding(rb_encoding *enc) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    return env->get_handle(Encoding::find(env->state(), enc->name));
  }

  int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc) {
    int n = ONIGENC_PRECISE_MBC_ENC_LEN(enc, (UChar*)p, (UChar*)e);
    if (ONIGENC_MBCLEN_CHARFOUND_P(n) && ONIGENC_MBCLEN_CHARFOUND_LEN(n) <= e-p)
      return ONIGENC_MBCLEN_CHARFOUND_LEN(n);
    else {
      int min = rb_enc_mbminlen(enc);
      return min <= e-p ? min : (int)(e-p);
    }
  }

  int rb_enc_precise_mbclen(const char* p, const char* e, rb_encoding *enc) {
    int n;
    if(e <= p) {
      return ONIGENC_CONSTRUCT_MBCLEN_NEEDMORE(1);
    }

    n = ONIGENC_PRECISE_MBC_ENC_LEN(enc, (UChar*)p, (UChar*)e);
    if(e-p < n) {
      return ONIGENC_CONSTRUCT_MBCLEN_NEEDMORE(n-(int)(e-p));
    }

    return n;
  }

  int rb_enc_codelen(int c, rb_encoding* enc)
  {
    int n = ONIGENC_CODE_TO_MBCLEN(enc, c);
    if (n == 0) {
      rb_raise(rb_eArgError, "invalid codepoint 0x%x in %s", c, rb_enc_name(enc));
    }
    return n;
  }

  char* rb_enc_nth(const char* p, const char* e, long nth, rb_encoding* enc) {
    if (rb_enc_mbmaxlen(enc) == 1) {
      p += nth;
    } else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
      p += nth * rb_enc_mbmaxlen(enc);
    } else {
      p += Encoding::find_character_byte_index((uint8_t*)p, (uint8_t*)e, nth, enc);
    }
    if (p > e) p = e;
    return (char*)p;
  }

#define ctype_test(c, ctype)  (rb_isascii(c) && ONIGENC_IS_ASCII_CODE_CTYPE((c), ctype))

  int rb_isalnum(int c) {
    return ctype_test(c, ONIGENC_CTYPE_ALNUM);
  }

  int rb_isalpha(int c) {
    return ctype_test(c, ONIGENC_CTYPE_ALPHA);
  }

  int rb_isblank(int c) {
    return ctype_test(c, ONIGENC_CTYPE_BLANK);
  }

  int rb_iscntrl(int c) {
    return ctype_test(c, ONIGENC_CTYPE_CNTRL);
  }

  int rb_isdigit(int c) {
    return ctype_test(c, ONIGENC_CTYPE_DIGIT);
  }

  int rb_isgraph(int c) {
    return ctype_test(c, ONIGENC_CTYPE_GRAPH);
  }

  int rb_islower(int c) {
    return ctype_test(c, ONIGENC_CTYPE_LOWER);
  }

  int rb_isprint(int c) {
    return ctype_test(c, ONIGENC_CTYPE_PRINT);
  }

  int rb_ispunct(int c) {
    return ctype_test(c, ONIGENC_CTYPE_PUNCT);
  }

  int rb_isspace(int c) {
    return ctype_test(c, ONIGENC_CTYPE_SPACE);
  }

  int rb_isupper(int c) {
    return ctype_test(c, ONIGENC_CTYPE_UPPER);
  }

  int rb_isxdigit(int c) {
    return ctype_test(c, ONIGENC_CTYPE_XDIGIT);
  }

  int rb_tolower(int c) {
    return rb_isascii(c) ? ONIGENC_ASCII_CODE_TO_LOWER_CASE(c) : c;
  }

  int rb_toupper(int c) {
    return rb_isascii(c) ? ONIGENC_ASCII_CODE_TO_UPPER_CASE(c) : c;
  }

  void rb_declare_transcoder(const char* from, const char* to, const char* lib) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Transcoding::declare(env->state(), from, to, lib);
  }

  void rb_register_transcoder(const rb_transcoder* trans) {
    NativeMethodEnvironment* env = NativeMethodEnvironment::get();

    Transcoding::define(env->state(), (OnigTranscodingType*)trans);
  }
}
<|endoftext|>