<commit_before>/*
** Author(s):
**  - Laurent LEC <llec@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#include <qi/log.hpp>
#include <qimessaging/qt/QiTransportSocket>
#include "src/qitransportsocket_p.h"
#include <QTcpSocket>
#include <QSslSocket>
#include <QHostAddress>
#include <qimessaging/message.hpp>
#include <qimessaging/buffer.hpp>
#include "../src/message_p.hpp"

QiTransportSocketPrivate::QiTransportSocketPrivate(QiTransportSocket* self)
  : _self(self)
  , _device(0)
  , _msg(0)
{
}

QiTransportSocketPrivate::~QiTransportSocketPrivate()
{
  if (_msg)
  {
    delete _msg;
    _msg = 0;
  }

  foreach (qi::Message* msg, _pendingMessages)
  {
    delete msg;
    msg = 0;
  }

  delete _device;
  _device = 0;
}

void QiTransportSocketPrivate::read()
{
  while (true)
  {
    if (_msg == 0)
    {
      _msg = new qi::Message();
      _readHdr = true;
    }

    if (_readHdr)
    {
      if (_device->bytesAvailable()
            >= static_cast<qint64>(sizeof(qi::MessagePrivate::MessageHeader)))
      {
        _device->read(static_cast<char*>(_msg->_p->getHeader()),
                      sizeof(qi::MessagePrivate::MessageHeader));

        if (!_msg->isValid())
        {
          qiLogError("QiTransportSocket") << "incorrect message, dropped";
          // TODO: implement error recovery...
          return;
        }

        _readHdr = false;
      }
      else
      {
        break;
      }
    }

    if (!_readHdr)
    {
      qint64 bufferSize = static_cast<qi::MessagePrivate::MessageHeader*>(_msg->_p->getHeader())->size;

      if (_device->bytesAvailable()
            >= static_cast<qint64>(bufferSize))
      {
        qi::Buffer buffer;
        buffer.reserve(bufferSize);
        _msg->setBuffer(buffer);

        _device->read(static_cast<char*>(buffer.data()), bufferSize);

        _pendingMessages.append(_msg);

        _readHdr = true;
        _msg = 0;

        emit readyRead();
      }
      else
      {
        break;
      }
    }
  }
}

QiTransportSocket::QiTransportSocket(QObject *parent)
  : QObject(parent)
  , _p(new QiTransportSocketPrivate(this))
{
  connect(_p, SIGNAL(readyRead()), this, SIGNAL(readyRead()));
}

QiTransportSocket::~QiTransportSocket()
{
  close();
  delete _p;
}

void QiTransportSocket::close()
{
  if (_p->_device)
  {
    _p->_device->close();
  }
}

void QiTransportSocket::write(const qi::Message& message)
{
  qint64 writtenSize = 0;

  message._p->complete();

  writtenSize = _p->_device->write(static_cast<char*>(message._p->getHeader()),
                                   sizeof(qi::MessagePrivate::MessageHeader));
  if (writtenSize != sizeof(qi::MessagePrivate::MessageHeader))
  {
    qiLogError("QiTransportSocket") << "write error, (" << writtenSize << ")" << _p->_device->errorString().toUtf8().constData();
  }

  writtenSize = _p->_device->write(static_cast<char*>(message._p->buffer.data()),
                                   message._p->buffer.size());
  if (writtenSize != static_cast<qint64>(message._p->buffer.size()))
  {
    qiLogError("QiTransportSocket") << "write error, (" << writtenSize << ")";
  }
}

qi::Message *QiTransportSocket::read()
{
  return _p->_pendingMessages.empty() ? 0 : _p->_pendingMessages.dequeue();
}

void QiTransportSocket::connectToHost(const QUrl& address)
{
  if (address.scheme() == "tcp")
  {
    QTcpSocket* socket = new QTcpSocket(this);
    connect(socket, SIGNAL(connected()), this, SIGNAL(connected()));
    connect(socket, SIGNAL(disconnected()), this, SIGNAL(disconnected()));
    connect(socket, SIGNAL(readyRead()), _p, SLOT(read()));

    QHostAddress host(address.host());
    socket->connectToHost(host, address.port());
    _p->_peer = address;
    _p->_device = socket;
  }
  else if (address.scheme() == "tcps")
  {
    QSslSocket* socket = new QSslSocket(this);
    connect(socket, SIGNAL(encrypted()), this, SIGNAL(connected()));
    connect(socket, SIGNAL(disconnected()), this, SIGNAL(disconnected()));
    connect(socket, SIGNAL(readyRead()), _p, SLOT(read()));

    socket->setProtocol(QSsl::TlsV1SslV3);
    socket->connectToHostEncrypted(address.host(), address.port());
    _p->_peer = address;
    _p->_device = socket;
  }

  qiLogError("QiTransportServer") << "Protocol `"
                                  << address.scheme().toUtf8().constData()
                                  << "' is not supported, can't connect";
}

QUrl QiTransportSocket::peer()
{
  return _p->_peer;
}

QiTransportSocket::SocketState QiTransportSocket::state() const
{
  if (!_p->_device)
  {
    return SocketState_Unconnected;
  }

  /*
   * This function must return a SocketState, which is mirroring the values
   * of QAbstractSocket.
   * If the socket is a QAbstractSocket, we can directly return the state
   * given by the API.
   */
  QAbstractSocket *socket;
  if ((socket = dynamic_cast<QAbstractSocket*>(_p->_device)))
  {
    return static_cast<SocketState>(socket->state());
  }

  /*
   * Just in case...
   */
  return SocketState_Unknown;
}
<commit_msg>Improve log messages<commit_after>/*
** Author(s):
**  - Laurent LEC <llec@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#include <qi/log.hpp>
#include <qimessaging/qt/QiTransportSocket>
#include "src/qitransportsocket_p.h"
#include <QTcpSocket>
#include <QSslSocket>
#include <QHostAddress>
#include <qimessaging/message.hpp>
#include <qimessaging/buffer.hpp>
#include "../src/message_p.hpp"

QiTransportSocketPrivate::QiTransportSocketPrivate(QiTransportSocket* self)
  : _self(self)
  , _device(0)
  , _msg(0)
{
}

QiTransportSocketPrivate::~QiTransportSocketPrivate()
{
  if (_msg)
  {
    delete _msg;
    _msg = 0;
  }

  foreach (qi::Message* msg, _pendingMessages)
  {
    delete msg;
    msg = 0;
  }

  delete _device;
  _device = 0;
}

void QiTransportSocketPrivate::read()
{
  while (true)
  {
    if (_msg == 0)
    {
      _msg = new qi::Message();
      _readHdr = true;
    }

    if (_readHdr)
    {
      if (_device->bytesAvailable()
            >= static_cast<qint64>(sizeof(qi::MessagePrivate::MessageHeader)))
      {
        _device->read(static_cast<char*>(_msg->_p->getHeader()),
                      sizeof(qi::MessagePrivate::MessageHeader));

        if (!_msg->isValid())
        {
          qiLogError("QiTransportSocket") << "incorrect message, dropped";
          // TODO: implement error recovery...
          return;
        }

        _readHdr = false;
      }
      else
      {
        break;
      }
    }

    if (!_readHdr)
    {
      qint64 bufferSize = static_cast<qi::MessagePrivate::MessageHeader*>(_msg->_p->getHeader())->size;

      if (_device->bytesAvailable()
            >= static_cast<qint64>(bufferSize))
      {
        qi::Buffer buffer;
        buffer.reserve(bufferSize);
        _msg->setBuffer(buffer);

        _device->read(static_cast<char*>(buffer.data()), bufferSize);

        _pendingMessages.append(_msg);

        _readHdr = true;
        _msg = 0;

        emit readyRead();
      }
      else
      {
        break;
      }
    }
  }
}

QiTransportSocket::QiTransportSocket(QObject *parent)
  : QObject(parent)
  , _p(new QiTransportSocketPrivate(this))
{
  connect(_p, SIGNAL(readyRead()), this, SIGNAL(readyRead()));
}

QiTransportSocket::~QiTransportSocket()
{
  close();
  delete _p;
}

void QiTransportSocket::close()
{
  if (_p->_device)
  {
    _p->_device->close();
  }
}

void QiTransportSocket::write(const qi::Message& message)
{
  qint64 writtenSize = 0;

  message._p->complete();

  writtenSize = _p->_device->write(static_cast<char*>(message._p->getHeader()),
                                   sizeof(qi::MessagePrivate::MessageHeader));
  if (writtenSize != sizeof(qi::MessagePrivate::MessageHeader))
  {
    qiLogError("QiTransportSocket") << "write error, (" << writtenSize << ")" << _p->_device->errorString().toUtf8().constData();
  }

  writtenSize = _p->_device->write(static_cast<char*>(message._p->buffer.data()),
                                   message._p->buffer.size());
  if (writtenSize != static_cast<qint64>(message._p->buffer.size()))
  {
    qiLogError("QiTransportSocket") << "write error, (" << writtenSize << ")";
  }
}

qi::Message *QiTransportSocket::read()
{
  return _p->_pendingMessages.empty() ? 0 : _p->_pendingMessages.dequeue();
}

void QiTransportSocket::connectToHost(const QUrl& address)
{
  qiLogDebug("QiTransportSocket") << "Connecting to " << address.toString().toUtf8().constData();

  if (address.scheme() == "tcp")
  {
    QTcpSocket* socket = new QTcpSocket(this);
    connect(socket, SIGNAL(connected()), this, SIGNAL(connected()));
    connect(socket, SIGNAL(disconnected()), this, SIGNAL(disconnected()));
    connect(socket, SIGNAL(readyRead()), _p, SLOT(read()));

    QHostAddress host(address.host());
    socket->connectToHost(host, address.port());
    _p->_peer = address;
    _p->_device = socket;
  }
  else if (address.scheme() == "tcps")
  {
    QSslSocket* socket = new QSslSocket(this);
    connect(socket, SIGNAL(encrypted()), this, SIGNAL(connected()));
    connect(socket, SIGNAL(disconnected()), this, SIGNAL(disconnected()));
    connect(socket, SIGNAL(readyRead()), _p, SLOT(read()));

    socket->setProtocol(QSsl::TlsV1SslV3);
    socket->connectToHostEncrypted(address.host(), address.port());
    _p->_peer = address;
    _p->_device = socket;
  }
  else
  {
    qiLogError("QiTransportServer") << "Protocol `"
                                    << address.scheme().toUtf8().constData()
                                    << "' is not supported, can't connect";
  }
}

QUrl QiTransportSocket::peer()
{
  return _p->_peer;
}

QiTransportSocket::SocketState QiTransportSocket::state() const
{
  if (!_p->_device)
  {
    return SocketState_Unconnected;
  }

  /*
   * This function must return a SocketState, which is mirroring the values
   * of QAbstractSocket.
   * If the socket is a QAbstractSocket, we can directly return the state
   * given by the API.
   */
  QAbstractSocket *socket;
  if ((socket = dynamic_cast<QAbstractSocket*>(_p->_device)))
  {
    return static_cast<SocketState>(socket->state());
  }

  /*
   * Just in case...
   */
  return SocketState_Unknown;
}
<|endoftext|>


<commit_before>/*
 ESP8266WiFiSTA.cpp - WiFi library for esp8266

 Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
 This file is part of the esp8266 core for Arduino environment.

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library 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
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

 Reworked on 28 Dec 2015 by Markus Sattler

 */

#include "ESP8266WiFi.h"
#include "ESP8266WiFiGeneric.h"
#include "ESP8266WiFiAP.h"

extern "C" {
#include "c_types.h"
#include "ets_sys.h"
#include "os_type.h"
#include "osapi.h"
#include "mem.h"
#include "user_interface.h"
}

#include "debug.h"

// -----------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------- Private functions ------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------

static bool softap_config_equal(const softap_config& lhs, const softap_config& rhs);

/**
 * compare two AP configurations
 * @param lhs softap_config
 * @param rhs softap_config
 * @return equal
 */
static bool softap_config_equal(const softap_config& lhs, const softap_config& rhs) {
    if(strcmp(reinterpret_cast<const char*>(lhs.ssid), reinterpret_cast<const char*>(rhs.ssid)) != 0) {
        return false;
    }
    if(strcmp(reinterpret_cast<const char*>(lhs.password), reinterpret_cast<const char*>(rhs.password)) != 0) {
        return false;
    }
    if(lhs.channel != rhs.channel) {
        return false;
    }
    if(lhs.ssid_hidden != rhs.ssid_hidden) {
        return false;
    }
    return true;
}

// -----------------------------------------------------------------------------------------------------------------------
// ----------------------------------------------------- AP function -----------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------

/**
 * Set up an access point
 * @param ssid          Pointer to the SSID (max 63 char).
 * @param passphrase    (for WPA2 min 8 char, for open use NULL)
 * @param channel       WiFi channel number, 1 - 13.
 * @param ssid_hidden   Network cloaking (0 = broadcast SSID, 1 = hide SSID)
 */
bool ESP8266WiFiAPClass::softAP(const char* ssid, const char* passphrase, int channel, int ssid_hidden) {

    if(!WiFi.enableAP(true)) {
        // enable AP failed
        DEBUG_WIFI("[AP] enableAP failed!\n");
        return false;
    }

    if(!ssid || *ssid == 0 || strlen(ssid) > 31) {
        // fail SSID too long or missing!
        DEBUG_WIFI("[AP] SSID too long or missing!\n");
        return false;
    }

    if(passphrase && (strlen(passphrase) > 63 || strlen(passphrase) < 8)) {
        // fail passphrase to long or short!
        DEBUG_WIFI("[AP] fail passphrase to long or short!\n");
        return false;
    }

    bool ret = false;

    struct softap_config conf;
    strcpy(reinterpret_cast<char*>(conf.ssid), ssid);
    conf.channel = channel;
    conf.ssid_len = strlen(ssid);
    conf.ssid_hidden = ssid_hidden;
    conf.max_connection = 4;
    conf.beacon_interval = 100;

    if(!passphrase || strlen(passphrase) == 0) {
        conf.authmode = AUTH_OPEN;
        *conf.password = 0;
    } else {
        conf.authmode = AUTH_WPA2_PSK;
        strcpy(reinterpret_cast<char*>(conf.password), passphrase);
    }

    struct softap_config conf_current;
    wifi_softap_get_config(&conf_current);
    if(!softap_config_equal(conf, conf_current)) {

        ETS_UART_INTR_DISABLE();
        if(WiFi._persistent) {
            ret = wifi_softap_set_config(&conf);
        } else {
            ret = wifi_softap_set_config_current(&conf);
        }
        ETS_UART_INTR_ENABLE();

        if(!ret) {
            DEBUG_WIFI("[AP] set_config failed!\n");
            return false;
        }

    } else {
        DEBUG_WIFI("[AP] softap config unchanged\n");
    }

    if(wifi_softap_dhcps_status() != DHCP_STARTED) {
        DEBUG_WIFI("[AP] DHCP not started, starting...\n");
        if(!wifi_softap_dhcps_start()) {
            DEBUG_WIFI("[AP] wifi_softap_dhcps_start failed!\n");
            ret = false;
        }
    }

    // check IP config
    struct ip_info ip;
    if(wifi_get_ip_info(SOFTAP_IF, &ip)) {
        if(ip.ip.addr == 0x00000000) {
            // Invalid config
            DEBUG_WIFI("[AP] IP config Invalid resetting...\n");
            //192.168.244.1 , 192.168.244.1 , 255.255.255.0
            ret = softAPConfig(0x01F4A8C0, 0x01F4A8C0, 0x00FFFFFF);
            if(!ret) {
                DEBUG_WIFI("[AP] softAPConfig failed!\n");
                ret = false;
            }
        }
    } else {
        DEBUG_WIFI("[AP] wifi_get_ip_info failed!\n");
        ret = false;
    }

    return ret;
}

/**
 * Configure access point
 * @param local_ip      access point IP
 * @param gateway       gateway IP
 * @param subnet        subnet mask
 */
bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet) {
    DEBUG_WIFI("[APConfig] local_ip: %s gateway: %s subnet: %s\n", local_ip.toString().c_str(), gateway.toString().c_str(), subnet.toString().c_str());
    if(!WiFi.enableAP(true)) {
        // enable AP failed
        DEBUG_WIFI("[APConfig] enableAP failed!\n");
        return false;
    }
    bool ret = true;

    struct ip_info info;
    info.ip.addr = static_cast<uint32_t>(local_ip);
    info.gw.addr = static_cast<uint32_t>(gateway);
    info.netmask.addr = static_cast<uint32_t>(subnet);

    if(!wifi_softap_dhcps_stop()) {
        DEBUG_WIFI("[APConfig] wifi_softap_dhcps_stop failed!\n");
    }

    if(!wifi_set_ip_info(SOFTAP_IF, &info)) {
        DEBUG_WIFI("[APConfig] wifi_set_ip_info failed!\n");
        ret = false;
    }

    struct dhcps_lease dhcp_lease;
    IPAddress ip = local_ip;
    ip[3] += 99;
    dhcp_lease.start_ip.addr = static_cast<uint32_t>(ip);
    DEBUG_WIFI("[APConfig] DHCP IP start: %s\n", ip.toString().c_str());

    ip[3] += 100;
    dhcp_lease.end_ip.addr = static_cast<uint32_t>(ip);
    DEBUG_WIFI("[APConfig] DHCP IP end: %s\n", ip.toString().c_str());

    if(!wifi_softap_set_dhcps_lease(&dhcp_lease)) {
        DEBUG_WIFI("[APConfig] wifi_set_ip_info failed!\n");
        ret = false;
    }

    // set lease time to 720min --> 12h
    if(!wifi_softap_set_dhcps_lease_time(720)) {
        DEBUG_WIFI("[APConfig] wifi_softap_set_dhcps_lease_time failed!\n");
        ret = false;
    }

    uint8 mode = 1;
    if(!wifi_softap_set_dhcps_offer_option(OFFER_ROUTER, &mode)) {
        DEBUG_WIFI("[APConfig] wifi_softap_set_dhcps_offer_option failed!\n");
        ret = false;
    }

    if(!wifi_softap_dhcps_start()) {
        DEBUG_WIFI("[APConfig] wifi_softap_dhcps_start failed!\n");
        ret = false;
    }

    // check config
    if(wifi_get_ip_info(SOFTAP_IF, &info)) {
        if(info.ip.addr == 0x00000000) {
            DEBUG_WIFI("[APConfig] IP config Invalid?!\n");
            ret = false;
        } else if(local_ip != info.ip.addr) {
            ip = info.ip.addr;
            DEBUG_WIFI("[APConfig] IP config not set correct?! new IP: %s\n", ip.toString().c_str());
            ret = false;
        }
    } else {
        DEBUG_WIFI("[APConfig] wifi_get_ip_info failed!\n");
        ret = false;
    }

    return ret;
}

/**
 * Disconnect from the network (close AP)
 * @param wifioff disable mode?
 * @return one value of wl_status_t enum
 */
bool ESP8266WiFiAPClass::softAPdisconnect(bool wifioff) {
    bool ret;
    struct softap_config conf;
    *conf.ssid = 0;
    *conf.password = 0;
    ETS_UART_INTR_DISABLE();
    if(WiFi._persistent) {
        ret = wifi_softap_set_config(&conf);
    } else {
        ret = wifi_softap_set_config_current(&conf);
    }
    ETS_UART_INTR_ENABLE();

    if(!ret) {
        DEBUG_WIFI("[APdisconnect] set_config failed!\n");
    }

    if(wifioff) {
        ret = WiFi.enableAP(false);
    }

    return ret;
}

/**
 * Get the count of the Station / client that are connected to the softAP interface
 * @return Stations count
 */
uint8_t ESP8266WiFiAPClass::softAPgetStationNum() {
    return wifi_softap_get_station_num();
}

/**
 * Get the softAP interface IP address.
 * @return IPAddress softAP IP
 */
IPAddress ESP8266WiFiAPClass::softAPIP() {
    struct ip_info ip;
    wifi_get_ip_info(SOFTAP_IF, &ip);
    return IPAddress(ip.ip.addr);
}

/**
 * Get the softAP interface MAC address.
 * @param mac   pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
 * @return      pointer to uint8_t*
 */
uint8_t* ESP8266WiFiAPClass::softAPmacAddress(uint8_t* mac) {
    wifi_get_macaddr(SOFTAP_IF, mac);
    return mac;
}

/**
 * Get the softAP interface MAC address.
 * @return String mac
 */
String ESP8266WiFiAPClass::softAPmacAddress(void) {
    uint8_t mac[6];
    char macStr[18] = { 0 };
    wifi_get_macaddr(SOFTAP_IF, mac);

    sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    return String(macStr);
}
<commit_msg>correct default return value for softAP<commit_after>/*
 ESP8266WiFiSTA.cpp - WiFi library for esp8266

 Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
 This file is part of the esp8266 core for Arduino environment.

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library 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
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

 Reworked on 28 Dec 2015 by Markus Sattler

 */

#include "ESP8266WiFi.h"
#include "ESP8266WiFiGeneric.h"
#include "ESP8266WiFiAP.h"

extern "C" {
#include "c_types.h"
#include "ets_sys.h"
#include "os_type.h"
#include "osapi.h"
#include "mem.h"
#include "user_interface.h"
}

#include "debug.h"

// -----------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------- Private functions ------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------

static bool softap_config_equal(const softap_config& lhs, const softap_config& rhs);

/**
 * compare two AP configurations
 * @param lhs softap_config
 * @param rhs softap_config
 * @return equal
 */
static bool softap_config_equal(const softap_config& lhs, const softap_config& rhs) {
    if(strcmp(reinterpret_cast<const char*>(lhs.ssid), reinterpret_cast<const char*>(rhs.ssid)) != 0) {
        return false;
    }
    if(strcmp(reinterpret_cast<const char*>(lhs.password), reinterpret_cast<const char*>(rhs.password)) != 0) {
        return false;
    }
    if(lhs.channel != rhs.channel) {
        return false;
    }
    if(lhs.ssid_hidden != rhs.ssid_hidden) {
        return false;
    }
    return true;
}

// -----------------------------------------------------------------------------------------------------------------------
// ----------------------------------------------------- AP function -----------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------

/**
 * Set up an access point
 * @param ssid          Pointer to the SSID (max 63 char).
 * @param passphrase    (for WPA2 min 8 char, for open use NULL)
 * @param channel       WiFi channel number, 1 - 13.
 * @param ssid_hidden   Network cloaking (0 = broadcast SSID, 1 = hide SSID)
 */
bool ESP8266WiFiAPClass::softAP(const char* ssid, const char* passphrase, int channel, int ssid_hidden) {

    if(!WiFi.enableAP(true)) {
        // enable AP failed
        DEBUG_WIFI("[AP] enableAP failed!\n");
        return false;
    }

    if(!ssid || *ssid == 0 || strlen(ssid) > 31) {
        // fail SSID too long or missing!
        DEBUG_WIFI("[AP] SSID too long or missing!\n");
        return false;
    }

    if(passphrase && (strlen(passphrase) > 63 || strlen(passphrase) < 8)) {
        // fail passphrase to long or short!
        DEBUG_WIFI("[AP] fail passphrase to long or short!\n");
        return false;
    }

    bool ret = true;

    struct softap_config conf;
    strcpy(reinterpret_cast<char*>(conf.ssid), ssid);
    conf.channel = channel;
    conf.ssid_len = strlen(ssid);
    conf.ssid_hidden = ssid_hidden;
    conf.max_connection = 4;
    conf.beacon_interval = 100;

    if(!passphrase || strlen(passphrase) == 0) {
        conf.authmode = AUTH_OPEN;
        *conf.password = 0;
    } else {
        conf.authmode = AUTH_WPA2_PSK;
        strcpy(reinterpret_cast<char*>(conf.password), passphrase);
    }

    struct softap_config conf_current;
    wifi_softap_get_config(&conf_current);
    if(!softap_config_equal(conf, conf_current)) {

        ETS_UART_INTR_DISABLE();
        if(WiFi._persistent) {
            ret = wifi_softap_set_config(&conf);
        } else {
            ret = wifi_softap_set_config_current(&conf);
        }
        ETS_UART_INTR_ENABLE();

        if(!ret) {
            DEBUG_WIFI("[AP] set_config failed!\n");
            return false;
        }

    } else {
        DEBUG_WIFI("[AP] softap config unchanged\n");
    }

    if(wifi_softap_dhcps_status() != DHCP_STARTED) {
        DEBUG_WIFI("[AP] DHCP not started, starting...\n");
        if(!wifi_softap_dhcps_start()) {
            DEBUG_WIFI("[AP] wifi_softap_dhcps_start failed!\n");
            ret = false;
        }
    }

    // check IP config
    struct ip_info ip;
    if(wifi_get_ip_info(SOFTAP_IF, &ip)) {
        if(ip.ip.addr == 0x00000000) {
            // Invalid config
            DEBUG_WIFI("[AP] IP config Invalid resetting...\n");
            //192.168.244.1 , 192.168.244.1 , 255.255.255.0
            ret = softAPConfig(0x01F4A8C0, 0x01F4A8C0, 0x00FFFFFF);
            if(!ret) {
                DEBUG_WIFI("[AP] softAPConfig failed!\n");
                ret = false;
            }
        }
    } else {
        DEBUG_WIFI("[AP] wifi_get_ip_info failed!\n");
        ret = false;
    }

    return ret;
}

/**
 * Configure access point
 * @param local_ip      access point IP
 * @param gateway       gateway IP
 * @param subnet        subnet mask
 */
bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet) {
    DEBUG_WIFI("[APConfig] local_ip: %s gateway: %s subnet: %s\n", local_ip.toString().c_str(), gateway.toString().c_str(), subnet.toString().c_str());
    if(!WiFi.enableAP(true)) {
        // enable AP failed
        DEBUG_WIFI("[APConfig] enableAP failed!\n");
        return false;
    }
    bool ret = true;

    struct ip_info info;
    info.ip.addr = static_cast<uint32_t>(local_ip);
    info.gw.addr = static_cast<uint32_t>(gateway);
    info.netmask.addr = static_cast<uint32_t>(subnet);

    if(!wifi_softap_dhcps_stop()) {
        DEBUG_WIFI("[APConfig] wifi_softap_dhcps_stop failed!\n");
    }

    if(!wifi_set_ip_info(SOFTAP_IF, &info)) {
        DEBUG_WIFI("[APConfig] wifi_set_ip_info failed!\n");
        ret = false;
    }

    struct dhcps_lease dhcp_lease;
    IPAddress ip = local_ip;
    ip[3] += 99;
    dhcp_lease.start_ip.addr = static_cast<uint32_t>(ip);
    DEBUG_WIFI("[APConfig] DHCP IP start: %s\n", ip.toString().c_str());

    ip[3] += 100;
    dhcp_lease.end_ip.addr = static_cast<uint32_t>(ip);
    DEBUG_WIFI("[APConfig] DHCP IP end: %s\n", ip.toString().c_str());

    if(!wifi_softap_set_dhcps_lease(&dhcp_lease)) {
        DEBUG_WIFI("[APConfig] wifi_set_ip_info failed!\n");
        ret = false;
    }

    // set lease time to 720min --> 12h
    if(!wifi_softap_set_dhcps_lease_time(720)) {
        DEBUG_WIFI("[APConfig] wifi_softap_set_dhcps_lease_time failed!\n");
        ret = false;
    }

    uint8 mode = 1;
    if(!wifi_softap_set_dhcps_offer_option(OFFER_ROUTER, &mode)) {
        DEBUG_WIFI("[APConfig] wifi_softap_set_dhcps_offer_option failed!\n");
        ret = false;
    }

    if(!wifi_softap_dhcps_start()) {
        DEBUG_WIFI("[APConfig] wifi_softap_dhcps_start failed!\n");
        ret = false;
    }

    // check config
    if(wifi_get_ip_info(SOFTAP_IF, &info)) {
        if(info.ip.addr == 0x00000000) {
            DEBUG_WIFI("[APConfig] IP config Invalid?!\n");
            ret = false;
        } else if(local_ip != info.ip.addr) {
            ip = info.ip.addr;
            DEBUG_WIFI("[APConfig] IP config not set correct?! new IP: %s\n", ip.toString().c_str());
            ret = false;
        }
    } else {
        DEBUG_WIFI("[APConfig] wifi_get_ip_info failed!\n");
        ret = false;
    }

    return ret;
}

/**
 * Disconnect from the network (close AP)
 * @param wifioff disable mode?
 * @return one value of wl_status_t enum
 */
bool ESP8266WiFiAPClass::softAPdisconnect(bool wifioff) {
    bool ret;
    struct softap_config conf;
    *conf.ssid = 0;
    *conf.password = 0;
    ETS_UART_INTR_DISABLE();
    if(WiFi._persistent) {
        ret = wifi_softap_set_config(&conf);
    } else {
        ret = wifi_softap_set_config_current(&conf);
    }
    ETS_UART_INTR_ENABLE();

    if(!ret) {
        DEBUG_WIFI("[APdisconnect] set_config failed!\n");
    }

    if(wifioff) {
        ret = WiFi.enableAP(false);
    }

    return ret;
}

/**
 * Get the count of the Station / client that are connected to the softAP interface
 * @return Stations count
 */
uint8_t ESP8266WiFiAPClass::softAPgetStationNum() {
    return wifi_softap_get_station_num();
}

/**
 * Get the softAP interface IP address.
 * @return IPAddress softAP IP
 */
IPAddress ESP8266WiFiAPClass::softAPIP() {
    struct ip_info ip;
    wifi_get_ip_info(SOFTAP_IF, &ip);
    return IPAddress(ip.ip.addr);
}

/**
 * Get the softAP interface MAC address.
 * @param mac   pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
 * @return      pointer to uint8_t*
 */
uint8_t* ESP8266WiFiAPClass::softAPmacAddress(uint8_t* mac) {
    wifi_get_macaddr(SOFTAP_IF, mac);
    return mac;
}

/**
 * Get the softAP interface MAC address.
 * @return String mac
 */
String ESP8266WiFiAPClass::softAPmacAddress(void) {
    uint8_t mac[6];
    char macStr[18] = { 0 };
    wifi_get_macaddr(SOFTAP_IF, mac);

    sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    return String(macStr);
}
<|endoftext|>


<commit_before>/* +---------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)               |
   |                          http://www.mrpt.org/                             |
   |                                                                           |
   | Copyright (c) 2005-2016, Individual contributors, see AUTHORS file        |
   | See: http://www.mrpt.org/Authors - All rights reserved.                   |
   | Released under BSD License. See details in http://www.mrpt.org/License    |
   +---------------------------------------------------------------------------+ */

#include "kinematics-precomp.h"  // Precompiled header
#include <mrpt/kinematics/CVehicleVelCmd_Holo.h>
#include <mrpt/utils/CStream.h>

using namespace mrpt::kinematics;
using namespace mrpt::utils;

IMPLEMENTS_SERIALIZABLE(CVehicleVelCmd_Holo, CVehicleVelCmd, mrpt::kinematics)

CVehicleVelCmd_Holo::CVehicleVelCmd_Holo() :
	vel(.0),
	dir_local(.0),
	ramp_time(.0),
	rot_speed(.0)
{
}
CVehicleVelCmd_Holo::~CVehicleVelCmd_Holo()
{
}

size_t CVehicleVelCmd_Holo::getVelCmdLength() const
{
	return 4;
}

std::string CVehicleVelCmd_Holo::getVelCmdDescription(const int index) const
{
	switch (index)
	{
	case 0: return "vel"; break;
	case 1: return "dir_local"; break;
	case 2: return "ramp_time"; break;
	case 3: return "rot_speed"; break;
	default:
		THROW_EXCEPTION_CUSTOM_MSG1("index out of bounds: %i",index);
	};
}

double CVehicleVelCmd_Holo::getVelCmdElement(const int index) const
{
	switch (index)
	{
	case 0: return vel; break;
	case 1: return dir_local; break;
	case 2: return ramp_time; break;
	case 3: return rot_speed; break;
	default:
		THROW_EXCEPTION_CUSTOM_MSG1("index out of bounds: %i", index);
	};
}

void CVehicleVelCmd_Holo::setVelCmdElement(const int index, const double val)
{
	switch (index)
	{
	case 0: vel=val; break;
	case 1: dir_local = val; break;
	case 2: ramp_time=val; break;
	case 3: rot_speed=val; break;
	default:
		THROW_EXCEPTION_CUSTOM_MSG1("index out of bounds: %i", index);
	};
}

bool CVehicleVelCmd_Holo::isStopCmd() const
{
	return vel == 0 && rot_speed == 0;
}

void CVehicleVelCmd_Holo::setToStop()
{
	vel = dir_local = ramp_time = rot_speed = .0;
}
void CVehicleVelCmd_Holo::readFromStream(mrpt::utils::CStream &in, int version)
{
	switch (version)
	{
	case 0:
		in >> vel >> dir_local >> ramp_time >> rot_speed;
		break;
	default:
		MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(version)
	};
}

void CVehicleVelCmd_Holo::writeToStream(mrpt::utils::CStream &out, int *version) const
{
	if (version)
	{
		*version = 0;
		return;
	}
	out << vel << dir_local << ramp_time << rot_speed;
}

void CVehicleVelCmd_Holo::cmdVel_scale(double vel_scale)
{
	vel *= vel_scale; // |(vx,vy)|
	rot_speed *= vel_scale; // rot_speed
	// ramp_time: leave unchanged
}

void CVehicleVelCmd_Holo::cmdVel_limits(const mrpt::kinematics::CVehicleVelCmd &prev_vel_cmd, const double beta, const TVelCmdParams &params)
{
	ASSERTMSG_(params.robotMax_V_mps >= .0, "[CVehicleVelCmd_Holo] `robotMax_V_mps` must be set to valid values: either assign values programatically or call loadConfigFile()");
	const mrpt::kinematics::CVehicleVelCmd_Holo *prevcmd = dynamic_cast<const mrpt::kinematics::CVehicleVelCmd_Holo*>(&prev_vel_cmd);
	ASSERTMSG_(prevcmd, "Expected prevcmd of type `CVehicleVelCmd_Holo`");

	double f = 1.0;
	if (vel>params.robotMax_V_mps) f = params.robotMax_V_mps / vel;

	vel *= f; // |(vx,vy)|
	rot_speed *= f; // rot_speed
	// ramp_time: leave unchanged
	// Blending with "beta" not required, since the ramp_time already blends cmds for holo robots.
}

<commit_msg>[CVehicleVelCmd_Holo::cmdVel_limits] Remove unnecessary cast and assertion<commit_after>/* +---------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)               |
   |                          http://www.mrpt.org/                             |
   |                                                                           |
   | Copyright (c) 2005-2016, Individual contributors, see AUTHORS file        |
   | See: http://www.mrpt.org/Authors - All rights reserved.                   |
   | Released under BSD License. See details in http://www.mrpt.org/License    |
   +---------------------------------------------------------------------------+ */

#include "kinematics-precomp.h"  // Precompiled header
#include <mrpt/kinematics/CVehicleVelCmd_Holo.h>
#include <mrpt/utils/CStream.h>

using namespace mrpt::kinematics;
using namespace mrpt::utils;

IMPLEMENTS_SERIALIZABLE(CVehicleVelCmd_Holo, CVehicleVelCmd, mrpt::kinematics)

CVehicleVelCmd_Holo::CVehicleVelCmd_Holo() :
	vel(.0),
	dir_local(.0),
	ramp_time(.0),
	rot_speed(.0)
{
}
CVehicleVelCmd_Holo::~CVehicleVelCmd_Holo()
{
}

size_t CVehicleVelCmd_Holo::getVelCmdLength() const
{
	return 4;
}

std::string CVehicleVelCmd_Holo::getVelCmdDescription(const int index) const
{
	switch (index)
	{
	case 0: return "vel"; break;
	case 1: return "dir_local"; break;
	case 2: return "ramp_time"; break;
	case 3: return "rot_speed"; break;
	default:
		THROW_EXCEPTION_CUSTOM_MSG1("index out of bounds: %i",index);
	};
}

double CVehicleVelCmd_Holo::getVelCmdElement(const int index) const
{
	switch (index)
	{
	case 0: return vel; break;
	case 1: return dir_local; break;
	case 2: return ramp_time; break;
	case 3: return rot_speed; break;
	default:
		THROW_EXCEPTION_CUSTOM_MSG1("index out of bounds: %i", index);
	};
}

void CVehicleVelCmd_Holo::setVelCmdElement(const int index, const double val)
{
	switch (index)
	{
	case 0: vel=val; break;
	case 1: dir_local = val; break;
	case 2: ramp_time=val; break;
	case 3: rot_speed=val; break;
	default:
		THROW_EXCEPTION_CUSTOM_MSG1("index out of bounds: %i", index);
	};
}

bool CVehicleVelCmd_Holo::isStopCmd() const
{
	return vel == 0 && rot_speed == 0;
}

void CVehicleVelCmd_Holo::setToStop()
{
	vel = dir_local = ramp_time = rot_speed = .0;
}
void CVehicleVelCmd_Holo::readFromStream(mrpt::utils::CStream &in, int version)
{
	switch (version)
	{
	case 0:
		in >> vel >> dir_local >> ramp_time >> rot_speed;
		break;
	default:
		MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(version)
	};
}

void CVehicleVelCmd_Holo::writeToStream(mrpt::utils::CStream &out, int *version) const
{
	if (version)
	{
		*version = 0;
		return;
	}
	out << vel << dir_local << ramp_time << rot_speed;
}

void CVehicleVelCmd_Holo::cmdVel_scale(double vel_scale)
{
	vel *= vel_scale; // |(vx,vy)|
	rot_speed *= vel_scale; // rot_speed
	// ramp_time: leave unchanged
}

void CVehicleVelCmd_Holo::cmdVel_limits(const mrpt::kinematics::CVehicleVelCmd &prev_vel_cmd, const double beta, const TVelCmdParams &params)
{
	ASSERTMSG_(params.robotMax_V_mps >= .0, "[CVehicleVelCmd_Holo] `robotMax_V_mps` must be set to valid values: either assign values programatically or call loadConfigFile()");

	double f = 1.0;
	if (vel>params.robotMax_V_mps) f = params.robotMax_V_mps / vel;

	vel *= f; // |(vx,vy)|
	rot_speed *= f; // rot_speed
	// ramp_time: leave unchanged
	// Blending with "beta" not required, since the ramp_time already blends cmds for holo robots.
}

<|endoftext|>


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

#include "net/tools/quic/test_tools/http_message_test_utils.h"

#include <vector>

#include "base/basictypes.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"

using base::StringPiece;
using std::string;
using std::vector;

namespace net {
namespace tools {
namespace test {

namespace {

//const char* kContentEncoding = "content-encoding";
const char* kContentLength = "content-length";
const char* kTransferCoding = "transfer-encoding";

// Both kHTTPVersionString and kMethodString arrays are constructed to match
// the enum values defined in Version and Method of HTTPMessage.
const char* kHTTPVersionString[] = {
  "",
  "HTTP/0.9",
  "HTTP/1.0",
  "HTTP/1.1"
};

const char* kMethodString[] = {
  "",
  "OPTIONS",
  "GET",
  "HEAD",
  "POST",
  "PUT",
  "DELETE",
  "TRACE",
  "CONNECT",
  "MKCOL",
  "UNLOCK",
};

// Returns true if the message represents a complete request or response.
// Messages are considered complete if:
// - Transfer-Encoding: chunked is present and message has a final chunk.
// - Content-Length header is present and matches the message body length.
// - Neither Transfer-Encoding nor Content-Length is present and message
//   is tagged as complete.
bool IsCompleteMessage(const HTTPMessage& message) {
  return true;
  const BalsaHeaders* headers = message.headers();
  StringPiece content_length = headers->GetHeader(kContentLength);
  if (!content_length.empty()) {
    int parsed_content_length;
    if (!base::StringToInt(content_length, &parsed_content_length)) {
      return false;
    }
    return (message.body().size() == (uint)parsed_content_length);
  } else {
    // Assume messages without transfer coding or content-length are
    // tagged correctly.
    return message.has_complete_message();
  }
}

}  // namespace

HTTPMessage::Method HTTPMessage::StringToMethod(StringPiece str) {
  // Skip the first element of the array since it is empty string.
  for (unsigned long i = 1; i < arraysize(kMethodString); ++i) {
    if (strncmp(str.data(), kMethodString[i], str.length()) == 0) {
      return static_cast<HTTPMessage::Method>(i);
    }
  }
  return HttpConstants::UNKNOWN_METHOD;
}

HTTPMessage::Version HTTPMessage::StringToVersion(StringPiece str) {
  // Skip the first element of the array since it is empty string.
  for (unsigned long i = 1; i < arraysize(kHTTPVersionString); ++i) {
    if (strncmp(str.data(), kHTTPVersionString[i], str.length()) == 0) {
      return static_cast<HTTPMessage::Version>(i);
    }
  }
  return HttpConstants::HTTP_UNKNOWN;
}

const char* HTTPMessage::MethodToString(Method method) {
  CHECK_LT(static_cast<size_t>(method), arraysize(kMethodString));
  return kMethodString[method];
}

const char* HTTPMessage::VersionToString(Version version) {
  CHECK_LT(static_cast<size_t>(version), arraysize(kHTTPVersionString));
  return kHTTPVersionString[version];
}

HTTPMessage::HTTPMessage()
    : is_request_(true) {
  InitializeFields();
}

HTTPMessage::HTTPMessage(Version ver, Method request, const string& path)
    : is_request_(true) {
  InitializeFields();
  if (ver != HttpConstants::HTTP_0_9) {
    headers()->SetRequestVersion(VersionToString(ver));
  }
  headers()->SetRequestMethod(MethodToString(request));
  headers()->SetRequestUri(path);
}

HTTPMessage::~HTTPMessage() {
}

void HTTPMessage::InitializeFields() {
  has_complete_message_ = true;
  skip_message_validation_ = false;
}

void HTTPMessage::AddHeader(const string& header, const string& value) {
  headers()->AppendHeader(header, value);
}

void HTTPMessage::RemoveHeader(const string& header) {
  headers()->RemoveAllOfHeader(header);
}

void HTTPMessage::ReplaceHeader(const string& header, const string& value) {
  headers()->ReplaceOrAppendHeader(header, value);
}

void HTTPMessage::AddBody(const string& body, bool add_content_length) {
  body_ = body;
  // Remove any transfer-encoding that was left by a previous body.
  RemoveHeader(kTransferCoding);
  if (add_content_length) {
    ReplaceHeader(kContentLength, base::IntToString(body.size()));
  } else {
    RemoveHeader(kContentLength);
  }
}

void HTTPMessage::ValidateMessage() const {
  if (skip_message_validation_) {
    return;
  }

  vector<StringPiece> transfer_encodings;
  headers()->GetAllOfHeader(kTransferCoding, &transfer_encodings);
  CHECK_GE(1ul, transfer_encodings.size());
  for (vector<StringPiece>::iterator it = transfer_encodings.begin();
       it != transfer_encodings.end();
       ++it) {
    CHECK(StringPieceUtils::EqualIgnoreCase("identity", *it) ||
          StringPieceUtils::EqualIgnoreCase("chunked", *it)) << *it;
  }

  vector<StringPiece> content_lengths;
  headers()->GetAllOfHeader(kContentLength, &content_lengths);
  CHECK_GE(1ul, content_lengths.size());

  CHECK_EQ(has_complete_message_, IsCompleteMessage(*this));
}

}  // namespace test
}  // namespace tools
}  // namespace net
<commit_msg>Fix an invalid early return.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/tools/quic/test_tools/http_message_test_utils.h"

#include <vector>

#include "base/basictypes.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"

using base::StringPiece;
using std::string;
using std::vector;

namespace net {
namespace tools {
namespace test {

namespace {

//const char* kContentEncoding = "content-encoding";
const char* kContentLength = "content-length";
const char* kTransferCoding = "transfer-encoding";

// Both kHTTPVersionString and kMethodString arrays are constructed to match
// the enum values defined in Version and Method of HTTPMessage.
const char* kHTTPVersionString[] = {
  "",
  "HTTP/0.9",
  "HTTP/1.0",
  "HTTP/1.1"
};

const char* kMethodString[] = {
  "",
  "OPTIONS",
  "GET",
  "HEAD",
  "POST",
  "PUT",
  "DELETE",
  "TRACE",
  "CONNECT",
  "MKCOL",
  "UNLOCK",
};

// Returns true if the message represents a complete request or response.
// Messages are considered complete if:
// - Transfer-Encoding: chunked is present and message has a final chunk.
// - Content-Length header is present and matches the message body length.
// - Neither Transfer-Encoding nor Content-Length is present and message
//   is tagged as complete.
bool IsCompleteMessage(const HTTPMessage& message) {
  const BalsaHeaders* headers = message.headers();
  StringPiece content_length = headers->GetHeader(kContentLength);
  if (!content_length.empty()) {
    int parsed_content_length;
    if (!base::StringToInt(content_length, &parsed_content_length)) {
      return false;
    }
    return (message.body().size() == (uint)parsed_content_length);
  } else {
    // Assume messages without transfer coding or content-length are
    // tagged correctly.
    return message.has_complete_message();
  }
}

}  // namespace

HTTPMessage::Method HTTPMessage::StringToMethod(StringPiece str) {
  // Skip the first element of the array since it is empty string.
  for (unsigned long i = 1; i < arraysize(kMethodString); ++i) {
    if (strncmp(str.data(), kMethodString[i], str.length()) == 0) {
      return static_cast<HTTPMessage::Method>(i);
    }
  }
  return HttpConstants::UNKNOWN_METHOD;
}

HTTPMessage::Version HTTPMessage::StringToVersion(StringPiece str) {
  // Skip the first element of the array since it is empty string.
  for (unsigned long i = 1; i < arraysize(kHTTPVersionString); ++i) {
    if (strncmp(str.data(), kHTTPVersionString[i], str.length()) == 0) {
      return static_cast<HTTPMessage::Version>(i);
    }
  }
  return HttpConstants::HTTP_UNKNOWN;
}

const char* HTTPMessage::MethodToString(Method method) {
  CHECK_LT(static_cast<size_t>(method), arraysize(kMethodString));
  return kMethodString[method];
}

const char* HTTPMessage::VersionToString(Version version) {
  CHECK_LT(static_cast<size_t>(version), arraysize(kHTTPVersionString));
  return kHTTPVersionString[version];
}

HTTPMessage::HTTPMessage()
    : is_request_(true) {
  InitializeFields();
}

HTTPMessage::HTTPMessage(Version ver, Method request, const string& path)
    : is_request_(true) {
  InitializeFields();
  if (ver != HttpConstants::HTTP_0_9) {
    headers()->SetRequestVersion(VersionToString(ver));
  }
  headers()->SetRequestMethod(MethodToString(request));
  headers()->SetRequestUri(path);
}

HTTPMessage::~HTTPMessage() {
}

void HTTPMessage::InitializeFields() {
  has_complete_message_ = true;
  skip_message_validation_ = false;
}

void HTTPMessage::AddHeader(const string& header, const string& value) {
  headers()->AppendHeader(header, value);
}

void HTTPMessage::RemoveHeader(const string& header) {
  headers()->RemoveAllOfHeader(header);
}

void HTTPMessage::ReplaceHeader(const string& header, const string& value) {
  headers()->ReplaceOrAppendHeader(header, value);
}

void HTTPMessage::AddBody(const string& body, bool add_content_length) {
  body_ = body;
  // Remove any transfer-encoding that was left by a previous body.
  RemoveHeader(kTransferCoding);
  if (add_content_length) {
    ReplaceHeader(kContentLength, base::IntToString(body.size()));
  } else {
    RemoveHeader(kContentLength);
  }
}

void HTTPMessage::ValidateMessage() const {
  if (skip_message_validation_) {
    return;
  }

  vector<StringPiece> transfer_encodings;
  headers()->GetAllOfHeader(kTransferCoding, &transfer_encodings);
  CHECK_GE(1ul, transfer_encodings.size());
  for (vector<StringPiece>::iterator it = transfer_encodings.begin();
       it != transfer_encodings.end();
       ++it) {
    CHECK(StringPieceUtils::EqualIgnoreCase("identity", *it) ||
          StringPieceUtils::EqualIgnoreCase("chunked", *it)) << *it;
  }

  vector<StringPiece> content_lengths;
  headers()->GetAllOfHeader(kContentLength, &content_lengths);
  CHECK_GE(1ul, content_lengths.size());

  CHECK_EQ(has_complete_message_, IsCompleteMessage(*this));
}

}  // namespace test
}  // namespace tools
}  // namespace net
<|endoftext|>


<commit_before>// Copyright 2010-2012 Google
// 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 <math.h>
#include <string.h>
#include <algorithm>
#include "base/hash.h"
#include <string>
#include <utility>
#include <vector>

#include "base/commandlineflags.h"
#include "base/hash.h"
#include "base/int-type-indexed-vector.h"
#include "base/int-type.h"
#include "base/integral_types.h"
#include "base/logging.h"
#include "base/map-util.h"
#include "base/scoped_ptr.h"
#include "base/stl_util.h"
#include "base/stringprintf.h"
#include "constraint_solver/constraint_solver.h"
#include "constraint_solver/constraint_solveri.h"
#include "util/bitset.h"
#include "util/const_int_array.h"

#include "core/Solver.cc"

namespace operations_research {
namespace {

class SatPropagator : public Constraint {
 public:
  SatPropagator(Solver* const solver) : Constraint(solver) {}

  ~SatPropagator() {}

  bool Check(IntExpr* const expr) const {
    IntVar* expr_var = NULL;
    bool expr_negated = false;
    return solver()->IsBooleanVar(expr, &expr_var, &expr_negated);
  }

  bool Check(const std::vector<IntVar*>& vars) const {
    for (int i = 0; i < vars.size(); ++i) {
      if (!Check(vars[i])) {
        return false;
      }
    }
    return true;
  }

  Minisat::Lit Literal(IntExpr* const expr) {
    IntVar* expr_var = NULL;
    bool expr_negated = false;
    if (!solver()->IsBooleanVar(expr, &expr_var, &expr_negated)) {
      return Minisat::lit_Error;
    }
    if (ContainsKey(indices_, expr_var)) {
      return Minisat::mkLit(indices_[expr_var], expr_negated);
    } else {
      const Minisat::Var var = minisat_.newVar(true, true);
      vars_.push_back(expr_var);
      return Minisat::mkLit(var, expr_negated);
    }
  }

  void VariableBound(int index) {
    // if (indices_[index]->Min() == 0) {
    //   Flip(Minisat::Var(-1 - index));
    // } else {
    //   Flip(Minisat::Var(1 + index));
    // }
  }

  virtual void Post() {
    for (int i = 0; i < vars_.size(); ++i) {
      Demon* const d = MakeConstraintDemon1(solver(),
                                            this,
                                            &SatPropagator::VariableBound,
                                            "VariableBound",
                                            indices_[vars_[i]]);
      vars_[i]->WhenDomain(d);
    }
  }

  virtual void InitialPropagate() {
    for (int i = 0; i < vars_.size(); ++i) {
      IntVar* const var = vars_[i];
      if (var->Bound()) {
        VariableBound(indices_[var]);
      }
    }
  }

  // Add a clause to the solver.
  bool AddClause (const vec<Lit>& ps) {
    return minisat_.addClause(ps);
  }

  // Add the empty clause, making the solver contradictory.
  bool AddEmptyClause() {
    return minisat_.addEmptyClause();
  }

  // Add a unit clause to the solver.
  bool AddClause (Lit p) {
    return minisat_.addClause(p);
  }

  // Add a binary clause to the solver.
  bool AddClause (Lit p, Lit q) {
    return minisat_.addClause(p, q);
  }

  // Add a ternary clause to the solver.
  bool AddClause (Lit p, Lit q, Lit r) {
    return minisat_.addClause(p, q, r);
  }

 private:
  Minisat::Solver minisat_;
  std::vector<IntVar*> vars_;
  hash_map<IntVar*, Minisat::Var> indices_;
};
}  // namespace

bool AddBoolEq(SatPropagator* const sat,
               IntExpr* const left,
               IntExpr* const right) {
  if (!sat->Check(left) || !sat->Check(right)) {
    return false;
  }
  Minisat::Lit left_lit = sat->Literal(left);
  Minisat::Lit right_lit = sat->Literal(right);
  sat->AddClause(~left_lit, right_lit);
  sat->AddClause(left_lit, ~right_lit);
  return true;
}

bool AddBoolLe(SatPropagator* const sat,
               IntExpr* const left,
               IntExpr* const right) {
  if (!sat->Check(left) || !sat->Check(right)) {
    return false;
  }
  Minisat::Lit left_lit = sat->Literal(left);
  Minisat::Lit right_lit = sat->Literal(right);
  sat->AddClause(~left_lit, right_lit);
  return true;
}

bool AddBoolNot(SatPropagator* const sat,
                IntExpr* const left,
                IntExpr* const right) {
  if (!sat->Check(left) || !sat->Check(right)) {
    return false;
  }
  Minisat::Lit left_lit = sat->Literal(left);
  Minisat::Lit right_lit = sat->Literal(right);
  sat->AddClause(~left_lit, ~right_lit);
  sat->AddClause(left_lit, right_lit);
  return true;
}

bool AddBoolAndArrayEqVar(SatPropagator* const sat,
                          const std::vector<IntVar*>& vars,
                          IntVar* const target) {
  return false;

}

bool AddBoolOrArrayEqualTrue(SatPropagator* const sat,
                             const std::vector<IntVar*>& vars) {
  if (!sat->Check(vars)) {
    return false;
  }
  std::vector<Minisat::Lit> atoms(vars.size());
  for (int i = 0; i < vars.size(); ++i) {
    atoms[i] = sat->Literal(vars[i]);
  }
  return false;
}
}  // namespace operations_research
<commit_msg>more integration with the minisat<commit_after>// Copyright 2010-2012 Google
// 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 <math.h>
#include <string.h>
#include <algorithm>
#include "base/hash.h"
#include <string>
#include <utility>
#include <vector>

#include "base/commandlineflags.h"
#include "base/hash.h"
#include "base/int-type-indexed-vector.h"
#include "base/int-type.h"
#include "base/integral_types.h"
#include "base/logging.h"
#include "base/map-util.h"
#include "base/scoped_ptr.h"
#include "base/stl_util.h"
#include "base/stringprintf.h"
#include "constraint_solver/constraint_solver.h"
#include "constraint_solver/constraint_solveri.h"
#include "util/bitset.h"
#include "util/const_int_array.h"

#include "core/Solver.cc"

namespace operations_research {
namespace {

class SatPropagator : public Constraint {
 public:
  SatPropagator(Solver* const solver) : Constraint(solver) {}

  ~SatPropagator() {}

  bool Check(IntExpr* const expr) const {
    IntVar* expr_var = NULL;
    bool expr_negated = false;
    return solver()->IsBooleanVar(expr, &expr_var, &expr_negated);
  }

  bool Check(const std::vector<IntVar*>& vars) const {
    for (int i = 0; i < vars.size(); ++i) {
      if (!Check(vars[i])) {
        return false;
      }
    }
    return true;
  }

  Minisat::Lit Literal(IntExpr* const expr) {
    IntVar* expr_var = NULL;
    bool expr_negated = false;
    if (!solver()->IsBooleanVar(expr, &expr_var, &expr_negated)) {
      return Minisat::lit_Error;
    }
    if (ContainsKey(indices_, expr_var)) {
      return Minisat::mkLit(indices_[expr_var], expr_negated);
    } else {
      const Minisat::Var var = minisat_.newVar(true, true);
      vars_.push_back(expr_var);
      return Minisat::mkLit(var, expr_negated);
    }
  }

  void VariableBound(int index) {
    // if (indices_[index]->Min() == 0) {
    //   Flip(Minisat::Var(-1 - index));
    // } else {
    //   Flip(Minisat::Var(1 + index));
    // }
  }

  virtual void Post() {
    for (int i = 0; i < vars_.size(); ++i) {
      Demon* const d = MakeConstraintDemon1(solver(),
                                            this,
                                            &SatPropagator::VariableBound,
                                            "VariableBound",
                                            indices_[vars_[i]]);
      vars_[i]->WhenDomain(d);
    }
  }

  virtual void InitialPropagate() {
    for (int i = 0; i < vars_.size(); ++i) {
      IntVar* const var = vars_[i];
      if (var->Bound()) {
        VariableBound(indices_[var]);
      }
    }
  }

  // Add a clause to the solver.
  bool AddClause (const vec<Lit>& ps) {
    return minisat_.addClause(ps);
  }

  // Add the empty clause, making the solver contradictory.
  bool AddEmptyClause() {
    return minisat_.addEmptyClause();
  }

  // Add a unit clause to the solver.
  bool AddClause (Lit p) {
    return minisat_.addClause(p);
  }

  // Add a binary clause to the solver.
  bool AddClause (Lit p, Lit q) {
    return minisat_.addClause(p, q);
  }

  // Add a ternary clause to the solver.
  bool AddClause (Lit p, Lit q, Lit r) {
    return minisat_.addClause(p, q, r);
  }

 private:
  Minisat::Solver minisat_;
  std::vector<IntVar*> vars_;
  hash_map<IntVar*, Minisat::Var> indices_;
};
}  // namespace

bool AddBoolEq(SatPropagator* const sat,
               IntExpr* const left,
               IntExpr* const right) {
  if (!sat->Check(left) || !sat->Check(right)) {
    return false;
  }
  Minisat::Lit left_lit = sat->Literal(left);
  Minisat::Lit right_lit = sat->Literal(right);
  sat->AddClause(~left_lit, right_lit);
  sat->AddClause(left_lit, ~right_lit);
  return true;
}

bool AddBoolLe(SatPropagator* const sat,
               IntExpr* const left,
               IntExpr* const right) {
  if (!sat->Check(left) || !sat->Check(right)) {
    return false;
  }
  Minisat::Lit left_lit = sat->Literal(left);
  Minisat::Lit right_lit = sat->Literal(right);
  sat->AddClause(~left_lit, right_lit);
  return true;
}

bool AddBoolNot(SatPropagator* const sat,
                IntExpr* const left,
                IntExpr* const right) {
  if (!sat->Check(left) || !sat->Check(right)) {
    return false;
  }
  Minisat::Lit left_lit = sat->Literal(left);
  Minisat::Lit right_lit = sat->Literal(right);
  sat->AddClause(~left_lit, ~right_lit);
  sat->AddClause(left_lit, right_lit);
  return true;
}

bool AddBoolAndArrayEqVar(SatPropagator* const sat,
                          const std::vector<IntVar*>& vars,
                          IntVar* const target) {
  return false;
  if (!sat->Check(vars) || !sat->Check(target)) {
    return false;
  }
  Minisat::Lit target_lit = sat->Literal(target);
  std::vector<Minisat::Lit> lits(vars.size() + 1);
  for (int i = 0; i < vars.size(); ++i) {
    lits[i] = sat->Literal(vars[i]);
  }
  lits[vars.size()] = ~target_lit;
  sat->AddClause(lits);

}

bool AddBoolOrArrayEqualTrue(SatPropagator* const sat,
                             const std::vector<IntVar*>& vars) {
  if (!sat->Check(vars)) {
    return false;
  }
  std::vector<Minisat::Lit> lits(vars.size());
  for (int i = 0; i < vars.size(); ++i) {
    lits[i] = sat->Literal(vars[i]);
  }
  sat->AddClause(lits);
  return false;
}

bool AddBoolAndArrayEqualFalse(SatPropagator* const sat,
                               const std::vector<IntVar*>& vars) {
  if (!sat->Check(vars)) {
    return false;
  }
  std::vector<Minisat::Lit> lits(vars.size());
  for (int i = 0; i < vars.size(); ++i) {
    lits[i] = ~sat->Literal(vars[i]);
  }
  sat->AddClause(lits);
  return false;
}
}  // namespace operations_research
<|endoftext|>


<commit_before>#ifndef TURBO_CONTAINER_SPSC_RING_QUEUE_HPP
#define TURBO_CONTAINER_SPSC_RING_QUEUE_HPP

#include <cstdint>
#include <array>
#include <atomic>
#include <functional>
#include <memory>
#include <vector>
#include <turbo/toolset/attribute.hpp>

namespace turbo {
namespace container {

template <class value_t, class allocator_t = std::allocator<value_t>> class spsc_key;

template <class value_t, class allocator_t = std::allocator<value_t>>
class spsc_producer
{
public:
    typedef value_t value_type;
    typedef allocator_t allocator_type;
    typedef spsc_key<value_t, allocator_t> key;
    enum class result
    {
	success,
	queue_full
    };
    spsc_producer(const key&,
		    std::vector<value_t, allocator_t>& buffer,
		    std::atomic<uint32_t>& head,
		    std::atomic<uint32_t>& tail);
    result try_enqueue_copy(const value_t& input);
    result try_enqueue_move(value_t&& input);
private:
    alignas(LEVEL1_DCACHE_LINESIZE) std::vector<value_t, allocator_t>& buffer_;
    alignas(LEVEL1_DCACHE_LINESIZE) std::atomic<uint32_t>& head_;
    alignas(LEVEL1_DCACHE_LINESIZE) std::atomic<uint32_t>& tail_;
};

template <class value_t, class allocator_t = std::allocator<value_t>>
class spsc_consumer
{
public:
    typedef value_t value_type;
    typedef allocator_t allocator_type;
    typedef spsc_key<value_t, allocator_t> key;
    spsc_consumer(const key&,
		    std::vector<value_t, allocator_t>& buffer,
		    std::atomic<uint32_t>& head,
		    std::atomic<uint32_t>& tail);
    enum class result
    {
	success,
	queue_empty
    };
    result try_dequeue_copy(value_t& output);
    result try_dequeue_move(value_t& output);
private:
    alignas(LEVEL1_DCACHE_LINESIZE) std::vector<value_t, allocator_t>& buffer_;
    alignas(LEVEL1_DCACHE_LINESIZE) std::atomic<uint32_t>& head_;
    alignas(LEVEL1_DCACHE_LINESIZE) std::atomic<uint32_t>& tail_;
};

template <class value_t, class allocator_t = std::allocator<value_t>>
class spsc_ring_queue
{
public:
    typedef value_t value_type;
    typedef allocator_t allocator_type;
    typedef spsc_producer<value_t, allocator_t> producer;
    typedef spsc_consumer<value_t, allocator_t> consumer;
    spsc_ring_queue(uint32_t capacity);
    producer& get_producer() { return producer_; }
    consumer& get_consumer() { return consumer_; }
private:
    typedef std::vector<value_t, allocator_t> vector_type;
    alignas(LEVEL1_DCACHE_LINESIZE) std::vector<value_t, allocator_t> buffer_;
    alignas(LEVEL1_DCACHE_LINESIZE) std::atomic<uint32_t> head_;
    alignas(LEVEL1_DCACHE_LINESIZE) std::atomic<uint32_t> tail_;
    producer producer_;
    consumer consumer_;
};

} // namespace container
} // namespace turbo

#endif
<commit_msg>only the producer and consumer objects need alignment, the private fields within them do not require it<commit_after>#ifndef TURBO_CONTAINER_SPSC_RING_QUEUE_HPP
#define TURBO_CONTAINER_SPSC_RING_QUEUE_HPP

#include <cstdint>
#include <atomic>
#include <functional>
#include <memory>
#include <vector>
#include <turbo/toolset/attribute.hpp>

namespace turbo {
namespace container {

template <class value_t, class allocator_t = std::allocator<value_t>> class spsc_key;

template <class value_t, class allocator_t = std::allocator<value_t>>
class spsc_producer
{
public:
    typedef value_t value_type;
    typedef allocator_t allocator_type;
    typedef spsc_key<value_t, allocator_t> key;
    enum class result
    {
	success,
	queue_full
    };
    spsc_producer(const key&,
		    std::vector<value_t, allocator_t>& buffer,
		    std::atomic<uint32_t>& head,
		    std::atomic<uint32_t>& tail);
    result try_enqueue_copy(const value_t& input);
    result try_enqueue_move(value_t&& input);
private:
    std::vector<value_t, allocator_t>& buffer_;
    std::atomic<uint32_t>& head_;
    std::atomic<uint32_t>& tail_;
};

template <class value_t, class allocator_t = std::allocator<value_t>>
class spsc_consumer
{
public:
    typedef value_t value_type;
    typedef allocator_t allocator_type;
    typedef spsc_key<value_t, allocator_t> key;
    spsc_consumer(const key&,
		    std::vector<value_t, allocator_t>& buffer,
		    std::atomic<uint32_t>& head,
		    std::atomic<uint32_t>& tail);
    enum class result
    {
	success,
	queue_empty
    };
    result try_dequeue_copy(value_t& output);
    result try_dequeue_move(value_t& output);
private:
    std::vector<value_t, allocator_t>& buffer_;
    std::atomic<uint32_t>& head_;
    std::atomic<uint32_t>& tail_;
};

template <class value_t, class allocator_t = std::allocator<value_t>>
class spsc_ring_queue
{
public:
    typedef value_t value_type;
    typedef allocator_t allocator_type;
    typedef spsc_producer<value_t, allocator_t> producer;
    typedef spsc_consumer<value_t, allocator_t> consumer;
    spsc_ring_queue(uint32_t capacity);
    producer& get_producer() { return producer_; }
    consumer& get_consumer() { return consumer_; }
private:
    typedef std::vector<value_t, allocator_t> vector_type;
    alignas(LEVEL1_DCACHE_LINESIZE) std::vector<value_t, allocator_t> buffer_;
    alignas(LEVEL1_DCACHE_LINESIZE) std::atomic<uint32_t> head_;
    alignas(LEVEL1_DCACHE_LINESIZE) std::atomic<uint32_t> tail_;
    alignas(LEVEL1_DCACHE_LINESIZE) producer producer_;
    alignas(LEVEL1_DCACHE_LINESIZE) consumer consumer_;
};

} // namespace container
} // namespace turbo

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
 */

#pragma once

#include <climits>
#include <cstddef>
#include <cmath>
#include <uavcan/build_config.hpp>

#ifndef UAVCAN_CPP_VERSION
# error UAVCAN_CPP_VERSION
#endif
#if UAVCAN_CPP_VERSION < UAVCAN_CPP11
# include <float.h>      // cfloat may not be available
#else
# include <cfloat>       // C++11 mode assumes that all standard headers are available
#endif

namespace uavcan
{
/**
 * Usage:
 *  StaticAssert<expression>::check();
 */
template <bool Value>
struct UAVCAN_EXPORT StaticAssert;

template <>
struct UAVCAN_EXPORT StaticAssert<true>
{
    static void check() { }
};

/**
 * Usage:
 *  ShowIntegerAsError<integer_expression>::foobar();
 */
template <long N> struct ShowIntegerAsError;

/**
 * Prevents copying when inherited
 */
class UAVCAN_EXPORT Noncopyable
{
    Noncopyable(const Noncopyable&);
    Noncopyable& operator=(const Noncopyable&);
protected:
    Noncopyable() { }
    ~Noncopyable() { }
};

/**
 * Compile time conditions
 */
template <bool B, typename T = void>
struct UAVCAN_EXPORT EnableIf { };

template <typename T>
struct UAVCAN_EXPORT EnableIf<true, T>
{
    typedef T Type;
};

/**
 * Lightweight type categorization.
 */
template <typename T, typename R = void>
struct UAVCAN_EXPORT EnableIfType
{
    typedef R Type;
};

/**
 * Compile-time type selection (Alexandrescu)
 */
template <bool Condition, typename TrueType, typename FalseType>
struct UAVCAN_EXPORT Select;

template <typename TrueType, typename FalseType>
struct UAVCAN_EXPORT Select<true, TrueType, FalseType>
{
    typedef TrueType Result;
};

template <typename TrueType, typename FalseType>
struct UAVCAN_EXPORT Select<false, TrueType, FalseType>
{
    typedef FalseType Result;
};

/**
 * Remove reference as in <type_traits>
 */
template <class T> struct RemoveReference      { typedef T Type; };
template <class T> struct RemoveReference<T&>  { typedef T Type; };
#if UAVCAN_CPP_VERSION > UAVCAN_CPP03
template <class T> struct RemoveReference<T&&> { typedef T Type; };
#endif

/**
 * Value types
 */
template <bool> struct UAVCAN_EXPORT BooleanType { };
typedef BooleanType<true> TrueType;
typedef BooleanType<false> FalseType;

/**
 * Relations
 */
template <typename T1, typename T2>
class UAVCAN_EXPORT IsImplicitlyConvertibleFromTo
{
    template <typename U> static U returner();

    struct True_ { char x[2]; };
    struct False_ { };

    static True_ test(const T2 &);
    static False_ test(...);

public:
    enum { Result = sizeof(True_) == sizeof(IsImplicitlyConvertibleFromTo<T1, T2>::test(returner<T1>())) };
};

/**
 * try_implicit_cast<>(From)
 * try_implicit_cast<>(From, To)
 * @{
 */
template <typename From, typename To>
struct UAVCAN_EXPORT TryImplicitCastImpl
{
    static To impl(const From& from, const To&, TrueType) { return To(from); }
    static To impl(const From&, const To& default_, FalseType) { return default_; }
};

/**
 * If possible, performs an implicit cast from the type From to the type To.
 * If the cast is not possible, returns default_ of type To.
 */
template <typename To, typename From>
UAVCAN_EXPORT
To try_implicit_cast(const From& from, const To& default_)
{
    return TryImplicitCastImpl<From, To>::impl(from, default_,
                                               BooleanType<IsImplicitlyConvertibleFromTo<From, To>::Result>());
}

/**
 * If possible, performs an implicit cast from the type From to the type To.
 * If the cast is not possible, returns a default constructed object of the type To.
 */
template <typename To, typename From>
UAVCAN_EXPORT
To try_implicit_cast(const From& from)
{
    return TryImplicitCastImpl<From, To>::impl(from, To(),
                                               BooleanType<IsImplicitlyConvertibleFromTo<From, To>::Result>());
}
/**
 * @}
 */

/**
 * Compile time square root for integers.
 * Useful for operations on square matrices.
 */
template <unsigned Value> struct UAVCAN_EXPORT CompileTimeIntSqrt;
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<4>  { enum { Result = 2 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<9>  { enum { Result = 3 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<16> { enum { Result = 4 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<25> { enum { Result = 5 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<36> { enum { Result = 6 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<49> { enum { Result = 7 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<64> { enum { Result = 8 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<81> { enum { Result = 9 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<100> { enum { Result = 10 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<121> { enum { Result = 11 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<144> { enum { Result = 12 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<169> { enum { Result = 13 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<196> { enum { Result = 14 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<225> { enum { Result = 15 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<256> { enum { Result = 16 }; };

/**
 * Replacement for std::copy(..)
 */
template <typename InputIt, typename OutputIt>
UAVCAN_EXPORT
OutputIt copy(InputIt first, InputIt last, OutputIt result)
{
    while (first != last)
    {
        *result = *first;
        ++first;
        ++result;
    }
    return result;
}

/**
 * Replacement for std::fill(..)
 */
template <typename ForwardIt, typename T>
UAVCAN_EXPORT
void fill(ForwardIt first, ForwardIt last, const T& value)
{
    while (first != last)
    {
        *first = value;
        ++first;
    }
}

/**
 * Replacement for std::fill_n(..)
 */
template<typename OutputIt, typename T>
UAVCAN_EXPORT
void fill_n(OutputIt first, std::size_t n, const T& value)
{
    while (n--)
    {
        *first++ = value;
    }
}

/**
 * Replacement for std::min(..)
 */
template <typename T>
UAVCAN_EXPORT
const T& min(const T& a, const T& b)
{
    return (b < a) ? b : a;
}

/**
 * Replacement for std::max(..)
 */
template <typename T>
UAVCAN_EXPORT
const T& max(const T& a, const T& b)
{
    return (a < b) ? b : a;
}

/**
 * Replacement for std::lexicographical_compare(..)
 */
template<typename InputIt1, typename InputIt2>
UAVCAN_EXPORT
bool lexicographical_compare(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
{
    while ((first1 != last1) && (first2 != last2))
    {
        if (*first1 < *first2)
        {
            return true;
        }
        if (*first2 < *first1)
        {
            return false;
        }
        ++first1;
        ++first2;
    }
    return (first1 == last1) && (first2 != last2);
}

/**
 * Replacement for std::equal(..)
 */
template<typename InputIt1, typename InputIt2>
UAVCAN_EXPORT
bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
{
    while (first1 != last1)
    {
        if (*first1 != *first2)
        {
            return false;
        }
        ++first1;
        ++first2;
    }
    return true;
}

/**
 * Numeric traits, like std::numeric_limits<>
 */
template <typename T>
struct UAVCAN_EXPORT NumericTraits;

/// char
template <>
struct UAVCAN_EXPORT NumericTraits<char>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 1 };
    static char max() { return CHAR_MAX; }
    static char min() { return CHAR_MIN; }
};
template <>
struct UAVCAN_EXPORT NumericTraits<signed char>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 1 };
    static signed char max() { return SCHAR_MAX; }
    static signed char min() { return SCHAR_MIN; }
};
template <>
struct UAVCAN_EXPORT NumericTraits<unsigned char>
{
    enum { IsSigned = 0 };
    enum { IsInteger = 1 };
    static unsigned char max() { return UCHAR_MAX; }
    static unsigned char min() { return 0; }
};

/// short
template <>
struct UAVCAN_EXPORT NumericTraits<short>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 1 };
    static short max() { return SHRT_MAX; }
    static short min() { return SHRT_MIN; }
};
template <>
struct UAVCAN_EXPORT NumericTraits<unsigned short>
{
    enum { IsSigned = 0 };
    enum { IsInteger = 1 };
    static unsigned short max() { return USHRT_MAX; }
    static unsigned short min() { return 0; }
};

/// int
template <>
struct UAVCAN_EXPORT NumericTraits<int>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 1 };
    static int max() { return INT_MAX; }
    static int min() { return INT_MIN; }
};
template <>
struct UAVCAN_EXPORT NumericTraits<unsigned int>
{
    enum { IsSigned = 0 };
    enum { IsInteger = 1 };
    static unsigned int max() { return UINT_MAX; }
    static unsigned int min() { return 0; }
};

/// long
template <>
struct UAVCAN_EXPORT NumericTraits<long>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 1 };
    static long max() { return LONG_MAX; }
    static long min() { return LONG_MIN; }
};
template <>
struct UAVCAN_EXPORT NumericTraits<unsigned long>
{
    enum { IsSigned = 0 };
    enum { IsInteger = 1 };
    static unsigned long max() { return ULONG_MAX; }
    static unsigned long min() { return 0; }
};

/// long long
template <>
struct UAVCAN_EXPORT NumericTraits<long long>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 1 };
    static long long max() { return LLONG_MAX; }
    static long long min() { return LLONG_MIN; }
};
template <>
struct UAVCAN_EXPORT NumericTraits<unsigned long long>
{
    enum { IsSigned = 0 };
    enum { IsInteger = 1 };
    static unsigned long long max() { return ULLONG_MAX; }
    static unsigned long long min() { return 0; }
};

/// float
template <>
struct UAVCAN_EXPORT NumericTraits<float>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 0 };
    static float max() { return FLT_MAX; }
    static float min() { return FLT_MIN; }
    static float infinity() { return INFINITY; }
    static float epsilon() { return FLT_EPSILON; }
};

/// double
template <>
struct UAVCAN_EXPORT NumericTraits<double>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 0 };
    static double max() { return DBL_MAX; }
    static double min() { return DBL_MIN; }
    static double infinity() { return static_cast<double>(INFINITY) * static_cast<double>(INFINITY); }
    static double epsilon() { return DBL_EPSILON; }
};

#if defined(LDBL_MAX) && defined(LDBL_MIN) && defined(LDBL_EPSILON)
/// long double
template <>
struct UAVCAN_EXPORT NumericTraits<long double>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 0 };
    static long double max() { return LDBL_MAX; }
    static long double min() { return LDBL_MIN; }
    static long double infinity() { return static_cast<long double>(INFINITY) * static_cast<long double>(INFINITY); }
    static long double epsilon() { return LDBL_EPSILON; }
};
#endif

#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
# undef isnan
# undef isinf
# undef signbit
#endif

/**
 * Replacement for std::isnan().
 * Note that direct float comparison (==, !=) is intentionally avoided.
 */
template <typename T>
inline bool isNaN(T arg)
{
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
    return std::isnan(arg);
#else
    // coverity[same_on_both_sides : FALSE]
    // cppcheck-suppress duplicateExpression
    return !(arg <= arg);
#endif
}

/**
 * Replacement for std::isinf().
 * Note that direct float comparison (==, !=) is intentionally avoided.
 */
template <typename T>
inline bool isInfinity(T arg)
{
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
    return std::isinf(arg);
#else
    return (arg >= NumericTraits<T>::infinity()) || (arg <= -NumericTraits<T>::infinity());
#endif
}

/**
 * Replacement for std::signbit().
 * Note that direct float comparison (==, !=) is intentionally avoided.
 */
template <typename T>
inline bool getSignBit(T arg)
{
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
    return std::signbit(arg);
#else
    return arg < T(0) || (((arg <= T(0)) && (arg >= T(0))) && (T(1) / arg < T(0)));
#endif
}

}
<commit_msg>Added IntToType<><commit_after>/*
 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
 */

#pragma once

#include <climits>
#include <cstddef>
#include <cmath>
#include <uavcan/build_config.hpp>

#ifndef UAVCAN_CPP_VERSION
# error UAVCAN_CPP_VERSION
#endif
#if UAVCAN_CPP_VERSION < UAVCAN_CPP11
# include <float.h>      // cfloat may not be available
#else
# include <cfloat>       // C++11 mode assumes that all standard headers are available
#endif

namespace uavcan
{
/**
 * Usage:
 *  StaticAssert<expression>::check();
 */
template <bool Value>
struct UAVCAN_EXPORT StaticAssert;

template <>
struct UAVCAN_EXPORT StaticAssert<true>
{
    static void check() { }
};

/**
 * Usage:
 *  ShowIntegerAsError<integer_expression>::foobar();
 */
template <long N> struct ShowIntegerAsError;

/**
 * Prevents copying when inherited
 */
class UAVCAN_EXPORT Noncopyable
{
    Noncopyable(const Noncopyable&);
    Noncopyable& operator=(const Noncopyable&);
protected:
    Noncopyable() { }
    ~Noncopyable() { }
};

/**
 * Compile time conditions
 */
template <bool B, typename T = void>
struct UAVCAN_EXPORT EnableIf { };

template <typename T>
struct UAVCAN_EXPORT EnableIf<true, T>
{
    typedef T Type;
};

/**
 * Lightweight type categorization.
 */
template <typename T, typename R = void>
struct UAVCAN_EXPORT EnableIfType
{
    typedef R Type;
};

/**
 * Compile-time type selection (Alexandrescu)
 */
template <bool Condition, typename TrueType, typename FalseType>
struct UAVCAN_EXPORT Select;

template <typename TrueType, typename FalseType>
struct UAVCAN_EXPORT Select<true, TrueType, FalseType>
{
    typedef TrueType Result;
};

template <typename TrueType, typename FalseType>
struct UAVCAN_EXPORT Select<false, TrueType, FalseType>
{
    typedef FalseType Result;
};

/**
 * Remove reference as in <type_traits>
 */
template <class T> struct RemoveReference      { typedef T Type; };
template <class T> struct RemoveReference<T&>  { typedef T Type; };
#if UAVCAN_CPP_VERSION > UAVCAN_CPP03
template <class T> struct RemoveReference<T&&> { typedef T Type; };
#endif

/**
 * Value types
 */
template <bool> struct UAVCAN_EXPORT BooleanType { };
typedef BooleanType<true> TrueType;
typedef BooleanType<false> FalseType;

template <int N> struct IntToType { };

/**
 * Relations
 */
template <typename T1, typename T2>
class UAVCAN_EXPORT IsImplicitlyConvertibleFromTo
{
    template <typename U> static U returner();

    struct True_ { char x[2]; };
    struct False_ { };

    static True_ test(const T2 &);
    static False_ test(...);

public:
    enum { Result = sizeof(True_) == sizeof(IsImplicitlyConvertibleFromTo<T1, T2>::test(returner<T1>())) };
};

/**
 * try_implicit_cast<>(From)
 * try_implicit_cast<>(From, To)
 * @{
 */
template <typename From, typename To>
struct UAVCAN_EXPORT TryImplicitCastImpl
{
    static To impl(const From& from, const To&, TrueType) { return To(from); }
    static To impl(const From&, const To& default_, FalseType) { return default_; }
};

/**
 * If possible, performs an implicit cast from the type From to the type To.
 * If the cast is not possible, returns default_ of type To.
 */
template <typename To, typename From>
UAVCAN_EXPORT
To try_implicit_cast(const From& from, const To& default_)
{
    return TryImplicitCastImpl<From, To>::impl(from, default_,
                                               BooleanType<IsImplicitlyConvertibleFromTo<From, To>::Result>());
}

/**
 * If possible, performs an implicit cast from the type From to the type To.
 * If the cast is not possible, returns a default constructed object of the type To.
 */
template <typename To, typename From>
UAVCAN_EXPORT
To try_implicit_cast(const From& from)
{
    return TryImplicitCastImpl<From, To>::impl(from, To(),
                                               BooleanType<IsImplicitlyConvertibleFromTo<From, To>::Result>());
}
/**
 * @}
 */

/**
 * Compile time square root for integers.
 * Useful for operations on square matrices.
 */
template <unsigned Value> struct UAVCAN_EXPORT CompileTimeIntSqrt;
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<4>  { enum { Result = 2 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<9>  { enum { Result = 3 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<16> { enum { Result = 4 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<25> { enum { Result = 5 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<36> { enum { Result = 6 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<49> { enum { Result = 7 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<64> { enum { Result = 8 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<81> { enum { Result = 9 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<100> { enum { Result = 10 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<121> { enum { Result = 11 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<144> { enum { Result = 12 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<169> { enum { Result = 13 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<196> { enum { Result = 14 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<225> { enum { Result = 15 }; };
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<256> { enum { Result = 16 }; };

/**
 * Replacement for std::copy(..)
 */
template <typename InputIt, typename OutputIt>
UAVCAN_EXPORT
OutputIt copy(InputIt first, InputIt last, OutputIt result)
{
    while (first != last)
    {
        *result = *first;
        ++first;
        ++result;
    }
    return result;
}

/**
 * Replacement for std::fill(..)
 */
template <typename ForwardIt, typename T>
UAVCAN_EXPORT
void fill(ForwardIt first, ForwardIt last, const T& value)
{
    while (first != last)
    {
        *first = value;
        ++first;
    }
}

/**
 * Replacement for std::fill_n(..)
 */
template<typename OutputIt, typename T>
UAVCAN_EXPORT
void fill_n(OutputIt first, std::size_t n, const T& value)
{
    while (n--)
    {
        *first++ = value;
    }
}

/**
 * Replacement for std::min(..)
 */
template <typename T>
UAVCAN_EXPORT
const T& min(const T& a, const T& b)
{
    return (b < a) ? b : a;
}

/**
 * Replacement for std::max(..)
 */
template <typename T>
UAVCAN_EXPORT
const T& max(const T& a, const T& b)
{
    return (a < b) ? b : a;
}

/**
 * Replacement for std::lexicographical_compare(..)
 */
template<typename InputIt1, typename InputIt2>
UAVCAN_EXPORT
bool lexicographical_compare(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
{
    while ((first1 != last1) && (first2 != last2))
    {
        if (*first1 < *first2)
        {
            return true;
        }
        if (*first2 < *first1)
        {
            return false;
        }
        ++first1;
        ++first2;
    }
    return (first1 == last1) && (first2 != last2);
}

/**
 * Replacement for std::equal(..)
 */
template<typename InputIt1, typename InputIt2>
UAVCAN_EXPORT
bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
{
    while (first1 != last1)
    {
        if (*first1 != *first2)
        {
            return false;
        }
        ++first1;
        ++first2;
    }
    return true;
}

/**
 * Numeric traits, like std::numeric_limits<>
 */
template <typename T>
struct UAVCAN_EXPORT NumericTraits;

/// char
template <>
struct UAVCAN_EXPORT NumericTraits<char>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 1 };
    static char max() { return CHAR_MAX; }
    static char min() { return CHAR_MIN; }
};
template <>
struct UAVCAN_EXPORT NumericTraits<signed char>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 1 };
    static signed char max() { return SCHAR_MAX; }
    static signed char min() { return SCHAR_MIN; }
};
template <>
struct UAVCAN_EXPORT NumericTraits<unsigned char>
{
    enum { IsSigned = 0 };
    enum { IsInteger = 1 };
    static unsigned char max() { return UCHAR_MAX; }
    static unsigned char min() { return 0; }
};

/// short
template <>
struct UAVCAN_EXPORT NumericTraits<short>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 1 };
    static short max() { return SHRT_MAX; }
    static short min() { return SHRT_MIN; }
};
template <>
struct UAVCAN_EXPORT NumericTraits<unsigned short>
{
    enum { IsSigned = 0 };
    enum { IsInteger = 1 };
    static unsigned short max() { return USHRT_MAX; }
    static unsigned short min() { return 0; }
};

/// int
template <>
struct UAVCAN_EXPORT NumericTraits<int>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 1 };
    static int max() { return INT_MAX; }
    static int min() { return INT_MIN; }
};
template <>
struct UAVCAN_EXPORT NumericTraits<unsigned int>
{
    enum { IsSigned = 0 };
    enum { IsInteger = 1 };
    static unsigned int max() { return UINT_MAX; }
    static unsigned int min() { return 0; }
};

/// long
template <>
struct UAVCAN_EXPORT NumericTraits<long>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 1 };
    static long max() { return LONG_MAX; }
    static long min() { return LONG_MIN; }
};
template <>
struct UAVCAN_EXPORT NumericTraits<unsigned long>
{
    enum { IsSigned = 0 };
    enum { IsInteger = 1 };
    static unsigned long max() { return ULONG_MAX; }
    static unsigned long min() { return 0; }
};

/// long long
template <>
struct UAVCAN_EXPORT NumericTraits<long long>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 1 };
    static long long max() { return LLONG_MAX; }
    static long long min() { return LLONG_MIN; }
};
template <>
struct UAVCAN_EXPORT NumericTraits<unsigned long long>
{
    enum { IsSigned = 0 };
    enum { IsInteger = 1 };
    static unsigned long long max() { return ULLONG_MAX; }
    static unsigned long long min() { return 0; }
};

/// float
template <>
struct UAVCAN_EXPORT NumericTraits<float>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 0 };
    static float max() { return FLT_MAX; }
    static float min() { return FLT_MIN; }
    static float infinity() { return INFINITY; }
    static float epsilon() { return FLT_EPSILON; }
};

/// double
template <>
struct UAVCAN_EXPORT NumericTraits<double>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 0 };
    static double max() { return DBL_MAX; }
    static double min() { return DBL_MIN; }
    static double infinity() { return static_cast<double>(INFINITY) * static_cast<double>(INFINITY); }
    static double epsilon() { return DBL_EPSILON; }
};

#if defined(LDBL_MAX) && defined(LDBL_MIN) && defined(LDBL_EPSILON)
/// long double
template <>
struct UAVCAN_EXPORT NumericTraits<long double>
{
    enum { IsSigned = 1 };
    enum { IsInteger = 0 };
    static long double max() { return LDBL_MAX; }
    static long double min() { return LDBL_MIN; }
    static long double infinity() { return static_cast<long double>(INFINITY) * static_cast<long double>(INFINITY); }
    static long double epsilon() { return LDBL_EPSILON; }
};
#endif

#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
# undef isnan
# undef isinf
# undef signbit
#endif

/**
 * Replacement for std::isnan().
 * Note that direct float comparison (==, !=) is intentionally avoided.
 */
template <typename T>
inline bool isNaN(T arg)
{
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
    return std::isnan(arg);
#else
    // coverity[same_on_both_sides : FALSE]
    // cppcheck-suppress duplicateExpression
    return !(arg <= arg);
#endif
}

/**
 * Replacement for std::isinf().
 * Note that direct float comparison (==, !=) is intentionally avoided.
 */
template <typename T>
inline bool isInfinity(T arg)
{
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
    return std::isinf(arg);
#else
    return (arg >= NumericTraits<T>::infinity()) || (arg <= -NumericTraits<T>::infinity());
#endif
}

/**
 * Replacement for std::signbit().
 * Note that direct float comparison (==, !=) is intentionally avoided.
 */
template <typename T>
inline bool getSignBit(T arg)
{
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
    return std::signbit(arg);
#else
    return arg < T(0) || (((arg <= T(0)) && (arg >= T(0))) && (T(1) / arg < T(0)));
#endif
}

}
<|endoftext|>