<commit_before>#pragma once

#include <agency/detail/config.hpp>
#include <agency/future.hpp>
#include <agency/new_executor_traits.hpp>
#include <agency/detail/executor_traits/check_for_member_functions.hpp>
#include <agency/detail/executor_traits/ignore_tail_parameters_and_invoke.hpp>
#include <type_traits>
#include <utility>

namespace agency
{
namespace detail
{
namespace new_executor_traits_detail
{
namespace multi_agent_then_execute_returning_user_specified_container_implementation_strategies
{

struct use_multi_agent_then_execute_returning_user_specified_container_member_function {};

struct use_multi_agent_then_execute_with_shared_inits_returning_user_specified_container {};

template<class Container, class Executor, class Function, class Future>
using select_multi_agent_then_execute_returning_user_specified_container_implementation =
  typename std::conditional<
    has_multi_agent_then_execute_returning_user_specified_container<Container,Executor,Function,Future>::value,
    use_multi_agent_then_execute_returning_user_specified_container_member_function,
    use_multi_agent_then_execute_with_shared_inits_returning_user_specified_container
  >::type;

template<class Container, class Executor, class Function, class Future>
typename new_executor_traits<Executor>::template future<Container>
  multi_agent_then_execute_returning_user_specified_container(use_multi_agent_then_execute_returning_user_specified_container_member_function,
                                                              Executor& ex, Function f, typename new_executor_traits<Executor>::shape_type shape, Future& fut)
{
  return ex.template then_execute<Container>(f, shape, fut);
} // end multi_agent_then_execute_returning_user_specified_container()

template<class Function, class T>
struct ignore_tail_parameters_and_invoke
{
  mutable Function f;

  template<class Index, class... Args>
  __AGENCY_ANNOTATION
  typename std::result_of<Function(Index,T&)>::type
  operator()(const Index& idx, T& past_arg, Args&&...) const
  {
    // XXX should use std::invoke
    return f(idx, past_arg);
  }
};

template<class Function>
struct ignore_tail_parameters_and_invoke<Function,void>
{
  mutable Function f;

  template<class Index, class... Args>
  __AGENCY_ANNOTATION
  typename std::result_of<Function(Index)>::type
  operator()(const Index& idx, Args&&...) const
  {
    // XXX should use std::invoke
    return f(idx);
  }
};

template<class Container, size_t... Indices, class Executor, class Function, class Future, class Tuple>
typename new_executor_traits<Executor>::template future<Container>
  multi_agent_then_execute_returning_user_specified_container_impl(detail::index_sequence<Indices...>,
                                                                   Executor& ex, Function f, typename new_executor_traits<Executor>::shape_type shape, Future& fut,
                                                                   const Tuple& tuple_of_ignored_parameters)
{
  using value_type = typename future_traits<Future>::value_type;

  return new_executor_traits<Executor>::template then_execute<Container>(ex, ignore_tail_parameters_and_invoke<Function,value_type>{f}, shape, fut, std::get<Indices>(tuple_of_ignored_parameters)...);
} // end multi_agent_then_execute_returning_user_specified_container_impl()

template<class Container, class Executor, class Function, class Future>
typename new_executor_traits<Executor>::template future<Container>
  multi_agent_then_execute_returning_user_specified_container(use_multi_agent_then_execute_with_shared_inits_returning_user_specified_container,
                                                              Executor& ex, Function f, typename new_executor_traits<Executor>::shape_type shape, Future& fut)
{
  auto tuple_of_ignored_parameters = new_executor_traits_detail::make_tuple_of_ignored_parameters(ex);

  return multi_agent_then_execute_returning_user_specified_container_impl<Container>(detail::make_index_sequence<std::tuple_size<decltype(tuple_of_ignored_parameters)>::value>(), ex, f, shape, fut, tuple_of_ignored_parameters);
} // end multi_agent_then_execute_returning_user_specified_container()

} // end multi_agent_then_execute_returning_user_specified_container_implementation_strategies
} // end new_executor_traits_detail
} // end detail

template<class Executor>
  template<class Container, class Function, class Future,
           class Enable1,
           class Enable2,
           class Enable3
           >
typename new_executor_traits<Executor>::template future<Container>
  new_executor_traits<Executor>
    ::then_execute(typename new_executor_traits<Executor>::executor_type& ex,
                   Function f,
                   typename new_executor_traits<Executor>::shape_type shape,
                   Future& fut)
{
  namespace ns = detail::new_executor_traits_detail::multi_agent_then_execute_returning_user_specified_container_implementation_strategies;

  using check_for_member_function = ns::select_multi_agent_then_execute_returning_user_specified_container_implementation<Container,Executor,Function,Future>;

  return ns::multi_agent_then_execute_returning_user_specified_container<Container>(check_for_member_function(), ex, f, shape, fut);
} // end new_executor_traits::then_execute()

} // end agency

<commit_msg>Use agency::invoke() in ignore_tail_parameters_and_invoke<commit_after>#pragma once

#include <agency/detail/config.hpp>
#include <agency/future.hpp>
#include <agency/new_executor_traits.hpp>
#include <agency/detail/executor_traits/check_for_member_functions.hpp>
#include <agency/detail/executor_traits/ignore_tail_parameters_and_invoke.hpp>
#include <agency/functional.hpp>
#include <type_traits>
#include <utility>

namespace agency
{
namespace detail
{
namespace new_executor_traits_detail
{
namespace multi_agent_then_execute_returning_user_specified_container_implementation_strategies
{

struct use_multi_agent_then_execute_returning_user_specified_container_member_function {};

struct use_multi_agent_then_execute_with_shared_inits_returning_user_specified_container {};

template<class Container, class Executor, class Function, class Future>
using select_multi_agent_then_execute_returning_user_specified_container_implementation =
  typename std::conditional<
    has_multi_agent_then_execute_returning_user_specified_container<Container,Executor,Function,Future>::value,
    use_multi_agent_then_execute_returning_user_specified_container_member_function,
    use_multi_agent_then_execute_with_shared_inits_returning_user_specified_container
  >::type;

template<class Container, class Executor, class Function, class Future>
typename new_executor_traits<Executor>::template future<Container>
  multi_agent_then_execute_returning_user_specified_container(use_multi_agent_then_execute_returning_user_specified_container_member_function,
                                                              Executor& ex, Function f, typename new_executor_traits<Executor>::shape_type shape, Future& fut)
{
  return ex.template then_execute<Container>(f, shape, fut);
} // end multi_agent_then_execute_returning_user_specified_container()

template<class Function, class T>
struct ignore_tail_parameters_and_invoke
{
  mutable Function f;

  template<class Index, class... Args>
  __AGENCY_ANNOTATION
  typename std::result_of<Function(Index,T&)>::type
  operator()(const Index& idx, T& past_arg, Args&&...) const
  {
    // XXX should use std::invoke
    return f(idx, past_arg);
  }
};

template<class Function>
struct ignore_tail_parameters_and_invoke<Function,void>
{
  mutable Function f;

  __agency_hd_warning_disable__
  template<class Index, class... Args>
  __AGENCY_ANNOTATION
  typename std::result_of<Function(Index)>::type
  operator()(const Index& idx, Args&&...) const
  {
    return agency::invoke(f, idx);
  }
};

template<class Container, size_t... Indices, class Executor, class Function, class Future, class Tuple>
typename new_executor_traits<Executor>::template future<Container>
  multi_agent_then_execute_returning_user_specified_container_impl(detail::index_sequence<Indices...>,
                                                                   Executor& ex, Function f, typename new_executor_traits<Executor>::shape_type shape, Future& fut,
                                                                   const Tuple& tuple_of_ignored_parameters)
{
  using value_type = typename future_traits<Future>::value_type;

  return new_executor_traits<Executor>::template then_execute<Container>(ex, ignore_tail_parameters_and_invoke<Function,value_type>{f}, shape, fut, std::get<Indices>(tuple_of_ignored_parameters)...);
} // end multi_agent_then_execute_returning_user_specified_container_impl()

template<class Container, class Executor, class Function, class Future>
typename new_executor_traits<Executor>::template future<Container>
  multi_agent_then_execute_returning_user_specified_container(use_multi_agent_then_execute_with_shared_inits_returning_user_specified_container,
                                                              Executor& ex, Function f, typename new_executor_traits<Executor>::shape_type shape, Future& fut)
{
  auto tuple_of_ignored_parameters = new_executor_traits_detail::make_tuple_of_ignored_parameters(ex);

  return multi_agent_then_execute_returning_user_specified_container_impl<Container>(detail::make_index_sequence<std::tuple_size<decltype(tuple_of_ignored_parameters)>::value>(), ex, f, shape, fut, tuple_of_ignored_parameters);
} // end multi_agent_then_execute_returning_user_specified_container()

} // end multi_agent_then_execute_returning_user_specified_container_implementation_strategies
} // end new_executor_traits_detail
} // end detail

template<class Executor>
  template<class Container, class Function, class Future,
           class Enable1,
           class Enable2,
           class Enable3
           >
typename new_executor_traits<Executor>::template future<Container>
  new_executor_traits<Executor>
    ::then_execute(typename new_executor_traits<Executor>::executor_type& ex,
                   Function f,
                   typename new_executor_traits<Executor>::shape_type shape,
                   Future& fut)
{
  namespace ns = detail::new_executor_traits_detail::multi_agent_then_execute_returning_user_specified_container_implementation_strategies;

  using check_for_member_function = ns::select_multi_agent_then_execute_returning_user_specified_container_implementation<Container,Executor,Function,Future>;

  return ns::multi_agent_then_execute_returning_user_specified_container<Container>(check_for_member_function(), ex, f, shape, fut);
} // end new_executor_traits::then_execute()

} // end agency

<|endoftext|>


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

#include "QUECTEL_BC95_CellularStack.h"
#include "CellularUtil.h"
#include "CellularLog.h"

using namespace mbed;
using namespace mbed_cellular_util;

QUECTEL_BC95_CellularStack::QUECTEL_BC95_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type) : AT_CellularStack(atHandler, cid, stack_type)
{
    _at.set_urc_handler("+NSONMI:", mbed::Callback<void()>(this, &QUECTEL_BC95_CellularStack::urc_nsonmi));
}

QUECTEL_BC95_CellularStack::~QUECTEL_BC95_CellularStack()
{
}

nsapi_error_t QUECTEL_BC95_CellularStack::socket_listen(nsapi_socket_t handle, int backlog)
{
    return NSAPI_ERROR_UNSUPPORTED;
}

nsapi_error_t QUECTEL_BC95_CellularStack::socket_accept(void *server, void **socket, SocketAddress *addr)
{
    return NSAPI_ERROR_UNSUPPORTED;
}

nsapi_error_t QUECTEL_BC95_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &address)
{
    CellularSocket *socket = (CellularSocket *)handle;

    _at.lock();
    if (!socket->created) {
        const nsapi_error_t error_create = create_socket_impl(socket);
        if (error_create != NSAPI_ERROR_OK) {
            return error_create;
        }
    }

    _at.cmd_start("AT+NSOCO=");
    _at.write_int(socket->id);
    _at.write_string(address.get_ip_address(), false);
    _at.write_int(address.get_port());
    _at.cmd_stop();
    _at.resp_start();
    _at.resp_stop();
    _at.unlock();

    if (_at.get_last_error() == NSAPI_ERROR_OK) {
        socket->remoteAddress = address;
        socket->connected = true;
        return NSAPI_ERROR_OK;
    }

    return NSAPI_ERROR_NO_CONNECTION;
}

void QUECTEL_BC95_CellularStack::urc_nsonmi()
{
    int sock_id = _at.read_int();

    for (int i = 0; i < get_max_socket_count(); i++) {
        CellularSocket *sock = _socket[i];
        if (sock && sock->id == sock_id) {
            if (sock->_cb) {
                sock->_cb(sock->_data);
            }
            break;
        }
    }
}

int QUECTEL_BC95_CellularStack::get_max_socket_count()
{
    return BC95_SOCKET_MAX;
}

bool QUECTEL_BC95_CellularStack::is_protocol_supported(nsapi_protocol_t protocol)
{
    return (protocol == NSAPI_UDP || protocol == NSAPI_TCP);
}

nsapi_error_t QUECTEL_BC95_CellularStack::socket_close_impl(int sock_id)
{
    _at.cmd_start("AT+NSOCL=");
    _at.write_int(sock_id);
    _at.cmd_stop_read_resp();

    tr_info("Close socket: %d error: %d", sock_id, _at.get_last_error());

    return _at.get_last_error();
}

nsapi_error_t QUECTEL_BC95_CellularStack::create_socket_impl(CellularSocket *socket)
{
    int sock_id = -1;
    bool socketOpenWorking = false;

    if (socket->proto == NSAPI_UDP) {
        _at.cmd_start("AT+NSOCR=DGRAM,17,");
    } else if (socket->proto == NSAPI_TCP) {
        _at.cmd_start("AT+NSOCR=STREAM,6,");
    } else {
        return NSAPI_ERROR_PARAMETER;
    }
    _at.write_int(socket->localAddress.get_port());
    _at.write_int(1);
    _at.cmd_stop();
    _at.resp_start();
    sock_id = _at.read_int();
    _at.resp_stop();

    socketOpenWorking = (_at.get_last_error() == NSAPI_ERROR_OK);

    if (!socketOpenWorking) {
        _at.cmd_start("AT+NSOCL=0");
        _at.cmd_stop_read_resp();

        if (socket->proto == NSAPI_UDP) {
            _at.cmd_start("AT+NSOCR=DGRAM,17,");
        } else if (socket->proto == NSAPI_TCP) {
            _at.cmd_start("AT+NSOCR=STREAM,6,");
        }
        _at.write_int(socket->localAddress.get_port());
        _at.write_int(1);
        _at.cmd_stop();
        _at.resp_start();
        sock_id = _at.read_int();
        _at.resp_stop();

        socketOpenWorking = (_at.get_last_error() == NSAPI_ERROR_OK);
    }

    if (!socketOpenWorking || (sock_id == -1)) {
        tr_error("Socket create failed!");
        return NSAPI_ERROR_NO_SOCKET;
    }

    // Check for duplicate socket id delivered by modem
    for (int i = 0; i < BC95_SOCKET_MAX; i++) {
        CellularSocket *sock = _socket[i];
        if (sock && sock->created && sock->id == sock_id) {
            tr_error("Duplicate socket index: %d created:%d, sock_id: %d", i, sock->created, sock_id);
            return NSAPI_ERROR_NO_SOCKET;
        }
    }

    tr_info("Socket create id: %d", sock_id);

    socket->id = sock_id;
    socket->created = true;

    return NSAPI_ERROR_OK;
}

nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
                                                                     const void *data, nsapi_size_t size)
{
    int sent_len = 0;

    char *hexstr = new char[size * 2 + 1];
    int hexlen = char_str_to_hex_str((const char *)data, size, hexstr);
    // NULL terminated for write_string
    hexstr[hexlen] = 0;

    if (socket->proto == NSAPI_UDP) {
        _at.cmd_start("AT+NSOST=");
        _at.write_int(socket->id);
        _at.write_string(address.get_ip_address(), false);
        _at.write_int(address.get_port());
        _at.write_int(size);
    } else if (socket->proto == NSAPI_TCP) {
        _at.cmd_start("AT+NSOSD=");
        _at.write_int(socket->id);
        _at.write_int(size);
    } else {
        delete [] hexstr;
        return NSAPI_ERROR_PARAMETER;
    }

    _at.write_string(hexstr, false);
    _at.cmd_stop();
    _at.resp_start();
    // skip socket id
    _at.skip_param();
    sent_len = _at.read_int();
    _at.resp_stop();

    delete [] hexstr;

    if (_at.get_last_error() == NSAPI_ERROR_OK) {
        return sent_len;
    }

    return _at.get_last_error();
}

nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
                                                                       void *buffer, nsapi_size_t size)
{
    nsapi_size_or_error_t recv_len = 0;
    int port;
    char ip_address[NSAPI_IP_SIZE];

    _at.cmd_start("AT+NSORF=");
    _at.write_int(socket->id);
    _at.write_int(size);
    _at.cmd_stop();
    _at.resp_start();
    // receiving socket id
    _at.skip_param();
    _at.read_string(ip_address, sizeof(ip_address));
    port = _at.read_int();
    recv_len = _at.read_int();
    int hexlen = _at.read_hex_string((char *)buffer, size);
    // remaining length
    _at.skip_param();
    _at.resp_stop();

    if (!recv_len || (recv_len == -1) || (_at.get_last_error() != NSAPI_ERROR_OK)) {
        return NSAPI_ERROR_WOULD_BLOCK;
    }

    if (address) {
        address->set_ip_address(ip_address);
        address->set_port(port);
    }

    if (recv_len != hexlen) {
        tr_error("Not received as much data as expected. Should receive: %d bytes, received: %d bytes", recv_len, hexlen);
    }
    return recv_len;
}
<commit_msg>Cellular: Fix max packet size for BC95 driver<commit_after>/*
 * Copyright (c) 2017, Arm Limited and affiliates.
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "QUECTEL_BC95_CellularStack.h"
#include "CellularUtil.h"
#include "CellularLog.h"

#define PACKET_SIZE_MAX 1358

using namespace mbed;
using namespace mbed_cellular_util;

QUECTEL_BC95_CellularStack::QUECTEL_BC95_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type) : AT_CellularStack(atHandler, cid, stack_type)
{
    _at.set_urc_handler("+NSONMI:", mbed::Callback<void()>(this, &QUECTEL_BC95_CellularStack::urc_nsonmi));
}

QUECTEL_BC95_CellularStack::~QUECTEL_BC95_CellularStack()
{
}

nsapi_error_t QUECTEL_BC95_CellularStack::socket_listen(nsapi_socket_t handle, int backlog)
{
    return NSAPI_ERROR_UNSUPPORTED;
}

nsapi_error_t QUECTEL_BC95_CellularStack::socket_accept(void *server, void **socket, SocketAddress *addr)
{
    return NSAPI_ERROR_UNSUPPORTED;
}

nsapi_error_t QUECTEL_BC95_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &address)
{
    CellularSocket *socket = (CellularSocket *)handle;

    _at.lock();
    if (!socket->created) {
        const nsapi_error_t error_create = create_socket_impl(socket);
        if (error_create != NSAPI_ERROR_OK) {
            return error_create;
        }
    }

    _at.cmd_start("AT+NSOCO=");
    _at.write_int(socket->id);
    _at.write_string(address.get_ip_address(), false);
    _at.write_int(address.get_port());
    _at.cmd_stop();
    _at.resp_start();
    _at.resp_stop();
    _at.unlock();

    if (_at.get_last_error() == NSAPI_ERROR_OK) {
        socket->remoteAddress = address;
        socket->connected = true;
        return NSAPI_ERROR_OK;
    }

    return NSAPI_ERROR_NO_CONNECTION;
}

void QUECTEL_BC95_CellularStack::urc_nsonmi()
{
    int sock_id = _at.read_int();

    for (int i = 0; i < get_max_socket_count(); i++) {
        CellularSocket *sock = _socket[i];
        if (sock && sock->id == sock_id) {
            if (sock->_cb) {
                sock->_cb(sock->_data);
            }
            break;
        }
    }
}

int QUECTEL_BC95_CellularStack::get_max_socket_count()
{
    return BC95_SOCKET_MAX;
}

bool QUECTEL_BC95_CellularStack::is_protocol_supported(nsapi_protocol_t protocol)
{
    return (protocol == NSAPI_UDP || protocol == NSAPI_TCP);
}

nsapi_error_t QUECTEL_BC95_CellularStack::socket_close_impl(int sock_id)
{
    _at.cmd_start("AT+NSOCL=");
    _at.write_int(sock_id);
    _at.cmd_stop_read_resp();

    tr_info("Close socket: %d error: %d", sock_id, _at.get_last_error());

    return _at.get_last_error();
}

nsapi_error_t QUECTEL_BC95_CellularStack::create_socket_impl(CellularSocket *socket)
{
    int sock_id = -1;
    bool socketOpenWorking = false;

    if (socket->proto == NSAPI_UDP) {
        _at.cmd_start("AT+NSOCR=DGRAM,17,");
    } else if (socket->proto == NSAPI_TCP) {
        _at.cmd_start("AT+NSOCR=STREAM,6,");
    } else {
        return NSAPI_ERROR_PARAMETER;
    }
    _at.write_int(socket->localAddress.get_port());
    _at.write_int(1);
    _at.cmd_stop();
    _at.resp_start();
    sock_id = _at.read_int();
    _at.resp_stop();

    socketOpenWorking = (_at.get_last_error() == NSAPI_ERROR_OK);

    if (!socketOpenWorking) {
        _at.cmd_start("AT+NSOCL=0");
        _at.cmd_stop_read_resp();

        if (socket->proto == NSAPI_UDP) {
            _at.cmd_start("AT+NSOCR=DGRAM,17,");
        } else if (socket->proto == NSAPI_TCP) {
            _at.cmd_start("AT+NSOCR=STREAM,6,");
        }
        _at.write_int(socket->localAddress.get_port());
        _at.write_int(1);
        _at.cmd_stop();
        _at.resp_start();
        sock_id = _at.read_int();
        _at.resp_stop();

        socketOpenWorking = (_at.get_last_error() == NSAPI_ERROR_OK);
    }

    if (!socketOpenWorking || (sock_id == -1)) {
        tr_error("Socket create failed!");
        return NSAPI_ERROR_NO_SOCKET;
    }

    // Check for duplicate socket id delivered by modem
    for (int i = 0; i < BC95_SOCKET_MAX; i++) {
        CellularSocket *sock = _socket[i];
        if (sock && sock->created && sock->id == sock_id) {
            tr_error("Duplicate socket index: %d created:%d, sock_id: %d", i, sock->created, sock_id);
            return NSAPI_ERROR_NO_SOCKET;
        }
    }

    tr_info("Socket create id: %d", sock_id);

    socket->id = sock_id;
    socket->created = true;

    return NSAPI_ERROR_OK;
}

nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
                                                                     const void *data, nsapi_size_t size)
{
    int sent_len = 0;

    if (size > PACKET_SIZE_MAX) {
        return NSAPI_ERROR_PARAMETER;
    }

    char *hexstr = new char[size * 2 + 1];
    int hexlen = char_str_to_hex_str((const char *)data, size, hexstr);
    // NULL terminated for write_string
    hexstr[hexlen] = 0;

    if (socket->proto == NSAPI_UDP) {
        _at.cmd_start("AT+NSOST=");
        _at.write_int(socket->id);
        _at.write_string(address.get_ip_address(), false);
        _at.write_int(address.get_port());
        _at.write_int(size);
    } else if (socket->proto == NSAPI_TCP) {
        _at.cmd_start("AT+NSOSD=");
        _at.write_int(socket->id);
        _at.write_int(size);
    } else {
        delete [] hexstr;
        return NSAPI_ERROR_PARAMETER;
    }

    _at.write_string(hexstr, false);
    _at.cmd_stop();
    _at.resp_start();
    // skip socket id
    _at.skip_param();
    sent_len = _at.read_int();
    _at.resp_stop();

    delete [] hexstr;

    if (_at.get_last_error() == NSAPI_ERROR_OK) {
        return sent_len;
    }

    return _at.get_last_error();
}

nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
                                                                       void *buffer, nsapi_size_t size)
{
    nsapi_size_or_error_t recv_len = 0;
    int port;
    char ip_address[NSAPI_IP_SIZE];

    _at.cmd_start("AT+NSORF=");
    _at.write_int(socket->id);
    _at.write_int(size <= PACKET_SIZE_MAX ? size : PACKET_SIZE_MAX);
    _at.cmd_stop();
    _at.resp_start();
    // receiving socket id
    _at.skip_param();
    _at.read_string(ip_address, sizeof(ip_address));
    port = _at.read_int();
    recv_len = _at.read_int();
    int hexlen = _at.read_hex_string((char *)buffer, size);
    // remaining length
    _at.skip_param();
    _at.resp_stop();

    if (!recv_len || (recv_len == -1) || (_at.get_last_error() != NSAPI_ERROR_OK)) {
        return NSAPI_ERROR_WOULD_BLOCK;
    }

    if (address) {
        address->set_ip_address(ip_address);
        address->set_port(port);
    }

    if (recv_len != hexlen) {
        tr_error("Not received as much data as expected. Should receive: %d bytes, received: %d bytes", recv_len, hexlen);
    }
    return recv_len;
}
<|endoftext|>


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

/**
 * @file
 **/

#include "modules/planning/scenarios/stage_intersection_cruise_impl.h"

#include <string>

#include "cyber/common/log.h"
#include "modules/map/pnc_map/path.h"
#include "modules/planning/common/planning_context.h"
#include "modules/planning/common/util/util.h"
#include "modules/planning/scenarios/util/util.h"

namespace apollo {
namespace planning {
namespace scenario {

bool StageIntersectionCruiseImpl::CheckDone(
    const Frame& frame,
    const ScenarioConfig::ScenarioType& scenario_type,
    const ScenarioConfig::StageConfig& config,
    const bool right_of_way_status) {
  const auto& reference_line_info = frame.reference_line_info().front();

  // TODO(all): remove when pnc_junction completely available on map
  // get traffic sign overlap along reference line
  hdmap::PathOverlap* traffic_sign_overlap = nullptr;
  if (scenario_type == ScenarioConfig::STOP_SIGN_PROTECTED ||
      scenario_type == ScenarioConfig::STOP_SIGN_UNPROTECTED) {
    const auto& stop_sign_status =
        PlanningContext::Planningstatus().stop_sign();
    const std::string traffic_sign_overlap_id =
        stop_sign_status.current_stop_sign_overlap_id();
    traffic_sign_overlap = scenario::util::GetOverlapOnReferenceLine(
        reference_line_info,
        traffic_sign_overlap_id,
        ReferenceLineInfo::STOP_SIGN);
  } else if (scenario_type == ScenarioConfig::TRAFFIC_LIGHT_PROTECTED ||
      scenario_type == ScenarioConfig::TRAFFIC_LIGHT_UNPROTECTED_LEFT_TURN ||
      scenario_type == ScenarioConfig::TRAFFIC_LIGHT_UNPROTECTED_RIGHT_TURN) {
    const auto& traffic_light_status =
        PlanningContext::Planningstatus().traffic_light();
    const std::string traffic_sign_overlap_id =
        traffic_light_status.current_traffic_light_overlap_id_size() > 0 ?
            traffic_light_status.current_traffic_light_overlap_id(0) : "";
    traffic_sign_overlap = scenario::util::GetOverlapOnReferenceLine(
        reference_line_info,
        traffic_sign_overlap_id,
        ReferenceLineInfo::SIGNAL);
  }
  if (!traffic_sign_overlap) {
    return true;
  }

  const auto& pnc_junction_overlaps =
      reference_line_info.reference_line().map_path().pnc_junction_overlaps();
  if (pnc_junction_overlaps.empty()) {
    // TODO(all): remove when pnc_junction completely available on map
    // pnc_junction not exist on map, use current traffic_sign's end_s
    constexpr double kIntersectionPassDist = 20.0;  // unit: m
    const double adc_back_edge_s =
        reference_line_info.AdcSlBoundary().start_s();
    const double distance_adc_pass_traffic_sign =
        adc_back_edge_s - traffic_sign_overlap->end_s;
    ADEBUG << "distance_adc_pass_traffic_sign["
           << distance_adc_pass_traffic_sign
           << "] traffic_sign_end_s[" << traffic_sign_overlap->end_s << "]";

    return distance_adc_pass_traffic_sign >= kIntersectionPassDist;
  }

  if (!planning::util::CheckInsidePnCJunction(reference_line_info)) {
    return true;
  }

  // set right_of_way_status
  reference_line_info.SetJunctionRightOfWay(traffic_sign_overlap->start_s,
                                            right_of_way_status);

  return false;
}

}  // namespace scenario
}  // namespace planning
}  // namespace apollo
<commit_msg>planning: more updates on StageIntersectionCuiseImpl<commit_after>/******************************************************************************
 * Copyright 2019 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file
 **/

#include "modules/planning/scenarios/stage_intersection_cruise_impl.h"

#include <string>

#include "cyber/common/log.h"
#include "modules/map/pnc_map/path.h"
#include "modules/planning/common/planning_context.h"
#include "modules/planning/common/util/util.h"
#include "modules/planning/scenarios/util/util.h"

namespace apollo {
namespace planning {
namespace scenario {

bool StageIntersectionCruiseImpl::CheckDone(
    const Frame& frame,
    const ScenarioConfig::ScenarioType& scenario_type,
    const ScenarioConfig::StageConfig& config,
    const bool right_of_way_status) {
  const auto& reference_line_info = frame.reference_line_info().front();

  const auto& pnc_junction_overlaps =
      reference_line_info.reference_line().map_path().pnc_junction_overlaps();
  if (pnc_junction_overlaps.empty()) {
    // TODO(all): remove when pnc_junction completely available on map
    // pnc_junction not exist on map, use current traffic_sign's end_s
    // get traffic sign overlap along reference line
    hdmap::PathOverlap* traffic_sign_overlap = nullptr;
    if (scenario_type == ScenarioConfig::STOP_SIGN_PROTECTED ||
        scenario_type == ScenarioConfig::STOP_SIGN_UNPROTECTED) {
      // stop_sign scenarios
      const auto& stop_sign_status =
          PlanningContext::Planningstatus().stop_sign();
      const std::string traffic_sign_overlap_id =
          stop_sign_status.current_stop_sign_overlap_id();
      traffic_sign_overlap = scenario::util::GetOverlapOnReferenceLine(
          reference_line_info,
          traffic_sign_overlap_id,
          ReferenceLineInfo::STOP_SIGN);
    } else if (scenario_type == ScenarioConfig::TRAFFIC_LIGHT_PROTECTED ||
        scenario_type == ScenarioConfig::TRAFFIC_LIGHT_UNPROTECTED_LEFT_TURN ||
        scenario_type == ScenarioConfig::TRAFFIC_LIGHT_UNPROTECTED_RIGHT_TURN) {
      // traffic_light scenarios
      const auto& traffic_light_status =
          PlanningContext::Planningstatus().traffic_light();
      const std::string traffic_sign_overlap_id =
          traffic_light_status.current_traffic_light_overlap_id_size() > 0 ?
              traffic_light_status.current_traffic_light_overlap_id(0) : "";
      traffic_sign_overlap = scenario::util::GetOverlapOnReferenceLine(
          reference_line_info,
          traffic_sign_overlap_id,
          ReferenceLineInfo::SIGNAL);
    } else {
      // TODO(all): to be added
      // yield_sign scenarios
    }

    if (!traffic_sign_overlap) {
      return true;
    }

    constexpr double kIntersectionPassDist = 20.0;  // unit: m
    const double adc_back_edge_s =
        reference_line_info.AdcSlBoundary().start_s();
    const double distance_adc_pass_traffic_sign =
        adc_back_edge_s - traffic_sign_overlap->end_s;
    ADEBUG << "distance_adc_pass_traffic_sign["
           << distance_adc_pass_traffic_sign
           << "] traffic_sign_end_s[" << traffic_sign_overlap->end_s << "]";

    // set right_of_way_status
    reference_line_info.SetJunctionRightOfWay(traffic_sign_overlap->start_s,
                                              right_of_way_status);

    return distance_adc_pass_traffic_sign >= kIntersectionPassDist;
  }

  if (!planning::util::CheckInsidePnCJunction(reference_line_info)) {
    return true;
  }

  // set right_of_way_status
  hdmap::PathOverlap pnc_junction_overlap;
  const double adc_front_edge_s =
      reference_line_info.AdcSlBoundary().end_s();
  reference_line_info.GetPnCJunction(adc_front_edge_s, &pnc_junction_overlap);
  reference_line_info.SetJunctionRightOfWay(pnc_junction_overlap.start_s,
                                            right_of_way_status);

  return false;
}

}  // namespace scenario
}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>#include <v8.h>
#include <mysql.h>
#include <stdlib.h>

v8::Handle<v8::FunctionTemplate> rest;

v8::Handle<v8::Value> _mysql(const v8::Arguments& args) {
  v8::HandleScope handle_scope;
  if (args.This()->InternalFieldCount() == 0) {
    return v8::ThrowException(v8::String::New("Invalid call format. Use 'new MySQL()'"));
  }
  args.This()->SetInternalField(0, v8::Boolean::New(false));

  return args.This();
}

v8::Handle<v8::Value> _connect(const v8::Arguments& args) {
  v8::HandleScope handle_scope;
  if (args.Length() < 4) {
    return v8::ThrowException(v8::String::New("Invalid call format. Use 'mysql.connect(host, user, pass, db)'"));
  }

  MYSQL *conn;

  v8::String::Utf8Value host(args[0]);
  v8::String::Utf8Value user(args[1]);
  v8::String::Utf8Value pass(args[2]);
  v8::String::Utf8Value db(args[3]);

  conn = mysql_init(NULL);

  if (!mysql_real_connect(conn, *host, *user, *pass, *db, 0, NULL, 0)){
    return v8::Boolean::New(false);
  } else {
    mysql_query(conn, "SET NAMES 'utf8'");
    args.This()->SetInternalField(0, v8::External::New((void *)conn));
    return args.This();
  }
}

v8::Handle<v8::Value> _query(const v8::Arguments &args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> c = args.This()->GetInternalField(0);
  if (c->IsFalse()) {
    return v8::ThrowException(v8::String::New("No connection established"));
  }
  if (args.Length() < 1) {
    return v8::ThrowException(v8::String::New("No query specified"));
  }
  v8::String::Utf8Value q(args[0]);

  MYSQL * conn = reinterpret_cast<MYSQL *>(v8::Handle<v8::External>::Cast(c)->Value());
  MYSQL_RES *res;
  mysql_query(conn, *q);
  res = mysql_store_result(conn);

  if (res) {
    v8::Handle<v8::Value> resargs[] = { v8::External::New((void *) res) };
    return rest->GetFunction()->NewInstance(1, resargs);
  } else {
    return v8::Boolean::New(false);
  }
}

v8::Handle<v8::Value> _error(const v8::Arguments &args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> c = args.This()->GetInternalField(0);
  if (c->IsFalse()) {
    return v8::ThrowException(v8::String::New("No connection established"));
  }

  MYSQL * conn = reinterpret_cast<MYSQL *>(v8::Handle<v8::External>::Cast(c)->Value());

  return v8::String::New(mysql_error(conn));
}

v8::Handle<v8::Value> _errno(const v8::Arguments &args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> c = args.This()->GetInternalField(0);
  if (c->IsFalse()) {
    return v8::ThrowException(v8::String::New("No connection established"));
  }

  MYSQL * conn = reinterpret_cast<MYSQL *>(v8::Handle<v8::External>::Cast(c)->Value());

  return v8::Integer::New(mysql_errno(conn));
}

v8::Handle<v8::Value> _affectedrows(const v8::Arguments &args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> c = args.This()->GetInternalField(0);
  if (c->IsFalse()) {
    return v8::ThrowException(v8::String::New("No connection established"));
  }

  MYSQL * conn = reinterpret_cast<MYSQL *>(v8::Handle<v8::External>::Cast(c)->Value());

  return v8::Integer::New(mysql_affected_rows(conn));
}

v8::Handle<v8::Value> _insertid(const v8::Arguments &args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> c = args.This()->GetInternalField(0);
  if (c->IsFalse()) {
    return v8::ThrowException(v8::String::New("No connection established"));
  }

  MYSQL * conn = reinterpret_cast<MYSQL *>(v8::Handle<v8::External>::Cast(c)->Value());

  return v8::Integer::New(mysql_insert_id(conn));
}

v8::Handle<v8::Value> _escape(const v8::Arguments &args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> c = args.This()->GetInternalField(0);
  if (c->IsFalse()) {
    return v8::ThrowException(v8::String::New("No connection established"));
  }
  if (args.Length() < 1) {
    return v8::ThrowException(v8::String::New("Nothing to escape"));
  }
  v8::String::Utf8Value str(args[0]);

  int len = args[0]->ToString()->Utf8Length();
  char * result = (char *) malloc((2*len+1) * sizeof(char));

  MYSQL * conn = reinterpret_cast<MYSQL *>(v8::Handle<v8::External>::Cast(c)->Value());

  int length = mysql_real_escape_string(conn, result, *str, len);

  return v8::String::New(result, length);
}

v8::Handle<v8::Value> _result(const v8::Arguments & args) {
  v8::HandleScope handle_scope;
  args.This()->SetInternalField(0, args[0]);
  return args.This();
}

v8::Handle<v8::Value> _numrows(const v8::Arguments & args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> r = args.This()->GetInternalField(0);
  MYSQL_RES * res = reinterpret_cast<MYSQL_RES *>(v8::Handle<v8::External>::Cast(r)->Value());

  return v8::Integer::New(mysql_num_rows(res));
}

v8::Handle<v8::Value> _numfields(const v8::Arguments & args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> r = args.This()->GetInternalField(0);
  MYSQL_RES * res = reinterpret_cast<MYSQL_RES *>(v8::Handle<v8::External>::Cast(r)->Value());

  return v8::Integer::New(mysql_num_fields(res));
}

v8::Handle<v8::Value> _fetchnames(const v8::Arguments & args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> r = args.This()->GetInternalField(0);
  MYSQL_RES * res = reinterpret_cast<MYSQL_RES *>(v8::Handle<v8::External>::Cast(r)->Value());

  int cnt = mysql_num_fields(res);
  MYSQL_FIELD * fields = mysql_fetch_fields(res);
  v8::Handle<v8::Array> result = v8::Array::New(cnt);

  for(int i = 0; i < cnt; i++) {
    result->Set(v8::Integer::New(i), v8::String::New(fields[i].name));
  }

  return result;
}

v8::Handle<v8::Value> _fetcharrays(const v8::Arguments & args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> r = args.This()->GetInternalField(0);
  MYSQL_RES * res = reinterpret_cast<MYSQL_RES *>(v8::Handle<v8::External>::Cast(r)->Value());
  mysql_data_seek(res, 0);

  int x = mysql_num_fields(res);
  int y = mysql_num_rows(res);
  MYSQL_ROW row;
  v8::Handle<v8::Array> result = v8::Array::New(y);

  for (int i = 0; i < y; i++) {
    row = mysql_fetch_row(res);
    v8::Handle<v8::Array> item = v8::Array::New(x);
    result->Set(v8::Integer::New(i), item);
    for (int j=0; j<x; j++) {
      if (row[j] == NULL) {
        item->Set(v8::Integer::New(j), v8::Null());
      } else {
        item->Set(v8::Integer::New(j), v8::String::New(row[j]));
      }
    }
  }

  return result;
}

v8::Handle<v8::Value> _fetchobjects(const v8::Arguments & args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> r = args.This()->GetInternalField(0);
  MYSQL_RES * res = reinterpret_cast<MYSQL_RES *>(v8::Handle<v8::External>::Cast(r)->Value());
  mysql_data_seek(res, 0);

  int x = mysql_num_fields(res);
  int y = mysql_num_rows(res);
  MYSQL_FIELD * fields = mysql_fetch_fields(res);
  MYSQL_ROW row;
  v8::Handle<v8::Array> result = v8::Array::New(y);

  for (int i = 0; i < y; i++) {
    row = mysql_fetch_row(res);
    v8::Handle<v8::Object> item = v8::Object::New();
    result->Set(v8::Integer::New(i), item);
    for (int j=0; j<x; j++) {
      if (row[j] == NULL) {
        item->Set(v8::String::New(fields[j].name), v8::Null());
      } else {
        item->Set(v8::String::New(fields[j].name), v8::String::New(row[j]));
      }
    }
  }

  return result;
}

void setup_mysql(v8::Handle<v8::Object> target) {
//  v8::HandleScope handle_scope;

  v8::Handle<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(_mysql);
  ft->SetClassName(v8::String::New("MySQL"));

  v8::Handle<v8::ObjectTemplate> ot = ft->InstanceTemplate();
  ot->SetInternalFieldCount(1); /* connection */

  v8::Handle<v8::ObjectTemplate> pt = ft->PrototypeTemplate();
  pt->Set(v8::String::New("connect"), v8::FunctionTemplate::New(_connect));
  pt->Set(v8::String::New("query"), v8::FunctionTemplate::New(_query));
  pt->Set(v8::String::New("error"), v8::FunctionTemplate::New(_error));
  pt->Set(v8::String::New("errno"), v8::FunctionTemplate::New(_errno));
  pt->Set(v8::String::New("affectedRows"), v8::FunctionTemplate::New(_affectedrows));
  pt->Set(v8::String::New("escape"), v8::FunctionTemplate::New(_escape));
  pt->Set(v8::String::New("insertId"), v8::FunctionTemplate::New(_insertid));

  rest = v8::FunctionTemplate::New(_result);
  rest->SetClassName(v8::String::New("Result"));

  v8::Handle<v8::ObjectTemplate> resinst = rest->InstanceTemplate();
  resinst->SetInternalFieldCount(1);

  v8::Handle<v8::ObjectTemplate> resproto = rest->PrototypeTemplate();
  resproto->Set(v8::String::New("numRows"), v8::FunctionTemplate::New(_numrows));
  resproto->Set(v8::String::New("numFields"), v8::FunctionTemplate::New(_numfields));
  resproto->Set(v8::String::New("fetchNames"), v8::FunctionTemplate::New(_fetchnames));
  resproto->Set(v8::String::New("fetchArrays"), v8::FunctionTemplate::New(_fetcharrays));
  resproto->Set(v8::String::New("fetchObjects"), v8::FunctionTemplate::New(_fetchobjects));

  target->Set(v8::String::New("MySQL"), ft->GetFunction());
}
<commit_msg>mysql on windows<commit_after>#include <v8.h>

#ifdef windows
#  include <my_global.h>
#endif

#include <mysql.h>
#include <stdlib.h>

v8::Handle<v8::FunctionTemplate> rest;

v8::Handle<v8::Value> _mysql(const v8::Arguments& args) {
  v8::HandleScope handle_scope;
  if (args.This()->InternalFieldCount() == 0) {
    return v8::ThrowException(v8::String::New("Invalid call format. Use 'new MySQL()'"));
  }
  args.This()->SetInternalField(0, v8::Boolean::New(false));

  return args.This();
}

v8::Handle<v8::Value> _connect(const v8::Arguments& args) {
  v8::HandleScope handle_scope;
  if (args.Length() < 4) {
    return v8::ThrowException(v8::String::New("Invalid call format. Use 'mysql.connect(host, user, pass, db)'"));
  }

  MYSQL *conn;

  v8::String::Utf8Value host(args[0]);
  v8::String::Utf8Value user(args[1]);
  v8::String::Utf8Value pass(args[2]);
  v8::String::Utf8Value db(args[3]);

  conn = mysql_init(NULL);

  if (!mysql_real_connect(conn, *host, *user, *pass, *db, 0, NULL, 0)){
    return v8::Boolean::New(false);
  } else {
    mysql_query(conn, "SET NAMES 'utf8'");
    args.This()->SetInternalField(0, v8::External::New((void *)conn));
    return args.This();
  }
}

v8::Handle<v8::Value> _query(const v8::Arguments &args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> c = args.This()->GetInternalField(0);
  if (c->IsFalse()) {
    return v8::ThrowException(v8::String::New("No connection established"));
  }
  if (args.Length() < 1) {
    return v8::ThrowException(v8::String::New("No query specified"));
  }
  v8::String::Utf8Value q(args[0]);

  MYSQL * conn = reinterpret_cast<MYSQL *>(v8::Handle<v8::External>::Cast(c)->Value());
  MYSQL_RES *res;
  mysql_query(conn, *q);
  res = mysql_store_result(conn);

  if (res) {
    v8::Handle<v8::Value> resargs[] = { v8::External::New((void *) res) };
    return rest->GetFunction()->NewInstance(1, resargs);
  } else {
    return v8::Boolean::New(false);
  }
}

v8::Handle<v8::Value> _error(const v8::Arguments &args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> c = args.This()->GetInternalField(0);
  if (c->IsFalse()) {
    return v8::ThrowException(v8::String::New("No connection established"));
  }

  MYSQL * conn = reinterpret_cast<MYSQL *>(v8::Handle<v8::External>::Cast(c)->Value());

  return v8::String::New(mysql_error(conn));
}

v8::Handle<v8::Value> _errno(const v8::Arguments &args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> c = args.This()->GetInternalField(0);
  if (c->IsFalse()) {
    return v8::ThrowException(v8::String::New("No connection established"));
  }

  MYSQL * conn = reinterpret_cast<MYSQL *>(v8::Handle<v8::External>::Cast(c)->Value());

  return v8::Integer::New(mysql_errno(conn));
}

v8::Handle<v8::Value> _affectedrows(const v8::Arguments &args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> c = args.This()->GetInternalField(0);
  if (c->IsFalse()) {
    return v8::ThrowException(v8::String::New("No connection established"));
  }

  MYSQL * conn = reinterpret_cast<MYSQL *>(v8::Handle<v8::External>::Cast(c)->Value());

  return v8::Integer::New(mysql_affected_rows(conn));
}

v8::Handle<v8::Value> _insertid(const v8::Arguments &args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> c = args.This()->GetInternalField(0);
  if (c->IsFalse()) {
    return v8::ThrowException(v8::String::New("No connection established"));
  }

  MYSQL * conn = reinterpret_cast<MYSQL *>(v8::Handle<v8::External>::Cast(c)->Value());

  return v8::Integer::New(mysql_insert_id(conn));
}

v8::Handle<v8::Value> _escape(const v8::Arguments &args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> c = args.This()->GetInternalField(0);
  if (c->IsFalse()) {
    return v8::ThrowException(v8::String::New("No connection established"));
  }
  if (args.Length() < 1) {
    return v8::ThrowException(v8::String::New("Nothing to escape"));
  }
  v8::String::Utf8Value str(args[0]);

  int len = args[0]->ToString()->Utf8Length();
  char * result = (char *) malloc((2*len+1) * sizeof(char));

  MYSQL * conn = reinterpret_cast<MYSQL *>(v8::Handle<v8::External>::Cast(c)->Value());

  int length = mysql_real_escape_string(conn, result, *str, len);

  return v8::String::New(result, length);
}

v8::Handle<v8::Value> _result(const v8::Arguments & args) {
  v8::HandleScope handle_scope;
  args.This()->SetInternalField(0, args[0]);
  return args.This();
}

v8::Handle<v8::Value> _numrows(const v8::Arguments & args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> r = args.This()->GetInternalField(0);
  MYSQL_RES * res = reinterpret_cast<MYSQL_RES *>(v8::Handle<v8::External>::Cast(r)->Value());

  return v8::Integer::New(mysql_num_rows(res));
}

v8::Handle<v8::Value> _numfields(const v8::Arguments & args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> r = args.This()->GetInternalField(0);
  MYSQL_RES * res = reinterpret_cast<MYSQL_RES *>(v8::Handle<v8::External>::Cast(r)->Value());

  return v8::Integer::New(mysql_num_fields(res));
}

v8::Handle<v8::Value> _fetchnames(const v8::Arguments & args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> r = args.This()->GetInternalField(0);
  MYSQL_RES * res = reinterpret_cast<MYSQL_RES *>(v8::Handle<v8::External>::Cast(r)->Value());

  int cnt = mysql_num_fields(res);
  MYSQL_FIELD * fields = mysql_fetch_fields(res);
  v8::Handle<v8::Array> result = v8::Array::New(cnt);

  for(int i = 0; i < cnt; i++) {
    result->Set(v8::Integer::New(i), v8::String::New(fields[i].name));
  }

  return result;
}

v8::Handle<v8::Value> _fetcharrays(const v8::Arguments & args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> r = args.This()->GetInternalField(0);
  MYSQL_RES * res = reinterpret_cast<MYSQL_RES *>(v8::Handle<v8::External>::Cast(r)->Value());
  mysql_data_seek(res, 0);

  int x = mysql_num_fields(res);
  int y = mysql_num_rows(res);
  MYSQL_ROW row;
  v8::Handle<v8::Array> result = v8::Array::New(y);

  for (int i = 0; i < y; i++) {
    row = mysql_fetch_row(res);
    v8::Handle<v8::Array> item = v8::Array::New(x);
    result->Set(v8::Integer::New(i), item);
    for (int j=0; j<x; j++) {
      if (row[j] == NULL) {
        item->Set(v8::Integer::New(j), v8::Null());
      } else {
        item->Set(v8::Integer::New(j), v8::String::New(row[j]));
      }
    }
  }

  return result;
}

v8::Handle<v8::Value> _fetchobjects(const v8::Arguments & args) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::Value> r = args.This()->GetInternalField(0);
  MYSQL_RES * res = reinterpret_cast<MYSQL_RES *>(v8::Handle<v8::External>::Cast(r)->Value());
  mysql_data_seek(res, 0);

  int x = mysql_num_fields(res);
  int y = mysql_num_rows(res);
  MYSQL_FIELD * fields = mysql_fetch_fields(res);
  MYSQL_ROW row;
  v8::Handle<v8::Array> result = v8::Array::New(y);

  for (int i = 0; i < y; i++) {
    row = mysql_fetch_row(res);
    v8::Handle<v8::Object> item = v8::Object::New();
    result->Set(v8::Integer::New(i), item);
    for (int j=0; j<x; j++) {
      if (row[j] == NULL) {
        item->Set(v8::String::New(fields[j].name), v8::Null());
      } else {
        item->Set(v8::String::New(fields[j].name), v8::String::New(row[j]));
      }
    }
  }

  return result;
}

void setup_mysql(v8::Handle<v8::Object> target) {
//  v8::HandleScope handle_scope;

  v8::Handle<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(_mysql);
  ft->SetClassName(v8::String::New("MySQL"));

  v8::Handle<v8::ObjectTemplate> ot = ft->InstanceTemplate();
  ot->SetInternalFieldCount(1); /* connection */

  v8::Handle<v8::ObjectTemplate> pt = ft->PrototypeTemplate();
  pt->Set(v8::String::New("connect"), v8::FunctionTemplate::New(_connect));
  pt->Set(v8::String::New("query"), v8::FunctionTemplate::New(_query));
  pt->Set(v8::String::New("error"), v8::FunctionTemplate::New(_error));
  pt->Set(v8::String::New("errno"), v8::FunctionTemplate::New(_errno));
  pt->Set(v8::String::New("affectedRows"), v8::FunctionTemplate::New(_affectedrows));
  pt->Set(v8::String::New("escape"), v8::FunctionTemplate::New(_escape));
  pt->Set(v8::String::New("insertId"), v8::FunctionTemplate::New(_insertid));

  rest = v8::FunctionTemplate::New(_result);
  rest->SetClassName(v8::String::New("Result"));

  v8::Handle<v8::ObjectTemplate> resinst = rest->InstanceTemplate();
  resinst->SetInternalFieldCount(1);

  v8::Handle<v8::ObjectTemplate> resproto = rest->PrototypeTemplate();
  resproto->Set(v8::String::New("numRows"), v8::FunctionTemplate::New(_numrows));
  resproto->Set(v8::String::New("numFields"), v8::FunctionTemplate::New(_numfields));
  resproto->Set(v8::String::New("fetchNames"), v8::FunctionTemplate::New(_fetchnames));
  resproto->Set(v8::String::New("fetchArrays"), v8::FunctionTemplate::New(_fetcharrays));
  resproto->Set(v8::String::New("fetchObjects"), v8::FunctionTemplate::New(_fetchobjects));

  target->Set(v8::String::New("MySQL"), ft->GetFunction());
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Pavel Shramov <shramov@mexmat.net>
 *
 * json2pb is free software; you can redistribute it and/or modify
 * it under the terms of the MIT license. See LICENSE for details.
 */

#include <errno.h>
#include <jansson.h>

// Backport json_boolean if needed (for jansson <2.4)
// This macro comes from the Jansson docs, and is thus
// Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>, distributed under
// the MIT license.
#ifndef json_boolean
#define json_boolean(val) ((val) ? json_true() : json_false())
#endif

#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>

#include <json2pb.h>

#include <stdexcept>
#include <cstdio>

namespace {
#include "bin2ascii.h"
}

using google::protobuf::Message;
using google::protobuf::MessageFactory;
using google::protobuf::Descriptor;
using google::protobuf::FieldDescriptor;
using google::protobuf::EnumDescriptor;
using google::protobuf::EnumValueDescriptor;
using google::protobuf::Reflection;

struct json_autoptr {
	json_t * ptr;
	json_autoptr(json_t *json) : ptr(json) {}
	~json_autoptr() { if (ptr) json_decref(ptr); }
	json_t * release() { json_t *tmp = ptr; ptr = 0; return tmp; }
};

class j2pb_error : public std::exception {
	std::string _error;
public:
	j2pb_error(const std::string &e) : _error(e) {}
	j2pb_error(const FieldDescriptor *field, const std::string &e) : _error(field->name() + ": " + e) {}
	virtual ~j2pb_error() throw() {};

	virtual const char *what() const throw () { return _error.c_str(); };
};

static json_t * _pb2json(const Message& msg);
static json_t * _field2json(const Message& msg, const FieldDescriptor *field, size_t index)
{
	const Reflection *ref = msg.GetReflection();
	const bool repeated = field->is_repeated();
	json_t *jf = 0;
	switch (field->cpp_type())
	{
#define _CONVERT(type, ctype, fmt, sfunc, afunc)		\
		case FieldDescriptor::type: {			\
			const ctype value = (repeated)?		\
				ref->afunc(msg, field, index):	\
				ref->sfunc(msg, field);		\
			jf = fmt(value);			\
			break;					\
		}

		_CONVERT(CPPTYPE_DOUBLE, double, json_real, GetDouble, GetRepeatedDouble);
		_CONVERT(CPPTYPE_FLOAT, double, json_real, GetFloat, GetRepeatedFloat);
		_CONVERT(CPPTYPE_INT64, json_int_t, json_integer, GetInt64, GetRepeatedInt64);
		_CONVERT(CPPTYPE_UINT64, json_int_t, json_integer, GetUInt64, GetRepeatedUInt64);
		_CONVERT(CPPTYPE_INT32, json_int_t, json_integer, GetInt32, GetRepeatedInt32);
		_CONVERT(CPPTYPE_UINT32, json_int_t, json_integer, GetUInt32, GetRepeatedUInt32);
		_CONVERT(CPPTYPE_BOOL, bool, json_boolean, GetBool, GetRepeatedBool);
#undef _CONVERT
		case FieldDescriptor::CPPTYPE_STRING: {
			std::string scratch;
			const std::string &value = (repeated)?
				ref->GetRepeatedStringReference(msg, field, index, &scratch):
				ref->GetStringReference(msg, field, &scratch);
			if (field->type() == FieldDescriptor::TYPE_BYTES)
				jf = json_string(b64_encode(value).c_str());
			else
				jf = json_string(value.c_str());
			break;
		}
		case FieldDescriptor::CPPTYPE_MESSAGE: {
			const Message& mf = (repeated)?
				ref->GetRepeatedMessage(msg, field, index):
				ref->GetMessage(msg, field);
			jf = _pb2json(mf);
			break;
		}
		case FieldDescriptor::CPPTYPE_ENUM: {
			const EnumValueDescriptor* ef = (repeated)?
				ref->GetRepeatedEnum(msg, field, index):
				ref->GetEnum(msg, field);

			jf = json_integer(ef->number());
			break;
		}
		default:
			break;
	}
	if (!jf) throw j2pb_error(field, "Fail to convert to json");
	return jf;
}

static json_t * _pb2json(const Message& msg)
{
	const Descriptor *d = msg.GetDescriptor();
	const Reflection *ref = msg.GetReflection();
	if (!d || !ref) return 0;

	json_t *root = json_object();
	json_autoptr _auto(root);

    //std::cerr << msg.DebugString() << std::endl;

	std::vector<const FieldDescriptor *> fields;
	ref->ListFields(msg, &fields);

	for (size_t i = 0; i != fields.size(); i++)
	{
		const FieldDescriptor *field = fields[i];
		json_t *jf = 0;
		if(field->is_repeated()) {
			size_t count = ref->FieldSize(msg, field);
			if (!count) continue;

			json_autoptr array(json_array());
			for (size_t j = 0; j < count; j++)
				json_array_append_new(array.ptr, _field2json(msg, field, j));
			jf = array.release();
		} else if (ref->HasField(msg, field))
			jf = _field2json(msg, field, 0);
		else
			continue;

		const std::string &name = (field->is_extension())?field->full_name():field->name();
		json_object_set_new(root, name.c_str(), jf);
	}
	return _auto.release();
}

static bool string2bool(const char* str) {
    // If the string is empty, *str == 0.
    return (*str == 't' || *str == 'T' || *str == 'y' || *str == 'Y' || (*str >= '1' && *str <= '9'));
}

static void _json2pb(Message& msg, json_t *root);
static void _json2field(Message &msg, const FieldDescriptor *field, json_t *jf)
{
	const Reflection *ref = msg.GetReflection();
	const bool repeated = field->is_repeated();
	json_error_t error;

	switch (field->cpp_type())
	{
#define _SET_OR_ADD(sfunc, afunc, value)			\
		do {						\
			if (repeated)				\
				ref->afunc(&msg, field, value);	\
			else					\
				ref->sfunc(&msg, field, value);	\
		} while (0)

#define _CONVERT_WITH_STRING(type, ctype, fmt, fromstringfunc, sfunc, afunc) 		\
		case FieldDescriptor::type: {			\
			ctype value;				\
			int r = json_unpack_ex(jf, &error, JSON_STRICT, fmt, &value); \
            if (r) { \
                if (!json_is_string(jf)) throw j2pb_error(field, std::string("Failed to unpack or view as string: ") + error.text); \
			    const char * string_value = json_string_value(jf); \
                value = fromstringfunc(string_value); \
            } \
			_SET_OR_ADD(sfunc, afunc, value);	\
			break;					\
		}

		_CONVERT_WITH_STRING(CPPTYPE_DOUBLE, double, "F", atof, SetDouble, AddDouble);
		_CONVERT_WITH_STRING(CPPTYPE_FLOAT, double, "F", atof, SetFloat, AddFloat);
		_CONVERT_WITH_STRING(CPPTYPE_INT64, json_int_t, "I", std::stoll, SetInt64, AddInt64);
		_CONVERT_WITH_STRING(CPPTYPE_UINT64, json_int_t, "I", std::stoull, SetUInt64, AddUInt64);
		_CONVERT_WITH_STRING(CPPTYPE_INT32, json_int_t, "I", atoi, SetInt32, AddInt32);
		_CONVERT_WITH_STRING(CPPTYPE_UINT32, json_int_t, "I", std::stoul, SetUInt32, AddUInt32);
		_CONVERT_WITH_STRING(CPPTYPE_BOOL, int, "b", string2bool, SetBool, AddBool);

		case FieldDescriptor::CPPTYPE_STRING: {
			if (!json_is_string(jf))
				throw j2pb_error(field, "Not a string");
			const char * value = json_string_value(jf);
			if(field->type() == FieldDescriptor::TYPE_BYTES)
				_SET_OR_ADD(SetString, AddString, b64_decode(value));
			else
				_SET_OR_ADD(SetString, AddString, value);
			break;
		}
		case FieldDescriptor::CPPTYPE_MESSAGE: {
			Message *mf = (repeated)?
				ref->AddMessage(&msg, field):
				ref->MutableMessage(&msg, field);
			_json2pb(*mf, jf);
			break;
		}
		case FieldDescriptor::CPPTYPE_ENUM: {
			const EnumDescriptor *ed = field->enum_type();
			const EnumValueDescriptor *ev = 0;
			if (json_is_integer(jf)) {
				ev = ed->FindValueByNumber(json_integer_value(jf));
			} else if (json_is_string(jf)) {
				ev = ed->FindValueByName(json_string_value(jf));
			} else
				throw j2pb_error(field, "Not an integer or string");
			if (!ev)
				throw j2pb_error(field, "Enum value not found");
			_SET_OR_ADD(SetEnum, AddEnum, ev);
			break;
		}
		default:
			break;

#undef _CONVERT_WITH_STRING
#undef _SET_OR_ADD
	}
}

static void _json2pb(Message& msg, json_t *root)
{
	const Descriptor *d = msg.GetDescriptor();
	const Reflection *ref = msg.GetReflection();
	if (!d || !ref) throw j2pb_error("No descriptor or reflection");

	for (void *i = json_object_iter(root); i; i = json_object_iter_next(root, i))
	{
		const char *name = json_object_iter_key(i);
		json_t *jf = json_object_iter_value(i);

		const FieldDescriptor *field = d->FindFieldByName(name);
		if (!field)
			field = ref->FindKnownExtensionByName(name);
			//field = d->file()->FindExtensionByName(name);

		if (!field) throw j2pb_error("Unknown field: " + std::string(name));

		int r = 0;
		if (field->is_repeated()) {
			if (!json_is_array(jf))
				throw j2pb_error(field, "Not array");
			for (size_t j = 0; j < json_array_size(jf); j++)
				_json2field(msg, field, json_array_get(jf, j));
		} else
			_json2field(msg, field, jf);
	}
}

void json2pb(Message &msg, const char *buf, size_t size)
{
	json_t *root;
	json_error_t error;

	root = json_loadb(buf, size, 0, &error);

	if (!root)
		throw j2pb_error(std::string("Load failed: ") + error.text);

	json_autoptr _auto(root);

	if (!json_is_object(root))
		throw j2pb_error("Malformed JSON: not an object");

	_json2pb(msg, root);
}

void json2pb(Message &msg, FILE *fp)
{
    json_t *root;
	json_error_t error;

	root = json_loadf(fp, JSON_DISABLE_EOF_CHECK, &error);

	if (!root)
		throw j2pb_error(std::string("Load failed: ") + error.text);

	json_autoptr _auto(root);

	if (!json_is_object(root))
		throw j2pb_error("Malformed JSON: not an object");

	_json2pb(msg, root);
}

void json2pb(Message &msg, const std::string& data)
{
    json2pb(msg, data.c_str(), data.size());
}

int json_dump_std_string(const char *buf, size_t size, void *data)
{
	std::string *s = (std::string *) data;
	s->append(buf, size);
	return 0;
}

std::string pb2json(const Message &msg)
{
	std::string r;

	json_t *root = _pb2json(msg);
	json_autoptr _auto(root);
	json_dump_callback(root, json_dump_std_string, &r, 0);
	return r;
}
<commit_msg>Quote all 64-bit integers like Protobuf does<commit_after>/*
 * Copyright (c) 2013 Pavel Shramov <shramov@mexmat.net>
 *
 * json2pb is free software; you can redistribute it and/or modify
 * it under the terms of the MIT license. See LICENSE for details.
 */

#include <errno.h>
#include <jansson.h>

// Backport json_boolean if needed (for jansson <2.4)
// This macro comes from the Jansson docs, and is thus
// Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>, distributed under
// the MIT license.
#ifndef json_boolean
#define json_boolean(val) ((val) ? json_true() : json_false())
#endif

#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>

#include <json2pb.h>

#include <stdexcept>
#include <cstdio>

namespace {
#include "bin2ascii.h"
}

using google::protobuf::Message;
using google::protobuf::MessageFactory;
using google::protobuf::Descriptor;
using google::protobuf::FieldDescriptor;
using google::protobuf::EnumDescriptor;
using google::protobuf::EnumValueDescriptor;
using google::protobuf::Reflection;

struct json_autoptr {
	json_t * ptr;
	json_autoptr(json_t *json) : ptr(json) {}
	~json_autoptr() { if (ptr) json_decref(ptr); }
	json_t * release() { json_t *tmp = ptr; ptr = 0; return tmp; }
};

class j2pb_error : public std::exception {
	std::string _error;
public:
	j2pb_error(const std::string &e) : _error(e) {}
	j2pb_error(const FieldDescriptor *field, const std::string &e) : _error(field->name() + ": " + e) {}
	virtual ~j2pb_error() throw() {};

	virtual const char *what() const throw () { return _error.c_str(); };
};

static json_t * _pb2json(const Message& msg);
static json_t * _field2json(const Message& msg, const FieldDescriptor *field, size_t index)
{
	const Reflection *ref = msg.GetReflection();
	const bool repeated = field->is_repeated();
	json_t *jf = 0;
	switch (field->cpp_type())
	{
#define _CONVERT(type, ctype, fmt, sfunc, afunc)		\
		case FieldDescriptor::type: {			\
			const ctype value = (repeated)?		\
				ref->afunc(msg, field, index):	\
				ref->sfunc(msg, field);		\
			jf = fmt(value);			\
			break;					\
		}

#define _CONVERT_AS_STRING(type, ctype, sfunc, afunc)		\
		case FieldDescriptor::type: {			\
			const ctype value = (repeated)?		\
				ref->afunc(msg, field, index):	\
				ref->sfunc(msg, field);		\
            std::string quoted = std::to_string(value); \
			jf = json_string(quoted.c_str());			\
			break;					\
		}

		_CONVERT(CPPTYPE_DOUBLE, double, json_real, GetDouble, GetRepeatedDouble);
		_CONVERT(CPPTYPE_FLOAT, double, json_real, GetFloat, GetRepeatedFloat);
		_CONVERT_AS_STRING(CPPTYPE_INT64, json_int_t, GetInt64, GetRepeatedInt64);
		_CONVERT_AS_STRING(CPPTYPE_UINT64, json_int_t, GetUInt64, GetRepeatedUInt64);
		_CONVERT(CPPTYPE_INT32, json_int_t, json_integer, GetInt32, GetRepeatedInt32);
		_CONVERT(CPPTYPE_UINT32, json_int_t, json_integer, GetUInt32, GetRepeatedUInt32);
		_CONVERT(CPPTYPE_BOOL, bool, json_boolean, GetBool, GetRepeatedBool);
#undef _CONVERT_AS_STRING
#undef _CONVERT
		case FieldDescriptor::CPPTYPE_STRING: {
			std::string scratch;
			const std::string &value = (repeated)?
				ref->GetRepeatedStringReference(msg, field, index, &scratch):
				ref->GetStringReference(msg, field, &scratch);
			if (field->type() == FieldDescriptor::TYPE_BYTES)
				jf = json_string(b64_encode(value).c_str());
			else
				jf = json_string(value.c_str());
			break;
		}
		case FieldDescriptor::CPPTYPE_MESSAGE: {
			const Message& mf = (repeated)?
				ref->GetRepeatedMessage(msg, field, index):
				ref->GetMessage(msg, field);
			jf = _pb2json(mf);
			break;
		}
		case FieldDescriptor::CPPTYPE_ENUM: {
			const EnumValueDescriptor* ef = (repeated)?
				ref->GetRepeatedEnum(msg, field, index):
				ref->GetEnum(msg, field);

			jf = json_integer(ef->number());
			break;
		}
		default:
			break;
	}
	if (!jf) throw j2pb_error(field, "Fail to convert to json");
	return jf;
}

static json_t * _pb2json(const Message& msg)
{
	const Descriptor *d = msg.GetDescriptor();
	const Reflection *ref = msg.GetReflection();
	if (!d || !ref) return 0;

	json_t *root = json_object();
	json_autoptr _auto(root);

    //std::cerr << msg.DebugString() << std::endl;

	std::vector<const FieldDescriptor *> fields;
	ref->ListFields(msg, &fields);

	for (size_t i = 0; i != fields.size(); i++)
	{
		const FieldDescriptor *field = fields[i];
		json_t *jf = 0;
		if(field->is_repeated()) {
			size_t count = ref->FieldSize(msg, field);
			if (!count) continue;

			json_autoptr array(json_array());
			for (size_t j = 0; j < count; j++)
				json_array_append_new(array.ptr, _field2json(msg, field, j));
			jf = array.release();
		} else if (ref->HasField(msg, field))
			jf = _field2json(msg, field, 0);
		else
			continue;

		const std::string &name = (field->is_extension())?field->full_name():field->name();
		json_object_set_new(root, name.c_str(), jf);
	}
	return _auto.release();
}

static bool string2bool(const char* str) {
    // If the string is empty, *str == 0.
    return (*str == 't' || *str == 'T' || *str == 'y' || *str == 'Y' || (*str >= '1' && *str <= '9'));
}

static void _json2pb(Message& msg, json_t *root);
static void _json2field(Message &msg, const FieldDescriptor *field, json_t *jf)
{
	const Reflection *ref = msg.GetReflection();
	const bool repeated = field->is_repeated();
	json_error_t error;

	switch (field->cpp_type())
	{
#define _SET_OR_ADD(sfunc, afunc, value)			\
		do {						\
			if (repeated)				\
				ref->afunc(&msg, field, value);	\
			else					\
				ref->sfunc(&msg, field, value);	\
		} while (0)

#define _CONVERT_WITH_STRING(type, ctype, fmt, fromstringfunc, sfunc, afunc) 		\
		case FieldDescriptor::type: {			\
			ctype value;				\
			int r = json_unpack_ex(jf, &error, JSON_STRICT, fmt, &value); \
            if (r) { \
                if (!json_is_string(jf)) throw j2pb_error(field, std::string("Failed to unpack or view as string: ") + error.text); \
			    const char * string_value = json_string_value(jf); \
                value = fromstringfunc(string_value); \
            } \
			_SET_OR_ADD(sfunc, afunc, value);	\
			break;					\
		}

		_CONVERT_WITH_STRING(CPPTYPE_DOUBLE, double, "F", atof, SetDouble, AddDouble);
		_CONVERT_WITH_STRING(CPPTYPE_FLOAT, double, "F", atof, SetFloat, AddFloat);
		_CONVERT_WITH_STRING(CPPTYPE_INT64, json_int_t, "I", std::stoll, SetInt64, AddInt64);
		_CONVERT_WITH_STRING(CPPTYPE_UINT64, json_int_t, "I", std::stoull, SetUInt64, AddUInt64);
		_CONVERT_WITH_STRING(CPPTYPE_INT32, json_int_t, "I", atoi, SetInt32, AddInt32);
		_CONVERT_WITH_STRING(CPPTYPE_UINT32, json_int_t, "I", std::stoul, SetUInt32, AddUInt32);
		_CONVERT_WITH_STRING(CPPTYPE_BOOL, int, "b", string2bool, SetBool, AddBool);

		case FieldDescriptor::CPPTYPE_STRING: {
			if (!json_is_string(jf))
				throw j2pb_error(field, "Not a string");
			const char * value = json_string_value(jf);
			if(field->type() == FieldDescriptor::TYPE_BYTES)
				_SET_OR_ADD(SetString, AddString, b64_decode(value));
			else
				_SET_OR_ADD(SetString, AddString, value);
			break;
		}
		case FieldDescriptor::CPPTYPE_MESSAGE: {
			Message *mf = (repeated)?
				ref->AddMessage(&msg, field):
				ref->MutableMessage(&msg, field);
			_json2pb(*mf, jf);
			break;
		}
		case FieldDescriptor::CPPTYPE_ENUM: {
			const EnumDescriptor *ed = field->enum_type();
			const EnumValueDescriptor *ev = 0;
			if (json_is_integer(jf)) {
				ev = ed->FindValueByNumber(json_integer_value(jf));
			} else if (json_is_string(jf)) {
				ev = ed->FindValueByName(json_string_value(jf));
			} else
				throw j2pb_error(field, "Not an integer or string");
			if (!ev)
				throw j2pb_error(field, "Enum value not found");
			_SET_OR_ADD(SetEnum, AddEnum, ev);
			break;
		}
		default:
			break;

#undef _CONVERT_WITH_STRING
#undef _SET_OR_ADD
	}
}

static void _json2pb(Message& msg, json_t *root)
{
	const Descriptor *d = msg.GetDescriptor();
	const Reflection *ref = msg.GetReflection();
	if (!d || !ref) throw j2pb_error("No descriptor or reflection");

	for (void *i = json_object_iter(root); i; i = json_object_iter_next(root, i))
	{
		const char *name = json_object_iter_key(i);
		json_t *jf = json_object_iter_value(i);

		const FieldDescriptor *field = d->FindFieldByName(name);
		if (!field)
			field = ref->FindKnownExtensionByName(name);
			//field = d->file()->FindExtensionByName(name);

		if (!field) throw j2pb_error("Unknown field: " + std::string(name));

		int r = 0;
		if (field->is_repeated()) {
			if (!json_is_array(jf))
				throw j2pb_error(field, "Not array");
			for (size_t j = 0; j < json_array_size(jf); j++)
				_json2field(msg, field, json_array_get(jf, j));
		} else
			_json2field(msg, field, jf);
	}
}

void json2pb(Message &msg, const char *buf, size_t size)
{
	json_t *root;
	json_error_t error;

	root = json_loadb(buf, size, 0, &error);

	if (!root)
		throw j2pb_error(std::string("Load failed: ") + error.text);

	json_autoptr _auto(root);

	if (!json_is_object(root))
		throw j2pb_error("Malformed JSON: not an object");

	_json2pb(msg, root);
}

void json2pb(Message &msg, FILE *fp)
{
    json_t *root;
	json_error_t error;

	root = json_loadf(fp, JSON_DISABLE_EOF_CHECK, &error);

	if (!root)
		throw j2pb_error(std::string("Load failed: ") + error.text);

	json_autoptr _auto(root);

	if (!json_is_object(root))
		throw j2pb_error("Malformed JSON: not an object");

	_json2pb(msg, root);
}

void json2pb(Message &msg, const std::string& data)
{
    json2pb(msg, data.c_str(), data.size());
}

int json_dump_std_string(const char *buf, size_t size, void *data)
{
	std::string *s = (std::string *) data;
	s->append(buf, size);
	return 0;
}

std::string pb2json(const Message &msg)
{
	std::string r;

	json_t *root = _pb2json(msg);
	json_autoptr _auto(root);
	json_dump_callback(root, json_dump_std_string, &r, 0);
	return r;
}
<|endoftext|>


<commit_before>#include <string>
#include <iostream>
#include <utility>
#include <cstdio>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/user.h>

#include "dwarf/dwarf++.hh"
#include "elf/elf++.hh"

#include "linenoise.h"

class debugger {
public:
    debugger (std::string prog_name, pid_t pid)
        : m_prog_name{std::move(prog_name)}, m_pid{pid} {}

    void run();
private:
    void handle_command(const std::string& line);

    std::string m_prog_name;
    pid_t m_pid;
};

void debugger::run() {
    char* line = nullptr;
    while((line = linenoise("minidbg> ")) != NULL) {
        handle_command(line);
        linenoiseHistoryAdd(line);
        linenoiseFree(line);
    }
}

void debugger::handle_command(const std::string& line) {
    if (line == "cont") {
        ptrace(PTRACE_CONT, m_pid, NULL, NULL);
    }
    else {
        std::cerr << "Unknown command\n";
    }
}

void execute_debugger (const std::string& prog_name, pid_t pid) {
    int wait_status;
    wait(&wait_status);

    auto fd = open(prog_name.c_str(), O_RDONLY);

    elf::elf ef(elf::create_mmap_loader(fd));
    dwarf::dwarf dw(dwarf::elf::create_loader(ef));

    debugger dbg{prog_name, pid};
    dbg.run();
}

void execute_debugee (const std::string& prog_name) {
  if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
      std::cerr << "Error in ptrace\n";
      return;
  }
  execl(prog_name.c_str(), prog_name.c_str(), NULL);
}

int main(int argc, char* argv[]) {
    auto prog = argv[1];

    auto pid = fork();
    if (pid == 0) {
        //child
        execute_debugee(prog);

    }
    else if (pid >= 1)  {
        //parent
        execute_debugger(prog, pid);
    }
    else {
        std::cerr << "Error forking";
    }
}
<commit_msg>Early line and pc work<commit_after>#include <string>
#include <iostream>
#include <utility>
#include <cstdio>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/user.h>

#include "dwarf/dwarf++.hh"
#include "elf/elf++.hh"

#include "linenoise.h"

class debugger {
public:
    debugger (std::string prog_name, pid_t pid)
        : m_prog_name{std::move(prog_name)}, m_pid{pid} {
            auto fd = open(m_prog_name.c_str(), O_RDONLY);

            m_elf = elf::elf{elf::create_mmap_loader(fd)};
            m_dwarf = dwarf::dwarf{dwarf::elf::create_loader(m_elf)};
        }

    void run();
private:
    void handle_command(const std::string& line);
    uint64_t get_pc();
    std::string get_current_line_entry();

    std::string m_prog_name;
    pid_t m_pid;
    dwarf::dwarf m_dwarf;
    elf::elf m_elf;
};

uint64_t debugger::get_pc() {
  struct user_regs_struct regs;
  std::cout << ptrace(PTRACE_GETREGS, m_pid, NULL, &regs) << std::endl;
  return regs.rip;
}

std::string debugger::get_current_line_entry() {
    auto pc = get_pc();

    for (auto &cu : m_dwarf.compilation_units()) {
        if (die_pc_range(cu.root()).contains(pc)) {
            return "";//at_name(cu.root());
            // Map PC to a line
            auto &lt = cu.get_line_table();
            auto it = lt.find_address(pc);
            if (it == lt.end()) {
                return "";
            }
            else {
                return it->get_description();
            }
        }
    }

    return "";
}

void debugger::run() {
    char* line = nullptr;
    while((line = linenoise("minidbg> ")) != NULL) {
        handle_command(line);
        linenoiseHistoryAdd(line);
        linenoiseFree(line);
    }
}

void debugger::handle_command(const std::string& line) {
    if (line == "cont") {
        ptrace(PTRACE_CONT, m_pid, NULL, NULL);
    }
    else if (line == "line") {
        std::cout << get_current_line_entry() << std::endl;
    }
    else if (line == "pc") {
        std::cout << std::hex << get_pc() << std::endl;
    }
    else {
        std::cerr << "Unknown command\n";
    }
}

void execute_debugger (const std::string& prog_name, pid_t pid) {
    int wait_status;
    wait(&wait_status);

    debugger dbg{prog_name, pid};
    dbg.run();
}

void execute_debugee (const std::string& prog_name) {
  if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
      std::cerr << "Error in ptrace\n";
      return;
  }
  execl(prog_name.c_str(), prog_name.c_str(), NULL);
}

int main(int argc, char* argv[]) {
    auto prog = argv[1];

    auto pid = fork();
    if (pid == 0) {
        //child
        execute_debugee(prog);

    }
    else if (pid >= 1)  {
        //parent
        execute_debugger(prog, pid);
    }
    else {
        std::cerr << "Error forking";
    }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>

#include <pcl/registration/ndt.h>
#include <pcl/filters/approximate_voxel_grid.h>

#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>

int
main (int argc, char** argv)
{
  // Loading first scan of room.
  pcl::PointCloud<pcl::PointXYZ>::Ptr target_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  if (pcl::io::loadPCDFile<pcl::PointXYZ> ("room_scan1.pcd", *target_cloud) == -1)
  {
    PCL_ERROR ("Couldn't read file room_scan1.pcd \n");
    return (-1);
  }
  std::cout << "Loaded " << target_cloud->size () << " data points from room_scan1.pcd" << std::endl;

  // Loading second scan of room from new perspective.
  pcl::PointCloud<pcl::PointXYZ>::Ptr input_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  if (pcl::io::loadPCDFile<pcl::PointXYZ> ("room_scan2.pcd", *input_cloud) == -1)
  {
    PCL_ERROR ("Couldn't read file room_scan2.pcd \n");
    return (-1);
  }
  std::cout << "Loaded " << input_cloud->size () << " data points from room_scan2.pcd" << std::endl;

  // Filtering input scan to roughly 10% of original size to increase speed of registration.
  pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::ApproximateVoxelGrid<pcl::PointXYZ> approximate_voxel_filter;
  approximate_voxel_filter.setLeafSize (0.2, 0.2, 0.2);
  approximate_voxel_filter.setInputCloud (input_cloud);
  approximate_voxel_filter.filter (*filtered_cloud);
  std::cout << "Filtered cloud contains " << filtered_cloud->size ()
            << " data points from room_scan2.pcd" << std::endl;

  // Initializing Normal Distributions Transform (NDT).
  pcl::NormalDistributionsTransform<pcl::PointXYZ, pcl::PointXYZ> ndt;

  // Setting scale dependent NDT parameters
  // Setting minimum transformation difference for termination condition.
  ndt.setTransformationEpsilon (0.01);
  // Setting maximum step size for More-Thuente line search.
  ndt.setStepSize (0.1);
  //Setting Resolution of NDT grid structure (VoxelGridCovariance).
  ndt.setResolution (1.0);

  // Setting max number of registration iterations.
  ndt.setMaximumIterations (35);

  // Setting point cloud to be aligned.
  ndt.setInputCloud (filtered_cloud);
  // Setting point cloud to be aligned to.
  ndt.setInputTarget (target_cloud);

  // Set initial alignment estimate found using robot odometry.
  Eigen::AngleAxisf init_rotation (0.6931, Eigen::Vector3f::UnitZ ());
  Eigen::Translation3f init_translation (1.79387, 0.720047, 0);
  Eigen::Matrix4f init_guess = (init_translation * init_rotation).matrix ();

  // Calculating required rigid transform to align the input cloud to the target cloud.
  pcl::PointCloud<pcl::PointXYZ>::Ptr output_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  ndt.align (*output_cloud, init_guess);

  std::cout << "Normal Distributions Transform has converged:" << ndt.hasConverged ()
            << " score: " << ndt.getFitnessScore () << std::endl;

  // Transforming unfiltered, input cloud using found transform.
  pcl::transformPointCloud (*input_cloud, *output_cloud, ndt.getFinalTransformation ());

  // Saving transformed input cloud.
  pcl::io::savePCDFileASCII ("room_scan2_transformed.pcd", *output_cloud);

  // Initializing point cloud visualizer
  boost::shared_ptr<pcl::visualization::PCLVisualizer>
  viewer_final (new pcl::visualization::PCLVisualizer ("3D Viewer"));
  viewer_final->setBackgroundColor (0, 0, 0);

  // Coloring and visualizing target cloud (red).
  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>
  target_color (target_cloud, 255, 0, 0);
  viewer_final->addPointCloud<pcl::PointXYZ> (target_cloud, target_color, "target cloud");
  viewer_final->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE,
                                                  1, "target cloud");

  // Coloring and visualizing transformed input cloud (green).
  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>
  output_color (output_cloud, 0, 255, 0);
  viewer_final->addPointCloud<pcl::PointXYZ> (output_cloud, output_color, "output cloud");
  viewer_final->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE,
                                                  1, "output cloud");

  // Starting visualizer
  viewer_final->addCoordinateSystem (1.0);
  viewer_final->initCameraParameters ();

  // Wait until visualizer window is closed.
  while (!viewer_final->wasStopped ())
  {
    viewer_final->spinOnce (100);
    boost::this_thread::sleep (boost::posix_time::microseconds (100000));
  }

  return (0);
}
<commit_msg>got rid of a deprecated API warning<commit_after>#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>

#include <pcl/registration/ndt.h>
#include <pcl/filters/approximate_voxel_grid.h>

#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>

int
main (int argc, char** argv)
{
  // Loading first scan of room.
  pcl::PointCloud<pcl::PointXYZ>::Ptr target_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  if (pcl::io::loadPCDFile<pcl::PointXYZ> ("room_scan1.pcd", *target_cloud) == -1)
  {
    PCL_ERROR ("Couldn't read file room_scan1.pcd \n");
    return (-1);
  }
  std::cout << "Loaded " << target_cloud->size () << " data points from room_scan1.pcd" << std::endl;

  // Loading second scan of room from new perspective.
  pcl::PointCloud<pcl::PointXYZ>::Ptr input_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  if (pcl::io::loadPCDFile<pcl::PointXYZ> ("room_scan2.pcd", *input_cloud) == -1)
  {
    PCL_ERROR ("Couldn't read file room_scan2.pcd \n");
    return (-1);
  }
  std::cout << "Loaded " << input_cloud->size () << " data points from room_scan2.pcd" << std::endl;

  // Filtering input scan to roughly 10% of original size to increase speed of registration.
  pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::ApproximateVoxelGrid<pcl::PointXYZ> approximate_voxel_filter;
  approximate_voxel_filter.setLeafSize (0.2, 0.2, 0.2);
  approximate_voxel_filter.setInputCloud (input_cloud);
  approximate_voxel_filter.filter (*filtered_cloud);
  std::cout << "Filtered cloud contains " << filtered_cloud->size ()
            << " data points from room_scan2.pcd" << std::endl;

  // Initializing Normal Distributions Transform (NDT).
  pcl::NormalDistributionsTransform<pcl::PointXYZ, pcl::PointXYZ> ndt;

  // Setting scale dependent NDT parameters
  // Setting minimum transformation difference for termination condition.
  ndt.setTransformationEpsilon (0.01);
  // Setting maximum step size for More-Thuente line search.
  ndt.setStepSize (0.1);
  //Setting Resolution of NDT grid structure (VoxelGridCovariance).
  ndt.setResolution (1.0);

  // Setting max number of registration iterations.
  ndt.setMaximumIterations (35);

  // Setting point cloud to be aligned.
  ndt.setInputSource (filtered_cloud);
  // Setting point cloud to be aligned to.
  ndt.setInputTarget (target_cloud);

  // Set initial alignment estimate found using robot odometry.
  Eigen::AngleAxisf init_rotation (0.6931, Eigen::Vector3f::UnitZ ());
  Eigen::Translation3f init_translation (1.79387, 0.720047, 0);
  Eigen::Matrix4f init_guess = (init_translation * init_rotation).matrix ();

  // Calculating required rigid transform to align the input cloud to the target cloud.
  pcl::PointCloud<pcl::PointXYZ>::Ptr output_cloud (new pcl::PointCloud<pcl::PointXYZ>);
  ndt.align (*output_cloud, init_guess);

  std::cout << "Normal Distributions Transform has converged:" << ndt.hasConverged ()
            << " score: " << ndt.getFitnessScore () << std::endl;

  // Transforming unfiltered, input cloud using found transform.
  pcl::transformPointCloud (*input_cloud, *output_cloud, ndt.getFinalTransformation ());

  // Saving transformed input cloud.
  pcl::io::savePCDFileASCII ("room_scan2_transformed.pcd", *output_cloud);

  // Initializing point cloud visualizer
  boost::shared_ptr<pcl::visualization::PCLVisualizer>
  viewer_final (new pcl::visualization::PCLVisualizer ("3D Viewer"));
  viewer_final->setBackgroundColor (0, 0, 0);

  // Coloring and visualizing target cloud (red).
  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>
  target_color (target_cloud, 255, 0, 0);
  viewer_final->addPointCloud<pcl::PointXYZ> (target_cloud, target_color, "target cloud");
  viewer_final->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE,
                                                  1, "target cloud");

  // Coloring and visualizing transformed input cloud (green).
  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>
  output_color (output_cloud, 0, 255, 0);
  viewer_final->addPointCloud<pcl::PointXYZ> (output_cloud, output_color, "output cloud");
  viewer_final->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE,
                                                  1, "output cloud");

  // Starting visualizer
  viewer_final->addCoordinateSystem (1.0);
  viewer_final->initCameraParameters ();

  // Wait until visualizer window is closed.
  while (!viewer_final->wasStopped ())
  {
    viewer_final->spinOnce (100);
    boost::this_thread::sleep (boost::posix_time::microseconds (100000));
  }

  return (0);
}
<|endoftext|>