<commit_before>#pragma once

#include <coffee/components/entity_container.h>
#include <coffee/components/entity_reference.h>
#include <coffee/components/service_query.h>
#include <coffee/components/visitor.h>

namespace Coffee {
namespace Components {

namespace detail {

using node_id = size_t;

extern void expand_neighbor_matrix(
    Vector<bool>& matrix, size_t size, node_id current_node);

FORCEDINLINE EntityContainer::visitor_graph create_visitor_graph(
    Vector<UqPtr<EntityVisitorBase>> const& visitors)
{
    Map<type_hash, Vector<node_id>> buckets;

    /* Add visitors to buckets */
    node_id idx = 0;
    for(auto const& visitor : visitors)
    {
        for(auto const& component : visitor->components)
            buckets[component].push_back(idx);

        idx++;
    }

    auto         neigh_size = visitors.size();
    Vector<bool> neighbor_matrix;
    neighbor_matrix.resize(visitors.size() * visitors.size());

    /* Create a neighbor matrix for the nodes */
    for(auto const& bucket : buckets)
    {
        /* TODO: Handle visitors with exclusive access */
        if(bucket.second.size() < 2)
        {
            auto node_idx = bucket.second.at(0);
            neighbor_matrix.at(neigh_size * node_idx + node_idx) = true;
            continue;
        }

        auto start = bucket.second.begin();
        auto it1   = start;
        auto it2   = start + 1;

        for(; it2 != bucket.second.end(); it1++, it2++)
        {
            auto x = C_FCAST<size_t>(it1 - start);
            auto y = C_FCAST<size_t>(it2 - start);

            bool val = true;

            auto coord1 = neigh_size * y + x;
            auto coord2 = neigh_size * x + y;

            neighbor_matrix.at(coord1) = neighbor_matrix.at(coord1) | val;
            neighbor_matrix.at(coord2) = neighbor_matrix.at(coord2) | val;
        }
    }

    /* Connect all nodes that run on main thread, grouping them together */
    {
        auto const is_mainthread = [](UqPtr<EntityVisitorBase> const& p) {
            return (p->flags & VisitorFlags::MainThread) ==
                   VisitorFlags::MainThread;
        };

        auto start = visitors.begin();

        auto it1 = std::find_if(start, visitors.end(), is_mainthread);

        while(it1 != visitors.end())
        {
            auto new_start = it1 + 1;
            auto it2 = std::find_if(new_start, visitors.end(), is_mainthread);

#if MODE_DEBUG
            if(it1 == it2)
                Throw(undefined_behavior("incorrect grouping"));
#endif
            if(it2 == visitors.end())
                break;

            auto x = C_FCAST<size_t>(it1 - start);
            auto y = C_FCAST<size_t>(it2 - start);

            neighbor_matrix.at(neigh_size * y + x) = true;
            neighbor_matrix.at(neigh_size * x + y) = true;

            it1 = it2;
        }
    }

    /* Expand neighbor matrix completely */
    for(auto i : Range<>(neigh_size))
        expand_neighbor_matrix(neighbor_matrix, neigh_size, i);

    /* De-duplicate neighbor matrix rows to create task queues */
    Set<Vector<bool>> unique_rows;
    for(auto i : Range<>(neigh_size))
    {
        unique_rows.insert(Vector<bool>(
            neighbor_matrix.begin() + C_FCAST<ssize_t>(neigh_size * i),
            neighbor_matrix.begin() + C_FCAST<ssize_t>(neigh_size * (i + 1))));
    }

    return unique_rows;
}

} // namespace detail

FORCEDINLINE
void EntityContainer::exec()
{
    time_point     time_now = clock::now();
    ContainerProxy proxy(*this);

    for(auto& subsys : subsystems)
        subsys.second->start_frame(proxy, time_now);

    /* TODO: Put visitors in buckets according to what data they access */
    for(auto const& visitor : visitors)
    {
        visitor->dispatch(*this, time_now);
    }

    for(auto& subsys : subsystems)
        subsys.second->end_frame(proxy, time_now);
}

FORCEDINLINE EntityContainer::visitor_graph EntityContainer::create_task_graph()
{
    return detail::create_visitor_graph(visitors);
}

template<typename ComponentType>
FORCEDINLINE void EntityContainer::register_component(
    UqPtr<ComponentContainer<ComponentType>>&& c)
{
    static const type_hash type_id = typeid(ComponentType).hash_code();

    if(components.find(type_id) != components.end())
        Throw(implementation_error("cannot register type twice"));

    auto adapted = C_DCAST<ComponentContainerBase>(c.get());

    if(C_RCAST<void*>(adapted) != C_RCAST<void*>(c.get()))
        Throw(implementation_error("pointer casts will fail"));

    components.emplace(type_id, std::move(c));
}

#if MODE_DEBUG
template<typename ServiceType, typename SubsystemType>
struct service_test
{
    template<typename T>
    struct dynamic_test
    {
        void operator()(SubsystemType* sub)
        {
            C_PTR_CHECK_MSG(
                C_DCAST<typename T::type>(sub), "service cast mismatch");
        }
    };

    void check_subsystems(SubsystemType* sub)
    {
        type_list::for_each<typename ServiceType::services, dynamic_test>(sub);
    }
};
#endif

template<typename ServiceType, typename SubsystemType>
void EntityContainer::register_subsystem_services(SubsystemType* subsystem)
{
    static_assert(std::is_same<type_hash, size_t>::value, "Mismatched types");

    auto types = type_list::collect_list<typename ServiceType::services>();

#if MODE_DEBUG
    service_test<ServiceType, SubsystemType>().check_subsystems(subsystem);
#endif

    for(type_hash v : types)
    {
        services.insert({v, subsystem});
    }
}

FORCEDINLINE EntityRef<EntityContainer> EntityContainer::ref(Entity& entity)
{
    return EntityRef<EntityContainer>(entity.id, this);
}

FORCEDINLINE EntityRef<EntityContainer> EntityContainer::ref(u64 entity)
{
    return EntityRef<EntityContainer>(entity, this);
}

template<typename ComponentTag>
ComponentRef<EntityContainer, ComponentTag> EntityContainer::ref_comp(
    u64 entity)
{
    return ComponentRef<EntityContainer, ComponentTag>(entity, this);
}

template<typename Service>
ServiceRef<Service> EntityContainer::service_ref()
{
    return ServiceRef<Service>(this);
}

template<class BaseType>
quick_container<service_query<BaseType>> EntityContainer::services_with()
{
    using query_type = service_query<BaseType>;

    return {[this]() {
                return query_type(
                    *this, typename query_type::begin_iterator_t());
            },
            [this]() {
                return query_type(*this, typename query_type::end_iterator_t());
            }};
}

inline EntityContainer& SubsystemBase::get_container(
    SubsystemBase::ContainerProxy& proxy)
{
    return proxy.m_container;
}

} // namespace Components
} // namespace Coffee
<commit_msg> - Change inline qualifier to FORCEDINLINE<commit_after>#pragma once

#include <coffee/components/entity_container.h>
#include <coffee/components/entity_reference.h>
#include <coffee/components/service_query.h>
#include <coffee/components/visitor.h>

namespace Coffee {
namespace Components {

namespace detail {

using node_id = size_t;

extern void expand_neighbor_matrix(
    Vector<bool>& matrix, size_t size, node_id current_node);

FORCEDINLINE EntityContainer::visitor_graph create_visitor_graph(
    Vector<UqPtr<EntityVisitorBase>> const& visitors)
{
    Map<type_hash, Vector<node_id>> buckets;

    /* Add visitors to buckets */
    node_id idx = 0;
    for(auto const& visitor : visitors)
    {
        for(auto const& component : visitor->components)
            buckets[component].push_back(idx);

        idx++;
    }

    auto         neigh_size = visitors.size();
    Vector<bool> neighbor_matrix;
    neighbor_matrix.resize(visitors.size() * visitors.size());

    /* Create a neighbor matrix for the nodes */
    for(auto const& bucket : buckets)
    {
        /* TODO: Handle visitors with exclusive access */
        if(bucket.second.size() < 2)
        {
            auto node_idx = bucket.second.at(0);
            neighbor_matrix.at(neigh_size * node_idx + node_idx) = true;
            continue;
        }

        auto start = bucket.second.begin();
        auto it1   = start;
        auto it2   = start + 1;

        for(; it2 != bucket.second.end(); it1++, it2++)
        {
            auto x = C_FCAST<size_t>(it1 - start);
            auto y = C_FCAST<size_t>(it2 - start);

            bool val = true;

            auto coord1 = neigh_size * y + x;
            auto coord2 = neigh_size * x + y;

            neighbor_matrix.at(coord1) = neighbor_matrix.at(coord1) | val;
            neighbor_matrix.at(coord2) = neighbor_matrix.at(coord2) | val;
        }
    }

    /* Connect all nodes that run on main thread, grouping them together */
    {
        auto const is_mainthread = [](UqPtr<EntityVisitorBase> const& p) {
            return (p->flags & VisitorFlags::MainThread) ==
                   VisitorFlags::MainThread;
        };

        auto start = visitors.begin();

        auto it1 = std::find_if(start, visitors.end(), is_mainthread);

        while(it1 != visitors.end())
        {
            auto new_start = it1 + 1;
            auto it2 = std::find_if(new_start, visitors.end(), is_mainthread);

#if MODE_DEBUG
            if(it1 == it2)
                Throw(undefined_behavior("incorrect grouping"));
#endif
            if(it2 == visitors.end())
                break;

            auto x = C_FCAST<size_t>(it1 - start);
            auto y = C_FCAST<size_t>(it2 - start);

            neighbor_matrix.at(neigh_size * y + x) = true;
            neighbor_matrix.at(neigh_size * x + y) = true;

            it1 = it2;
        }
    }

    /* Expand neighbor matrix completely */
    for(auto i : Range<>(neigh_size))
        expand_neighbor_matrix(neighbor_matrix, neigh_size, i);

    /* De-duplicate neighbor matrix rows to create task queues */
    Set<Vector<bool>> unique_rows;
    for(auto i : Range<>(neigh_size))
    {
        unique_rows.insert(Vector<bool>(
            neighbor_matrix.begin() + C_FCAST<ssize_t>(neigh_size * i),
            neighbor_matrix.begin() + C_FCAST<ssize_t>(neigh_size * (i + 1))));
    }

    return unique_rows;
}

} // namespace detail

FORCEDINLINE
void EntityContainer::exec()
{
    time_point     time_now = clock::now();
    ContainerProxy proxy(*this);

    for(auto& subsys : subsystems)
        subsys.second->start_frame(proxy, time_now);

    /* TODO: Put visitors in buckets according to what data they access */
    for(auto const& visitor : visitors)
    {
        visitor->dispatch(*this, time_now);
    }

    for(auto& subsys : subsystems)
        subsys.second->end_frame(proxy, time_now);
}

FORCEDINLINE EntityContainer::visitor_graph EntityContainer::create_task_graph()
{
    return detail::create_visitor_graph(visitors);
}

template<typename ComponentType>
FORCEDINLINE void EntityContainer::register_component(
    UqPtr<ComponentContainer<ComponentType>>&& c)
{
    static const type_hash type_id = typeid(ComponentType).hash_code();

    if(components.find(type_id) != components.end())
        Throw(implementation_error("cannot register type twice"));

    auto adapted = C_DCAST<ComponentContainerBase>(c.get());

    if(C_RCAST<void*>(adapted) != C_RCAST<void*>(c.get()))
        Throw(implementation_error("pointer casts will fail"));

    components.emplace(type_id, std::move(c));
}

#if MODE_DEBUG
template<typename ServiceType, typename SubsystemType>
struct service_test
{
    template<typename T>
    struct dynamic_test
    {
        void operator()(SubsystemType* sub)
        {
            C_PTR_CHECK_MSG(
                C_DCAST<typename T::type>(sub), "service cast mismatch");
        }
    };

    void check_subsystems(SubsystemType* sub)
    {
        type_list::for_each<typename ServiceType::services, dynamic_test>(sub);
    }
};
#endif

template<typename ServiceType, typename SubsystemType>
void EntityContainer::register_subsystem_services(SubsystemType* subsystem)
{
    static_assert(std::is_same<type_hash, size_t>::value, "Mismatched types");

    auto types = type_list::collect_list<typename ServiceType::services>();

#if MODE_DEBUG
    service_test<ServiceType, SubsystemType>().check_subsystems(subsystem);
#endif

    for(type_hash v : types)
    {
        services.insert({v, subsystem});
    }
}

FORCEDINLINE EntityRef<EntityContainer> EntityContainer::ref(Entity& entity)
{
    return EntityRef<EntityContainer>(entity.id, this);
}

FORCEDINLINE EntityRef<EntityContainer> EntityContainer::ref(u64 entity)
{
    return EntityRef<EntityContainer>(entity, this);
}

template<typename ComponentTag>
ComponentRef<EntityContainer, ComponentTag> EntityContainer::ref_comp(
    u64 entity)
{
    return ComponentRef<EntityContainer, ComponentTag>(entity, this);
}

template<typename Service>
ServiceRef<Service> EntityContainer::service_ref()
{
    return ServiceRef<Service>(this);
}

template<class BaseType>
quick_container<service_query<BaseType>> EntityContainer::services_with()
{
    using query_type = service_query<BaseType>;

    return {[this]() {
                return query_type(
                    *this, typename query_type::begin_iterator_t());
            },
            [this]() {
                return query_type(*this, typename query_type::end_iterator_t());
            }};
}

FORCEDINLINE EntityContainer& SubsystemBase::get_container(
    SubsystemBase::ContainerProxy& proxy)
{
    return proxy.m_container;
}

} // namespace Components
} // namespace Coffee
<|endoftext|>


<commit_before>/*            __ __                                                     *\
**     __    /_// /  ___            lila API                            **
**    / /   __ / /  / _ |           (c) 2016, Christian Krause          **
**   / /__ / // /__/ __ |                                               **
**  /____//_//____/_/ | |                                               **
\*                    |/                                                */

#include "lexer.hpp"

namespace lila {
  namespace lexer {

    int tokenize(basic_istream<char>* is, vector<unique_ptr<Token>>* tokens) {
      char c;

      while (is->get(c)) {
        if (isspace(c))
          continue;

        if (isdigit(c)) { // Number: [0-9]+
          string number;

          do {
            number += c;
            is->get(c);
          } while (isdigit(c));

          double value = strtod(number.c_str(), nullptr);
          auto numberToken = llvm::make_unique<NumberToken>(value);
          tokens->push_back(move(numberToken));

        } else { // other token
          string str;

          do {
            str += c;
            is->get(c);
          } while (!isspace(c));

          auto otherToken = llvm::make_unique<OtherToken>(str);
          tokens->push_back(move(otherToken));
        }
      }

      return 0;
    }

  }
}
<commit_msg>improve lexer end of stream handling<commit_after>/*            __ __                                                     *\
**     __    /_// /  ___            lila API                            **
**    / /   __ / /  / _ |           (c) 2016, Christian Krause          **
**   / /__ / // /__/ __ |                                               **
**  /____//_//____/_/ | |                                               **
\*                    |/                                                */

#include "lexer.hpp"

namespace lila {
  namespace lexer {

    int tokenize(basic_istream<char>* is, vector<unique_ptr<Token>>* tokens) {
      char c;

      while (is && is->get(c)) {
        if (isspace(c))
          continue;

        if (isdigit(c)) { // Number: [0-9]+
          string number;
          number += c;

          while (is && is->get(c) && isdigit(c))
            number += c;

          double value = strtod(number.c_str(), nullptr);
          auto numberToken = llvm::make_unique<NumberToken>(value);
          tokens->push_back(move(numberToken));

        } else { // other token
          string str;
          str += c;

          while (is && is->get(c) && !isspace(c))
            str += c;

          auto otherToken = llvm::make_unique<OtherToken>(str);
          tokens->push_back(move(otherToken));
        }
      }

      return 0;
    }

  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014, Ford Motor Company
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following
 * disclaimer in the documentation and/or other materials provided with the
 * distribution.
 *
 * Neither the name of the Ford Motor Company nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <sstream>

#include "transport_manager/transport_adapter/transport_adapter_impl.h"
#include "transport_manager/usb/usb_device_scanner.h"
#include "transport_manager/usb/usb_device.h"
#include "transport_manager/usb/common.h"

#include "utils/logger.h"

namespace transport_manager {
namespace transport_adapter {

CREATE_LOGGERPTR_GLOBAL(logger_, "UsbDeviceScanner")

class AoaInitSequence : public UsbControlTransferSequence {
 public:
  AoaInitSequence();
  virtual ~AoaInitSequence() {
  }

 private:
  class AoaGetProtocolRequest;
  class AoaSendIdString;
  class AoaTurnIntoAccessoryMode;
};

void UsbDeviceScanner::OnDeviceArrived(PlatformUsbDevice* device) {
  LOG4CXX_AUTO_TRACE(logger_);
  if (IsAppleDevice(device)) {
    SupportedDeviceFound(device);
  } else {
    if (IsGoogleAccessory(device)) {
      SupportedDeviceFound(device);
    } else {
      TurnIntoAccessoryMode(device);
    }
  }
}

void UsbDeviceScanner::OnDeviceLeft(PlatformUsbDevice* device) {
  LOG4CXX_AUTO_TRACE(logger_);
  LOG4CXX_DEBUG(logger_, "PlatformUsbDevice " << device);
  bool list_changed = false;
  devices_mutex_.Acquire();
  for (Devices::iterator it = devices_.begin(); it != devices_.end(); ++it) {
    if (device == *it) {
      devices_.erase(it);
      list_changed = true;
      break;
    }
  }
  devices_mutex_.Release();
  if (list_changed) {
    UpdateList();
  }
}

UsbDeviceScanner::UsbDeviceScanner(TransportAdapterController* controller)
    : controller_(controller) {
}

UsbDeviceScanner::~UsbDeviceScanner() {
}

class AoaInitSequence::AoaGetProtocolRequest : public UsbControlInTransfer {
  virtual ~AoaGetProtocolRequest() {
  }
  virtual RequestType Type() const {
    return VENDOR;
  }
  virtual uint8_t Request() const {
    return 51;
  }
  virtual uint16_t Value() const {
    return 0;
  }
  virtual uint16_t Index() const {
    return 0;
  }
  virtual uint16_t Length() const {
    return 2;
  }
  virtual bool OnCompleted(unsigned char* data) const {
    const int protocol_version = data[1] << 8 | data[0];
    LOG4CXX_DEBUG(logger_, "AOA protocol version " << protocol_version);
    if (protocol_version == 0) {
      // AOA protocol not supported
      return false;
    }
    return true;
  }
};

class AoaInitSequence::AoaSendIdString : public UsbControlOutTransfer {
 public:
  AoaSendIdString(uint16_t index, const char* string, uint16_t length)
      : index_(index),
        string_(string),
        length_(length) {
  }

 private:
  virtual ~AoaSendIdString() {
  }
  virtual RequestType Type() const {
    return VENDOR;
  }
  virtual uint8_t Request() const {
    return 52;
  }
  virtual uint16_t Value() const {
    return 0;
  }
  virtual uint16_t Index() const {
    return index_;
  }
  virtual uint16_t Length() const {
    return length_;
  }
  virtual const char* Data() const {
    return string_;
  }
  uint16_t index_;
  const char* string_;
  uint16_t length_;
};

class AoaInitSequence::AoaTurnIntoAccessoryMode : public UsbControlOutTransfer {
  virtual ~AoaTurnIntoAccessoryMode() {
  }
  virtual RequestType Type() const {
    return VENDOR;
  }
  virtual uint8_t Request() const {
    return 53;
  }
  virtual uint16_t Value() const {
    return 0;
  }
  virtual uint16_t Index() const {
    return 0;
  }
  virtual uint16_t Length() const {
    return 0;
  }
  virtual const char* Data() const {
    return 0;
  }
};

#ifdef MODIFY_FUNCTION_SIGN
static char manufacturer[] = "Ford";
static char model_name[] = "HMI";
static char description[] = "Human machine interface";
static char version[] = "1.0";
static char uri[] = "http://www.ford.com";
static char serial_num[] = "N000000";
#else
static char manufacturer[] = "SDL";
static char model_name[] = "Core";
static char description[] = "SmartDeviceLink Core Component USB";
static char version[] = "1.0";
static char uri[] = "http://www.smartdevicelink.org";
static char serial_num[] = "N000000";
#endif

AoaInitSequence::AoaInitSequence()
    : UsbControlTransferSequence() {
  AddTransfer(new AoaGetProtocolRequest);
  AddTransfer(new AoaSendIdString(0, manufacturer, sizeof(manufacturer)));
  AddTransfer(new AoaSendIdString(1, model_name, sizeof(model_name)));
  AddTransfer(new AoaSendIdString(2, description, sizeof(description)));
  AddTransfer(new AoaSendIdString(3, version, sizeof(version)));
  AddTransfer(new AoaSendIdString(4, uri, sizeof(uri)));
  AddTransfer(new AoaSendIdString(5, serial_num, sizeof(serial_num)));
  AddTransfer(new AoaTurnIntoAccessoryMode);
}

void UsbDeviceScanner::TurnIntoAccessoryMode(PlatformUsbDevice* device) {
  LOG4CXX_AUTO_TRACE(logger_);
  LOG4CXX_DEBUG(logger_, "PlatformUsbDevice: " << device);
  GetUsbHandler()->StartControlTransferSequence(new AoaInitSequence, device);
}

void UsbDeviceScanner::SupportedDeviceFound(PlatformUsbDevice* device) {
  LOG4CXX_AUTO_TRACE(logger_);
  LOG4CXX_TRACE(logger_, "PlatformUsbDevice: " << device);

  devices_mutex_.Acquire();
  devices_.push_back(device);
  devices_mutex_.Release();
  LOG4CXX_DEBUG(
      logger_,
      "USB device (bus number " << static_cast<int>(device->bus_number())
      << ", address " << static_cast<int>(device->address())
      << ") identified as: " << device->GetManufacturer()
      << ", " << device->GetProductName()
      << ", serial: " << device->GetSerialNumber());
  UpdateList();
}

TransportAdapter::Error UsbDeviceScanner::Init() {
  return TransportAdapter::OK;
}

TransportAdapter::Error UsbDeviceScanner::Scan() {
  return TransportAdapter::OK;
}

void UsbDeviceScanner::UpdateList() {
  LOG4CXX_AUTO_TRACE(logger_);
  DeviceVector device_vector;
  devices_mutex_.Acquire();
  for (Devices::const_iterator it = devices_.begin(); it != devices_.end();
      ++it) {
    const std::string device_name = (*it)->GetManufacturer() + " "
        + (*it)->GetProductName();
    std::ostringstream oss;
    oss << (*it)->GetManufacturer() << ":" << (*it)->GetProductName() << ":"
        << (*it)->GetSerialNumber();
    const DeviceUID device_uid = oss.str();
    DeviceSptr device(new UsbDevice(*it, device_name, device_uid));
    device_vector.push_back(device);
  }
  devices_mutex_.Release();

  LOG4CXX_DEBUG(logger_, "USB search done " << device_vector.size());
  controller_->SearchDeviceDone(device_vector);
}

void UsbDeviceScanner::Terminate() {
}

bool UsbDeviceScanner::IsInitialised() const {
  return true;
}

}  // namespace
}  // namespace
<commit_msg>Revert to use 'SyncProxyTester 4.0'.<commit_after>/*
 * Copyright (c) 2014, Ford Motor Company
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following
 * disclaimer in the documentation and/or other materials provided with the
 * distribution.
 *
 * Neither the name of the Ford Motor Company nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <sstream>

#include "transport_manager/transport_adapter/transport_adapter_impl.h"
#include "transport_manager/usb/usb_device_scanner.h"
#include "transport_manager/usb/usb_device.h"
#include "transport_manager/usb/common.h"

#include "utils/logger.h"

namespace transport_manager {
namespace transport_adapter {

CREATE_LOGGERPTR_GLOBAL(logger_, "UsbDeviceScanner")

class AoaInitSequence : public UsbControlTransferSequence {
 public:
  AoaInitSequence();
  virtual ~AoaInitSequence() {
  }

 private:
  class AoaGetProtocolRequest;
  class AoaSendIdString;
  class AoaTurnIntoAccessoryMode;
};

void UsbDeviceScanner::OnDeviceArrived(PlatformUsbDevice* device) {
  LOG4CXX_AUTO_TRACE(logger_);
  if (IsAppleDevice(device)) {
    SupportedDeviceFound(device);
  } else {
    if (IsGoogleAccessory(device)) {
      SupportedDeviceFound(device);
    } else {
      TurnIntoAccessoryMode(device);
    }
  }
}

void UsbDeviceScanner::OnDeviceLeft(PlatformUsbDevice* device) {
  LOG4CXX_AUTO_TRACE(logger_);
  LOG4CXX_DEBUG(logger_, "PlatformUsbDevice " << device);
  bool list_changed = false;
  devices_mutex_.Acquire();
  for (Devices::iterator it = devices_.begin(); it != devices_.end(); ++it) {
    if (device == *it) {
      devices_.erase(it);
      list_changed = true;
      break;
    }
  }
  devices_mutex_.Release();
  if (list_changed) {
    UpdateList();
  }
}

UsbDeviceScanner::UsbDeviceScanner(TransportAdapterController* controller)
    : controller_(controller) {
}

UsbDeviceScanner::~UsbDeviceScanner() {
}

class AoaInitSequence::AoaGetProtocolRequest : public UsbControlInTransfer {
  virtual ~AoaGetProtocolRequest() {
  }
  virtual RequestType Type() const {
    return VENDOR;
  }
  virtual uint8_t Request() const {
    return 51;
  }
  virtual uint16_t Value() const {
    return 0;
  }
  virtual uint16_t Index() const {
    return 0;
  }
  virtual uint16_t Length() const {
    return 2;
  }
  virtual bool OnCompleted(unsigned char* data) const {
    const int protocol_version = data[1] << 8 | data[0];
    LOG4CXX_DEBUG(logger_, "AOA protocol version " << protocol_version);
    if (protocol_version == 0) {
      // AOA protocol not supported
      return false;
    }
    return true;
  }
};

class AoaInitSequence::AoaSendIdString : public UsbControlOutTransfer {
 public:
  AoaSendIdString(uint16_t index, const char* string, uint16_t length)
      : index_(index),
        string_(string),
        length_(length) {
  }

 private:
  virtual ~AoaSendIdString() {
  }
  virtual RequestType Type() const {
    return VENDOR;
  }
  virtual uint8_t Request() const {
    return 52;
  }
  virtual uint16_t Value() const {
    return 0;
  }
  virtual uint16_t Index() const {
    return index_;
  }
  virtual uint16_t Length() const {
    return length_;
  }
  virtual const char* Data() const {
    return string_;
  }
  uint16_t index_;
  const char* string_;
  uint16_t length_;
};

class AoaInitSequence::AoaTurnIntoAccessoryMode : public UsbControlOutTransfer {
  virtual ~AoaTurnIntoAccessoryMode() {
  }
  virtual RequestType Type() const {
    return VENDOR;
  }
  virtual uint8_t Request() const {
    return 53;
  }
  virtual uint16_t Value() const {
    return 0;
  }
  virtual uint16_t Index() const {
    return 0;
  }
  virtual uint16_t Length() const {
    return 0;
  }
  virtual const char* Data() const {
    return 0;
  }
};

static char manufacturer[] = "SDL";
static char model_name[] = "Core";
static char description[] = "SmartDeviceLink Core Component USB";
static char version[] = "1.0";
static char uri[] = "http://www.smartdevicelink.org";
static char serial_num[] = "N000000";

AoaInitSequence::AoaInitSequence()
    : UsbControlTransferSequence() {
  AddTransfer(new AoaGetProtocolRequest);
  AddTransfer(new AoaSendIdString(0, manufacturer, sizeof(manufacturer)));
  AddTransfer(new AoaSendIdString(1, model_name, sizeof(model_name)));
  AddTransfer(new AoaSendIdString(2, description, sizeof(description)));
  AddTransfer(new AoaSendIdString(3, version, sizeof(version)));
  AddTransfer(new AoaSendIdString(4, uri, sizeof(uri)));
  AddTransfer(new AoaSendIdString(5, serial_num, sizeof(serial_num)));
  AddTransfer(new AoaTurnIntoAccessoryMode);
}

void UsbDeviceScanner::TurnIntoAccessoryMode(PlatformUsbDevice* device) {
  LOG4CXX_AUTO_TRACE(logger_);
  LOG4CXX_DEBUG(logger_, "PlatformUsbDevice: " << device);
  GetUsbHandler()->StartControlTransferSequence(new AoaInitSequence, device);
}

void UsbDeviceScanner::SupportedDeviceFound(PlatformUsbDevice* device) {
  LOG4CXX_AUTO_TRACE(logger_);
  LOG4CXX_TRACE(logger_, "PlatformUsbDevice: " << device);

  devices_mutex_.Acquire();
  devices_.push_back(device);
  devices_mutex_.Release();
  LOG4CXX_DEBUG(
      logger_,
      "USB device (bus number " << static_cast<int>(device->bus_number())
      << ", address " << static_cast<int>(device->address())
      << ") identified as: " << device->GetManufacturer()
      << ", " << device->GetProductName()
      << ", serial: " << device->GetSerialNumber());
  UpdateList();
}

TransportAdapter::Error UsbDeviceScanner::Init() {
  return TransportAdapter::OK;
}

TransportAdapter::Error UsbDeviceScanner::Scan() {
  return TransportAdapter::OK;
}

void UsbDeviceScanner::UpdateList() {
  LOG4CXX_AUTO_TRACE(logger_);
  DeviceVector device_vector;
  devices_mutex_.Acquire();
  for (Devices::const_iterator it = devices_.begin(); it != devices_.end();
      ++it) {
    const std::string device_name = (*it)->GetManufacturer() + " "
        + (*it)->GetProductName();
    std::ostringstream oss;
    oss << (*it)->GetManufacturer() << ":" << (*it)->GetProductName() << ":"
        << (*it)->GetSerialNumber();
    const DeviceUID device_uid = oss.str();
    DeviceSptr device(new UsbDevice(*it, device_name, device_uid));
    device_vector.push_back(device);
  }
  devices_mutex_.Release();

  LOG4CXX_DEBUG(logger_, "USB search done " << device_vector.size());
  controller_->SearchDeviceDone(device_vector);
}

void UsbDeviceScanner::Terminate() {
}

bool UsbDeviceScanner::IsInitialised() const {
  return true;
}

}  // namespace
}  // namespace
<|endoftext|>


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

#include <gtest/gtest.h>

#include <memory>
#include <string>

#include "composition_interfaces/srv/load_node.hpp"
#include "composition_interfaces/srv/unload_node.hpp"
#include "composition_interfaces/srv/list_nodes.hpp"

#include "component_manager.hpp"

using namespace std::chrono_literals;

class TestComponentManager : public ::testing::Test
{
protected:
  static void SetUpTestCase()
  {
    rclcpp::init(0, nullptr);
  }
};

TEST_F(TestComponentManager, load_components)
{
  auto exec = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
  auto node = rclcpp::Node::make_shared("test_component_manager");
  auto manager = std::make_shared<rclcpp_components::ComponentManager>(exec);

  exec->add_node(manager);
  exec->add_node(node);

  auto client = node->create_client<composition_interfaces::srv::LoadNode>(
    "/ComponentManager/_container/load_node");

  if (!client->wait_for_service(20s)) {
    ASSERT_TRUE(false) << "service not available after waiting";
  }

  {
    auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
    request->package_name = "rclcpp_components";
    request->plugin_name = "test_rclcpp_components::TestComponentFoo";

    auto result = client->async_send_request(request);
    auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
    EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
    EXPECT_EQ(result.get()->success, true);
    EXPECT_EQ(result.get()->error_message, "");
    EXPECT_EQ(result.get()->full_node_name, "/test_component_foo");
    EXPECT_EQ(result.get()->unique_id, 1u);
  }

  {
    auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
    request->package_name = "rclcpp_components";
    request->plugin_name = "test_rclcpp_components::TestComponentBar";

    auto result = client->async_send_request(request);
    auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
    EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
    EXPECT_EQ(result.get()->success, true);
    EXPECT_EQ(result.get()->error_message, "");
    EXPECT_EQ(result.get()->full_node_name, "/test_component_bar");
    EXPECT_EQ(result.get()->unique_id, 2u);
  }

  // Test remapping the node name
  {
    auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
    request->package_name = "rclcpp_components";
    request->plugin_name = "test_rclcpp_components::TestComponentFoo";
    request->node_name = "test_component_baz";

    auto result = client->async_send_request(request);
    auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
    EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
    EXPECT_EQ(result.get()->success, true);
    EXPECT_EQ(result.get()->error_message, "");
    EXPECT_EQ(result.get()->full_node_name, "/test_component_baz");
    EXPECT_EQ(result.get()->unique_id, 3u);
  }

  // Test remapping the node namespace
  {
    auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
    request->package_name = "rclcpp_components";
    request->plugin_name = "test_rclcpp_components::TestComponentFoo";
    request->node_namespace = "/ns";
    request->node_name = "test_component_bing";

    auto result = client->async_send_request(request);
    auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
    EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
    EXPECT_EQ(result.get()->success, true);
    EXPECT_EQ(result.get()->error_message, "");
    EXPECT_EQ(result.get()->full_node_name, "/ns/test_component_bing");
    EXPECT_EQ(result.get()->unique_id, 4u);
  }

  auto node_names = node->get_node_names();

  auto find_in_nodes = [node_names](std::string name) {
      return std::find(node_names.begin(), node_names.end(), name) != node_names.end();
    };

  EXPECT_TRUE(find_in_nodes("/test_component_foo"));
  EXPECT_TRUE(find_in_nodes("/test_component_bar"));
  EXPECT_TRUE(find_in_nodes("/test_component_baz"));
  EXPECT_TRUE(find_in_nodes("/ns/test_component_bing"));
}

TEST_F(TestComponentManager, load_invalid_components)
{
  auto exec = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
  auto node = rclcpp::Node::make_shared("test_component_manager");
  auto manager = std::make_shared<rclcpp_components::ComponentManager>(exec);

  exec->add_node(manager);
  exec->add_node(node);

  auto client = node->create_client<composition_interfaces::srv::LoadNode>(
    "/ComponentManager/_container/load_node");

  if (!client->wait_for_service(20s)) {
    ASSERT_TRUE(false) << "service not available after waiting";
  }

  {
    // Valid package, but invalid class name.
    auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
    request->package_name = "rclcpp_components";
    request->plugin_name = "test_rclcpp_components::TestComponent";

    auto result = client->async_send_request(request);
    auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
    EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
    EXPECT_EQ(result.get()->success, false);
    EXPECT_EQ(result.get()->error_message, "Failed to find class with the requested plugin name.");
    EXPECT_EQ(result.get()->full_node_name, "");
    EXPECT_EQ(result.get()->unique_id, 0u);
  }

  {
    // Invalid package, but valid class name.
    auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
    request->package_name = "rclcpp_components_foo";
    request->plugin_name = "test_rclcpp_components::TestComponentFoo";

    auto result = client->async_send_request(request);
    auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
    EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
    EXPECT_EQ(result.get()->success, false);
    EXPECT_EQ(result.get()->error_message, "Could not find requested resource in ament index");
    EXPECT_EQ(result.get()->full_node_name, "");
    EXPECT_EQ(result.get()->unique_id, 0u);
  }
}

TEST_F(TestComponentManager, list_components)
{
  auto exec = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
  auto node = rclcpp::Node::make_shared("test_component_manager");
  auto manager = std::make_shared<rclcpp_components::ComponentManager>(exec);

  exec->add_node(manager);
  exec->add_node(node);

  {
    auto client = node->create_client<composition_interfaces::srv::LoadNode>(
      "/ComponentManager/_container/load_node");

    if (!client->wait_for_service(20s)) {
      ASSERT_TRUE(false) << "service not available after waiting";
    }

    {
      auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
      request->package_name = "rclcpp_components";
      request->plugin_name = "test_rclcpp_components::TestComponentFoo";

      auto result = client->async_send_request(request);
      auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
      EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
      EXPECT_EQ(result.get()->success, true);
      EXPECT_EQ(result.get()->error_message, "");
      EXPECT_EQ(result.get()->full_node_name, "/test_component_foo");
      EXPECT_EQ(result.get()->unique_id, 1u);
    }
  }

  {
    auto client = node->create_client<composition_interfaces::srv::ListNodes>(
      "/ComponentManager/_container/list_nodes");

    if (!client->wait_for_service(20s)) {
      ASSERT_TRUE(false) << "service not available after waiting";
    }

    {
      auto request = std::make_shared<composition_interfaces::srv::ListNodes::Request>();
      auto result = client->async_send_request(request);
      auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
      EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
      auto node_names = result.get()->full_node_names;
      auto unique_ids = result.get()->unique_ids;

      EXPECT_EQ(node_names.size(), 1u);
      EXPECT_EQ(node_names[0], "/test_component_foo");
      EXPECT_EQ(unique_ids.size(), 1u);
      EXPECT_EQ(unique_ids[0], 1u);
    }
  }
}

TEST_F(TestComponentManager, unload_component)
{
  auto exec = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
  auto node = rclcpp::Node::make_shared("test_component_manager");
  auto manager = std::make_shared<rclcpp_components::ComponentManager>(exec);

  exec->add_node(manager);
  exec->add_node(node);

  {
    auto client = node->create_client<composition_interfaces::srv::LoadNode>(
      "/ComponentManager/_container/load_node");

    if (!client->wait_for_service(20s)) {
      ASSERT_TRUE(false) << "service not available after waiting";
    }

    {
      auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
      request->package_name = "rclcpp_components";
      request->plugin_name = "test_rclcpp_components::TestComponentFoo";

      auto result = client->async_send_request(request);
      auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
      EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
      EXPECT_EQ(result.get()->success, true);
      EXPECT_EQ(result.get()->error_message, "");
      EXPECT_EQ(result.get()->full_node_name, "/test_component_foo");
      EXPECT_EQ(result.get()->unique_id, 1u);
    }
  }

  auto node_names = node->get_node_names();
  auto find_in_nodes = [node_names](std::string name) {
      return std::find(node_names.begin(), node_names.end(), name) != node_names.end();
    };
  EXPECT_TRUE(find_in_nodes("/test_component_foo"));

  {
    auto client = node->create_client<composition_interfaces::srv::UnloadNode>(
      "/ComponentManager/_container/unload_node");

    if (!client->wait_for_service(20s)) {
      ASSERT_TRUE(false) << "service not available after waiting";
    }

    {
      auto request = std::make_shared<composition_interfaces::srv::UnloadNode::Request>();
      request->unique_id = 1;

      auto result = client->async_send_request(request);
      auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
      EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
      EXPECT_EQ(result.get()->success, true);
      EXPECT_EQ(result.get()->error_message, "");
    }

    {
      auto request = std::make_shared<composition_interfaces::srv::UnloadNode::Request>();
      request->unique_id = 1;

      auto result = client->async_send_request(request);
      auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
      EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
      EXPECT_EQ(result.get()->success, false);
      EXPECT_EQ(result.get()->error_message, "No node found with unique_id: 1");
    }
  }
}
<commit_msg>Aggregate all component manager API tests. (#876)<commit_after>// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gtest/gtest.h>

#include <memory>
#include <string>

#include "composition_interfaces/srv/load_node.hpp"
#include "composition_interfaces/srv/unload_node.hpp"
#include "composition_interfaces/srv/list_nodes.hpp"

#include "component_manager.hpp"

using namespace std::chrono_literals;

class TestComponentManager : public ::testing::Test
{
protected:
  static void SetUpTestCase()
  {
    rclcpp::init(0, nullptr);
  }
};

// TODO(hidmic): split up tests once Node bring up/tear down races
//               are solved https://github.com/ros2/rclcpp/issues/863
TEST_F(TestComponentManager, components_api)
{
  auto exec = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
  auto node = rclcpp::Node::make_shared("test_component_manager");
  auto manager = std::make_shared<rclcpp_components::ComponentManager>(exec);

  exec->add_node(manager);
  exec->add_node(node);

  auto client = node->create_client<composition_interfaces::srv::LoadNode>(
    "/ComponentManager/_container/load_node");

  if (!client->wait_for_service(20s)) {
    ASSERT_TRUE(false) << "service not available after waiting";
  }

  {
    auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
    request->package_name = "rclcpp_components";
    request->plugin_name = "test_rclcpp_components::TestComponentFoo";

    auto result = client->async_send_request(request);
    auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
    EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
    EXPECT_EQ(result.get()->success, true);
    EXPECT_EQ(result.get()->error_message, "");
    EXPECT_EQ(result.get()->full_node_name, "/test_component_foo");
    EXPECT_EQ(result.get()->unique_id, 1u);
  }

  {
    auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
    request->package_name = "rclcpp_components";
    request->plugin_name = "test_rclcpp_components::TestComponentBar";

    auto result = client->async_send_request(request);
    auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
    EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
    EXPECT_EQ(result.get()->success, true);
    EXPECT_EQ(result.get()->error_message, "");
    EXPECT_EQ(result.get()->full_node_name, "/test_component_bar");
    EXPECT_EQ(result.get()->unique_id, 2u);
  }

  // Test remapping the node name
  {
    auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
    request->package_name = "rclcpp_components";
    request->plugin_name = "test_rclcpp_components::TestComponentFoo";
    request->node_name = "test_component_baz";

    auto result = client->async_send_request(request);
    auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
    EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
    EXPECT_EQ(result.get()->success, true);
    EXPECT_EQ(result.get()->error_message, "");
    EXPECT_EQ(result.get()->full_node_name, "/test_component_baz");
    EXPECT_EQ(result.get()->unique_id, 3u);
  }

  // Test remapping the node namespace
  {
    auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
    request->package_name = "rclcpp_components";
    request->plugin_name = "test_rclcpp_components::TestComponentFoo";
    request->node_namespace = "/ns";
    request->node_name = "test_component_bing";

    auto result = client->async_send_request(request);
    auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
    EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
    EXPECT_EQ(result.get()->success, true);
    EXPECT_EQ(result.get()->error_message, "");
    EXPECT_EQ(result.get()->full_node_name, "/ns/test_component_bing");
    EXPECT_EQ(result.get()->unique_id, 4u);
  }

  {
    // Valid package, but invalid class name.
    auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
    request->package_name = "rclcpp_components";
    request->plugin_name = "test_rclcpp_components::TestComponent";

    auto result = client->async_send_request(request);
    auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
    EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
    EXPECT_EQ(result.get()->success, false);
    EXPECT_EQ(result.get()->error_message, "Failed to find class with the requested plugin name.");
    EXPECT_EQ(result.get()->full_node_name, "");
    EXPECT_EQ(result.get()->unique_id, 0u);
  }

  {
    // Invalid package, but valid class name.
    auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
    request->package_name = "rclcpp_components_foo";
    request->plugin_name = "test_rclcpp_components::TestComponentFoo";

    auto result = client->async_send_request(request);
    auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
    EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
    EXPECT_EQ(result.get()->success, false);
    EXPECT_EQ(result.get()->error_message, "Could not find requested resource in ament index");
    EXPECT_EQ(result.get()->full_node_name, "");
    EXPECT_EQ(result.get()->unique_id, 0u);
  }

  auto node_names = node->get_node_names();

  auto find_in_nodes = [node_names](std::string name) {
      return std::find(node_names.begin(), node_names.end(), name) != node_names.end();
    };

  EXPECT_TRUE(find_in_nodes("/test_component_foo"));
  EXPECT_TRUE(find_in_nodes("/test_component_bar"));
  EXPECT_TRUE(find_in_nodes("/test_component_baz"));
  EXPECT_TRUE(find_in_nodes("/ns/test_component_bing"));

  {
    auto client = node->create_client<composition_interfaces::srv::ListNodes>(
      "/ComponentManager/_container/list_nodes");

    if (!client->wait_for_service(20s)) {
      ASSERT_TRUE(false) << "service not available after waiting";
    }

    {
      auto request = std::make_shared<composition_interfaces::srv::ListNodes::Request>();
      auto result = client->async_send_request(request);
      auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
      EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
      auto node_names = result.get()->full_node_names;
      auto unique_ids = result.get()->unique_ids;

      EXPECT_EQ(node_names.size(), 4u);
      EXPECT_EQ(node_names[0], "/test_component_foo");
      EXPECT_EQ(node_names[1], "/test_component_bar");
      EXPECT_EQ(node_names[2], "/test_component_baz");
      EXPECT_EQ(node_names[3], "/ns/test_component_bing");
      EXPECT_EQ(unique_ids.size(), 4u);
      EXPECT_EQ(unique_ids[0], 1u);
      EXPECT_EQ(unique_ids[1], 2u);
      EXPECT_EQ(unique_ids[2], 3u);
      EXPECT_EQ(unique_ids[3], 4u);
    }
  }

  {
    auto client = node->create_client<composition_interfaces::srv::UnloadNode>(
      "/ComponentManager/_container/unload_node");

    if (!client->wait_for_service(20s)) {
      ASSERT_TRUE(false) << "service not available after waiting";
    }

    {
      auto request = std::make_shared<composition_interfaces::srv::UnloadNode::Request>();
      request->unique_id = 1;

      auto result = client->async_send_request(request);
      auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
      EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
      EXPECT_EQ(result.get()->success, true);
      EXPECT_EQ(result.get()->error_message, "");
    }

    {
      auto request = std::make_shared<composition_interfaces::srv::UnloadNode::Request>();
      request->unique_id = 1;

      auto result = client->async_send_request(request);
      auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
      EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
      EXPECT_EQ(result.get()->success, false);
      EXPECT_EQ(result.get()->error_message, "No node found with unique_id: 1");
    }
  }

  {
    auto client = node->create_client<composition_interfaces::srv::ListNodes>(
      "/ComponentManager/_container/list_nodes");

    if (!client->wait_for_service(20s)) {
      ASSERT_TRUE(false) << "service not available after waiting";
    }

    {
      auto request = std::make_shared<composition_interfaces::srv::ListNodes::Request>();
      auto result = client->async_send_request(request);
      auto ret = exec->spin_until_future_complete(result, 5s);  // Wait for the result.
      EXPECT_EQ(ret, rclcpp::executor::FutureReturnCode::SUCCESS);
      auto node_names = result.get()->full_node_names;
      auto unique_ids = result.get()->unique_ids;

      EXPECT_EQ(node_names.size(), 3u);
      EXPECT_EQ(node_names[0], "/test_component_bar");
      EXPECT_EQ(node_names[1], "/test_component_baz");
      EXPECT_EQ(node_names[2], "/ns/test_component_bing");
      EXPECT_EQ(unique_ids.size(), 3u);
      EXPECT_EQ(unique_ids[0], 2u);
      EXPECT_EQ(unique_ids[1], 3u);
      EXPECT_EQ(unique_ids[2], 4u);
    }
  }
}
<|endoftext|>


<commit_before>#include "lexerTest.h"

#include <QtCore/QDebug>

#include <plugins/generationRulesTool/tokenTypes.h>

using namespace qrTest;

void LexerTest::SetUp() {
	mErrors.clear();
	mLexer.reset(new simpleParser::Lexer(mErrors));
}

void LexerTest::TearDown() {
	mErrors.clear();
}

TEST_F(LexerTest, lexerTestForForeachExample) {
	QString stream = "'enum State {'\n"
				"foreach (State) {\n"
				"State.name ',' \n"
				"newline \n"
				"} \n"
				"StartState.name ',' newline \n"
				"EndState.name newline \n"
				"'}' \n";

	auto lexerResult = mLexer->tokenize(stream);

	ASSERT_EQ(lexerResult.length(), 22);

	for (qrtext::core::Token<simpleParser::TokenTypes> token : lexerResult) {
		qDebug() << token.token();
	}

	EXPECT_EQ(simpleParser::TokenTypes::text, lexerResult[0].token());
	EXPECT_EQ(simpleParser::TokenTypes::foreachKeyword, lexerResult[1].token());
	EXPECT_EQ(simpleParser::TokenTypes::openingBracket, lexerResult[2].token());
	EXPECT_EQ(simpleParser::TokenTypes::identifier, lexerResult[3].token());
	EXPECT_EQ(simpleParser::TokenTypes::closingBracket, lexerResult[4].token());

	EXPECT_EQ(simpleParser::TokenTypes::openingCurlyBracket, lexerResult[5].token());
	EXPECT_EQ(simpleParser::TokenTypes::identifier, lexerResult[6].token());
	EXPECT_EQ(simpleParser::TokenTypes::dot, lexerResult[7].token());
	EXPECT_EQ(simpleParser::TokenTypes::identifier, lexerResult[8].token());
	EXPECT_EQ(simpleParser::TokenTypes::text, lexerResult[9].token());

	EXPECT_EQ(simpleParser::TokenTypes::newlineKeyword, lexerResult[10].token());
	EXPECT_EQ(simpleParser::TokenTypes::closingCurlyBracket, lexerResult[11].token());
	EXPECT_EQ(simpleParser::TokenTypes::identifier, lexerResult[12].token());
	EXPECT_EQ(simpleParser::TokenTypes::dot, lexerResult[13].token());
	EXPECT_EQ(simpleParser::TokenTypes::identifier, lexerResult[14].token());

	EXPECT_EQ(simpleParser::TokenTypes::text, lexerResult[15].token());
	EXPECT_EQ(simpleParser::TokenTypes::newlineKeyword, lexerResult[16].token());
	EXPECT_EQ(simpleParser::TokenTypes::identifier, lexerResult[17].token());
	EXPECT_EQ(simpleParser::TokenTypes::dot, lexerResult[18].token());
	EXPECT_EQ(simpleParser::TokenTypes::identifier, lexerResult[19].token());

	EXPECT_EQ(simpleParser::TokenTypes::newlineKeyword, lexerResult[20].token());
	EXPECT_EQ(simpleParser::TokenTypes::text, lexerResult[21].token());
}
<commit_msg>removed qDebug<commit_after>#include "lexerTest.h"

#include <plugins/generationRulesTool/tokenTypes.h>

using namespace qrTest;

void LexerTest::SetUp() {
	mErrors.clear();
	mLexer.reset(new simpleParser::Lexer(mErrors));
}

void LexerTest::TearDown() {
	mErrors.clear();
}

TEST_F(LexerTest, lexerTestForForeachExample) {
	QString stream = "'enum State {'\n"
				"foreach (State) {\n"
				"State.name ',' \n"
				"newline \n"
				"} \n"
				"StartState.name ',' newline \n"
				"EndState.name newline \n"
				"'}' \n";

	auto lexerResult = mLexer->tokenize(stream);

	ASSERT_EQ(lexerResult.length(), 22);

	EXPECT_EQ(simpleParser::TokenTypes::text, lexerResult[0].token());
	EXPECT_EQ(simpleParser::TokenTypes::foreachKeyword, lexerResult[1].token());
	EXPECT_EQ(simpleParser::TokenTypes::openingBracket, lexerResult[2].token());
	EXPECT_EQ(simpleParser::TokenTypes::identifier, lexerResult[3].token());
	EXPECT_EQ(simpleParser::TokenTypes::closingBracket, lexerResult[4].token());

	EXPECT_EQ(simpleParser::TokenTypes::openingCurlyBracket, lexerResult[5].token());
	EXPECT_EQ(simpleParser::TokenTypes::identifier, lexerResult[6].token());
	EXPECT_EQ(simpleParser::TokenTypes::dot, lexerResult[7].token());
	EXPECT_EQ(simpleParser::TokenTypes::identifier, lexerResult[8].token());
	EXPECT_EQ(simpleParser::TokenTypes::text, lexerResult[9].token());

	EXPECT_EQ(simpleParser::TokenTypes::newlineKeyword, lexerResult[10].token());
	EXPECT_EQ(simpleParser::TokenTypes::closingCurlyBracket, lexerResult[11].token());
	EXPECT_EQ(simpleParser::TokenTypes::identifier, lexerResult[12].token());
	EXPECT_EQ(simpleParser::TokenTypes::dot, lexerResult[13].token());
	EXPECT_EQ(simpleParser::TokenTypes::identifier, lexerResult[14].token());

	EXPECT_EQ(simpleParser::TokenTypes::text, lexerResult[15].token());
	EXPECT_EQ(simpleParser::TokenTypes::newlineKeyword, lexerResult[16].token());
	EXPECT_EQ(simpleParser::TokenTypes::identifier, lexerResult[17].token());
	EXPECT_EQ(simpleParser::TokenTypes::dot, lexerResult[18].token());
	EXPECT_EQ(simpleParser::TokenTypes::identifier, lexerResult[19].token());

	EXPECT_EQ(simpleParser::TokenTypes::newlineKeyword, lexerResult[20].token());
	EXPECT_EQ(simpleParser::TokenTypes::text, lexerResult[21].token());
}
<|endoftext|>


<commit_before>// stack.cpp : Defines the entry point for the console application.

#include "stdafx.h"
#include "stack.h"
#include <iostream>

using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
	char comm[6];
	char push[6] = "push";
	char pop[6] = "pop";
	char count[6] = "count";
	char stop[6] = "stop";
	stack<int> st;
	int num = 0;
	int top_value;
	cout << "commands" << endl;
	do
	{
		cin >> comm;
		if (!strcmp(comm, push))
		{
			cout << "enter number" << endl;
			cin >> num;
			st.push(num);
		}
		if (!strcmp(comm, pop))
		{
			try
			{
				top_value = st.pop();
				cout << top_value << endl;
			}
			catch (char *s)
			{
				cout << s << endl;
			}
		}
		if (!strcmp(comm, count))
		{
			cout << st.count() << endl;
		}

	} while (strcmp(comm, stop));
	system("pause");
	return 0;
}

<commit_msg>Update stack.cpp<commit_after>// stack.cpp : Defines the entry point for the console application.

//#include "stdafx.h"
#include "stack.h"
#include <iostream>

using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
	char comm[6];
	char push[6] = "push";
	char pop[6] = "pop";
	char count[6] = "count";
	char stop[6] = "stop";
	stack<int> st;
	int num = 0;
	int top_value;
	cout << "commands" << endl;
	do
	{
		cin >> comm;
		if (!strcmp(comm, push))
		{
			cout << "enter number" << endl;
			cin >> num;
			st.push(num);
		}
		if (!strcmp(comm, pop))
		{
			try
			{
				top_value = st.pop();
				cout << top_value << endl;
			}
			catch (char *s)
			{
				cout << s << endl;
			}
		}
		if (!strcmp(comm, count))
		{
			cout << st.count() << endl;
		}

	} while (strcmp(comm, stop));
	system("pause");
	return 0;
}

<|endoftext|>


<commit_before>/* banker_behaviour_test.cc
   Wolfgang Sourdeau, 20 December 2012
   Copyright (c) 2012 Datacratic Inc.  All rights reserved.

   Functional tests of the master and slave bankers
*/

#define BOOST_TEST_MAIN
#define BOOST_TEST_DYN_LINK

#include <unordered_set>

#include "boost/test/unit_test.hpp"
#include "jml/arch/format.h"

#include "soa/service/service_base.h"
#include "soa/service/testing/redis_temporary_server.h"
#include "soa/service/testing/zookeeper_temporary_server.h"

#include "rtbkit/core/banker/master_banker.h"
#include "rtbkit/core/banker/slave_banker.h"

#include "banker_temporary_server.h"

using namespace std;

using namespace Datacratic;
using namespace RTBKIT;
using namespace Redis;

namespace {

void
RedisReplyFillSetOfStrings(const Redis::Reply & reply,
                           unordered_set<string> & aSet) {
    ExcAssert(reply.type() == Redis::ARRAY);
    for (int i = 0; i < reply.length(); i++) {
        aSet.insert(reply[i].asString());
    }
}

}

/* make sure that requests from the slave banker are properly deferred when
 * the master banker is not available */
BOOST_AUTO_TEST_CASE( test_banker_deferred )
{
    ZooKeeper::TemporaryServer zookeeper;
    zookeeper.start();

    auto proxies = std::make_shared<ServiceProxies>();
    proxies->useZookeeper(ML::format("localhost:%d", zookeeper.getPort()));

    /* spawn slave */
    SlaveBanker slave(proxies->zmqContext);
    slave.init(proxies->config, "slave");
    slave.start();

    /* invoke addSpendAccount but wait 3 seconds before spawning master */
    int done(false);
    auto onSpendAdded = [&] (std::exception_ptr exc, ShadowAccount &&shadowAccount) {
        cerr << "(slave) onSpendAdded..." << endl;
        done = true;
        ML::futex_wake(done);
    };
    slave.addSpendAccount({"hello", "world"}, CurrencyPool(), onSpendAdded);
    ML::sleep(1);

    /* spawn master */
    RedisTemporaryServer redis;
    BankerTemporaryServer master(redis, ML::format("localhost:%d", zookeeper.getPort()));

    /* wait for the addSpendAccount op to complete */
    while (!done) {
        ML::futex_wait(done, false);
    }

    /* shut down the master banker now to force a write to redis */
    master.shutdown();

    /* check that "hello:world" has been saved */
    auto connection = std::make_shared<AsyncConnection>(redis);
    Redis::Result result = connection->exec(SMEMBERS("banker:accounts"), 5);
    BOOST_CHECK(result.ok());
    const Reply & keysReply = result.reply();
    unordered_set<string> keys;
    RedisReplyFillSetOfStrings(keysReply, keys);
    BOOST_CHECK_EQUAL(keys.count("hello:world"), 1);
}

/* make sure that the slave banker does create a spend account, even when a
 * "legacyImported" account exists */
BOOST_AUTO_TEST_CASE( test_banker_slave_banker_accounts )
{
    ZooKeeper::TemporaryServer zookeeper;
    zookeeper.start();

    auto proxies = std::make_shared<ServiceProxies>();
    proxies->useZookeeper(ML::format("localhost:%d", zookeeper.getPort()));

    /* spawn master */
    RedisTemporaryServer redis;

    /* create some initial accounts */
    {
        MasterBanker master(proxies, "initBanker");
        auto storage = make_shared<RedisBankerPersistence>(redis);
        master.init(storage);
        master.start();

        master.accounts.createAccount({"top"}, AT_BUDGET);
        master.accounts.setBudget({"top"}, MicroUSD(15729914170));
        master.accounts.setAvailable({"top", "sub"}, MicroUSD(11005485799),
                                     AT_BUDGET);
        master.accounts.setAvailable({"top", "sub", "legacyImported"},
                                     MicroUSD(10991979974),
                                     AT_SPEND);
        master.accounts.importSpend({"top", "sub", "legacyImported"},
                                    MicroUSD(10991979974));
        /* save the initial accounts state (the async save is guaranteed to
         * be over when "master" is destroyed) */
        master.saveState();
    }

    /* instantiate a slave and add a spend account from it */
    {
        /* spawn a master banker server process */
        BankerTemporaryServer master(redis, ML::format("localhost:%d", zookeeper.getPort()));

        /* spawn slave */
        SlaveBanker slave(proxies->zmqContext);
        slave.init(proxies->config, "slaveBanker");
        slave.start();

        slave.addSpendAccountSync({"top", "sub"});

        ML::sleep(2);
    }

    /* ensure that "top:sub:slaveBanker" has been created. If not, an
     * exception will be thrown. */
    {
        MasterBanker master(proxies, "initBanker2");
        auto storage = make_shared<RedisBankerPersistence>(redis);
        master.init(storage);
        master.start();
        auto account
            = master.accounts.getAccount({"top", "sub", "slaveBanker"});
        cerr << "account: " << account;
    }
}
<commit_msg>removed obsolete deferred banker test, since RestProxy now fails right away when a connection is not established yet<commit_after>/* banker_behaviour_test.cc
   Wolfgang Sourdeau, 20 December 2012
   Copyright (c) 2012 Datacratic Inc.  All rights reserved.

   Functional tests of the master and slave bankers
*/

#define BOOST_TEST_MAIN
#define BOOST_TEST_DYN_LINK

#include <unordered_set>

#include "boost/test/unit_test.hpp"
#include "jml/arch/format.h"

#include "soa/service/service_base.h"
#include "soa/service/testing/redis_temporary_server.h"
#include "soa/service/testing/zookeeper_temporary_server.h"

#include "rtbkit/core/banker/master_banker.h"
#include "rtbkit/core/banker/slave_banker.h"

#include "banker_temporary_server.h"

using namespace std;

using namespace Datacratic;
using namespace RTBKIT;
using namespace Redis;

namespace {

void
RedisReplyFillSetOfStrings(const Redis::Reply & reply,
                           unordered_set<string> & aSet) {
    ExcAssert(reply.type() == Redis::ARRAY);
    for (int i = 0; i < reply.length(); i++) {
        aSet.insert(reply[i].asString());
    }
}

}

/* make sure that the slave banker does create a spend account, even when a
 * "legacyImported" account exists */
BOOST_AUTO_TEST_CASE( test_banker_slave_banker_accounts )
{
    ZooKeeper::TemporaryServer zookeeper;
    zookeeper.start();

    auto proxies = std::make_shared<ServiceProxies>();
    proxies->useZookeeper(ML::format("localhost:%d", zookeeper.getPort()));

    /* spawn master */
    RedisTemporaryServer redis;

    /* create some initial accounts */
    {
        MasterBanker master(proxies, "initBanker");
        auto storage = make_shared<RedisBankerPersistence>(redis);
        master.init(storage);
        master.start();

        master.accounts.createAccount({"top"}, AT_BUDGET);
        master.accounts.setBudget({"top"}, MicroUSD(15729914170));
        master.accounts.setAvailable({"top", "sub"}, MicroUSD(11005485799),
                                     AT_BUDGET);
        master.accounts.setAvailable({"top", "sub", "legacyImported"},
                                     MicroUSD(10991979974),
                                     AT_SPEND);
        master.accounts.importSpend({"top", "sub", "legacyImported"},
                                    MicroUSD(10991979974));
        /* save the initial accounts state (the async save is guaranteed to
         * be over when "master" is destroyed) */
        master.saveState();
    }

    /* instantiate a slave and add a spend account from it */
    {
        /* spawn a master banker server process */
        BankerTemporaryServer master(redis, ML::format("localhost:%d", zookeeper.getPort()));

        /* spawn slave */
        SlaveBanker slave(proxies->zmqContext);
        slave.init(proxies->config, "slaveBanker");
        slave.start();

        slave.addSpendAccountSync({"top", "sub"});

        ML::sleep(2);
    }

    /* ensure that "top:sub:slaveBanker" has been created. If not, an
     * exception will be thrown. */
    {
        MasterBanker master(proxies, "initBanker2");
        auto storage = make_shared<RedisBankerPersistence>(redis);
        master.init(storage);
        master.start();
        auto account
            = master.accounts.getAccount({"top", "sub", "slaveBanker"});
        cerr << "account: " << account;
    }
}
<|endoftext|>


<commit_before>/*!
  \copyright (c) RDO-Team, 2011
  \file      calc_statement.cpp
  \authors
  \authors     (dluschan@rk9.bmstu.ru)
  \date      16.04.2011
  \brief
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
#include "simulator/runtime/pch.h"
// ----------------------------------------------------------------------- INCLUDES
// ----------------------------------------------------------------------- SYNOPSIS
#include "simulator/runtime/calc/procedural/calc_statement.h"
// --------------------------------------------------------------------------------

OPEN_RDO_RUNTIME_NAMESPACE

// --------------------------------------------------------------------------------
// -------------------- RDOCalcNoChange
// --------------------------------------------------------------------------------
RDOCalcNoChange::RDOCalcNoChange()
{
	m_value = RDOValue(0);
}

REF(RDOValue) RDOCalcNoChange::doCalc(CREF(LPRDORuntime) pRuntime)
{
	UNUSED(pRuntime);
	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcIf
// --------------------------------------------------------------------------------
RDOCalcIf::RDOCalcIf(CREF(LPRDOCalc) pCondition)
	: m_pCondition(pCondition)
{
	ASSERT(m_pCondition);
	m_value = RDOValue(false);
}

void RDOCalcIf::setThenStatement(CREF(LPRDOCalc) pStatement)
{
	ASSERT(pStatement);
	m_statements.first = pStatement;
}

void RDOCalcIf::setElseStatement(CREF(LPRDOCalc) pStatement)
{
	ASSERT(pStatement);
	m_statements.second = pStatement;
}

rbool RDOCalcIf::hasElse() const
{
	return m_statements.second;
}

REF(RDOValue) RDOCalcIf::doCalc(CREF(LPRDORuntime) pRuntime)
{
	return m_pCondition->calcValue(pRuntime).getAsBool()
		? m_statements.first->calcValue(pRuntime)
		: hasElse()
			? m_statements.second->calcValue(pRuntime)
			: m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcFor
// --------------------------------------------------------------------------------
RDOCalcFor::RDOCalcFor(CREF(LPRDOCalc) pDeclaration, CREF(LPRDOCalc) pCondition, CREF(LPRDOCalc) pExpression)
	: m_pDeclaration(pDeclaration)
	, m_pCondition  (pCondition  )
	, m_pExpression (pExpression )
{
	ASSERT(m_pDeclaration);
	ASSERT(m_pCondition  );
	ASSERT(m_pExpression );
}

void RDOCalcFor::setStatement(CREF(LPRDOCalc) pStatement)
{
	ASSERT(pStatement);
	m_pStatement = pStatement;
}

REF(RDOValue) RDOCalcFor::doCalc(CREF(LPRDORuntime) pRuntime)
{
	m_value = RDOValue(0);

	m_pDeclaration->calcValue(pRuntime);
	while (m_pCondition->calcValue(pRuntime).getAsBool())
	{
		m_value = m_pStatement->calcValue(pRuntime);
		if (pRuntime->getFunBreakFlag() != RDORuntime::FBF_NONE)
		{
			break;
		}
		m_pExpression->calcValue(pRuntime);
	}

	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcFunReturn
// --------------------------------------------------------------------------------
RDOCalcFunReturn::RDOCalcFunReturn(CREF(LPRDOCalc) pReturn)
	: m_pReturn(pReturn)
{}

REF(RDOValue) RDOCalcFunReturn::doCalc(CREF(LPRDORuntime) pRuntime)
{
	ASSERT(m_pReturn);

	m_value = m_pReturn->calcValue(pRuntime);
	pRuntime->setFunBreakFlag(RDORuntime::FBF_RETURN);
	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcFunBreak
// --------------------------------------------------------------------------------
RDOCalcFunBreak::RDOCalcFunBreak()
{}

REF(RDOValue) RDOCalcFunBreak::doCalc(CREF(LPRDORuntime) pRuntime)
{
	pRuntime->setFunBreakFlag(RDORuntime::FBF_BREAK);
	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcBaseStatementList
// --------------------------------------------------------------------------------
RDOCalcBaseStatementList::RDOCalcBaseStatementList()
{}

void RDOCalcBaseStatementList::addCalcStatement(CREF(LPRDOCalc) pStatement)
{
	ASSERT(pStatement);
	m_calcStatementList.push_back(pStatement);
}

RDOCalc::RDOCalcList RDOCalcBaseStatementList::statementList()
{
	return m_calcStatementList;
}

REF(RDOValue) RDOCalcBaseStatementList::doCalc(CREF(LPRDORuntime) pRuntime)
{
	STL_FOR_ALL(m_calcStatementList, calcIt)
	{
		RDOValue tempValue = (*calcIt)->calcValue(pRuntime);
		if (tempValue.typeID() != RDOType::t_unknow)
		{
			m_value = tempValue;
		}
	}
	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcStatementList
// --------------------------------------------------------------------------------
RDOCalcStatementList::RDOCalcStatementList()
{}

REF(RDOValue) RDOCalcStatementList::doCalc(CREF(LPRDORuntime) pRuntime)
{
	STL_FOR_ALL(m_calcStatementList, calcIt)
	{
		m_value = (*calcIt)->calcValue(pRuntime);

		if (pRuntime->getFunBreakFlag() != RDORuntime::FBF_NONE)
		{
			break;
		}
	}
	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcBreakCatch
// --------------------------------------------------------------------------------
RDOCalcBreakCatch::RDOCalcBreakCatch()
{
	m_value = RDOValue(0);
}

void RDOCalcBreakCatch::addStatementList(CREF(LPRDOCalc) pStatementList)
{
	ASSERT(pStatementList);
	m_pStatementList = pStatementList;
}

REF(RDOValue) RDOCalcBreakCatch::doCalc(CREF(LPRDORuntime) pRuntime)
{
	ASSERT(m_pStatementList);

	m_pStatementList->calcValue(pRuntime);

	if (pRuntime->getFunBreakFlag() == RDORuntime::FBF_BREAK)
	{
		pRuntime->setFunBreakFlag(RDORuntime::FBF_NONE);
	}

	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcReturnCatch
// --------------------------------------------------------------------------------
RDOCalcReturnCatch::RDOCalcReturnCatch()
{}

void RDOCalcReturnCatch::setTryCalc(CREF(LPRDOCalc) pTryCalc)
{
	ASSERT(pTryCalc);
	m_pTryCalc = pTryCalc;
}

REF(RDOValue) RDOCalcReturnCatch::doCalc(CREF(LPRDORuntime) pRuntime)
{
	ASSERT(m_pTryCalc);

	m_value = m_pTryCalc->calcValue(pRuntime);

	if (pRuntime->getFunBreakFlag() == RDORuntime::FBF_RETURN)
	{
		pRuntime->setFunBreakFlag(RDORuntime::FBF_NONE);
	}

	return m_value;
}

CLOSE_RDO_RUNTIME_NAMESPACE
<commit_msg> - не создаётся лишняя копия<commit_after>/*!
  \copyright (c) RDO-Team, 2011
  \file      calc_statement.cpp
  \authors
  \authors     (dluschan@rk9.bmstu.ru)
  \date      16.04.2011
  \brief
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
#include "simulator/runtime/pch.h"
// ----------------------------------------------------------------------- INCLUDES
// ----------------------------------------------------------------------- SYNOPSIS
#include "simulator/runtime/calc/procedural/calc_statement.h"
// --------------------------------------------------------------------------------

OPEN_RDO_RUNTIME_NAMESPACE

// --------------------------------------------------------------------------------
// -------------------- RDOCalcNoChange
// --------------------------------------------------------------------------------
RDOCalcNoChange::RDOCalcNoChange()
{
	m_value = RDOValue(0);
}

REF(RDOValue) RDOCalcNoChange::doCalc(CREF(LPRDORuntime) pRuntime)
{
	UNUSED(pRuntime);
	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcIf
// --------------------------------------------------------------------------------
RDOCalcIf::RDOCalcIf(CREF(LPRDOCalc) pCondition)
	: m_pCondition(pCondition)
{
	ASSERT(m_pCondition);
	m_value = RDOValue(false);
}

void RDOCalcIf::setThenStatement(CREF(LPRDOCalc) pStatement)
{
	ASSERT(pStatement);
	m_statements.first = pStatement;
}

void RDOCalcIf::setElseStatement(CREF(LPRDOCalc) pStatement)
{
	ASSERT(pStatement);
	m_statements.second = pStatement;
}

rbool RDOCalcIf::hasElse() const
{
	return m_statements.second;
}

REF(RDOValue) RDOCalcIf::doCalc(CREF(LPRDORuntime) pRuntime)
{
	return m_pCondition->calcValue(pRuntime).getAsBool()
		? m_statements.first->calcValue(pRuntime)
		: hasElse()
			? m_statements.second->calcValue(pRuntime)
			: m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcFor
// --------------------------------------------------------------------------------
RDOCalcFor::RDOCalcFor(CREF(LPRDOCalc) pDeclaration, CREF(LPRDOCalc) pCondition, CREF(LPRDOCalc) pExpression)
	: m_pDeclaration(pDeclaration)
	, m_pCondition  (pCondition  )
	, m_pExpression (pExpression )
{
	ASSERT(m_pDeclaration);
	ASSERT(m_pCondition  );
	ASSERT(m_pExpression );
}

void RDOCalcFor::setStatement(CREF(LPRDOCalc) pStatement)
{
	ASSERT(pStatement);
	m_pStatement = pStatement;
}

REF(RDOValue) RDOCalcFor::doCalc(CREF(LPRDORuntime) pRuntime)
{
	m_value = RDOValue(0);

	m_pDeclaration->calcValue(pRuntime);
	while (m_pCondition->calcValue(pRuntime).getAsBool())
	{
		m_value = m_pStatement->calcValue(pRuntime);
		if (pRuntime->getFunBreakFlag() != RDORuntime::FBF_NONE)
		{
			break;
		}
		m_pExpression->calcValue(pRuntime);
	}

	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcFunReturn
// --------------------------------------------------------------------------------
RDOCalcFunReturn::RDOCalcFunReturn(CREF(LPRDOCalc) pReturn)
	: m_pReturn(pReturn)
{}

REF(RDOValue) RDOCalcFunReturn::doCalc(CREF(LPRDORuntime) pRuntime)
{
	ASSERT(m_pReturn);

	m_value = m_pReturn->calcValue(pRuntime);
	pRuntime->setFunBreakFlag(RDORuntime::FBF_RETURN);
	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcFunBreak
// --------------------------------------------------------------------------------
RDOCalcFunBreak::RDOCalcFunBreak()
{}

REF(RDOValue) RDOCalcFunBreak::doCalc(CREF(LPRDORuntime) pRuntime)
{
	pRuntime->setFunBreakFlag(RDORuntime::FBF_BREAK);
	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcBaseStatementList
// --------------------------------------------------------------------------------
RDOCalcBaseStatementList::RDOCalcBaseStatementList()
{}

void RDOCalcBaseStatementList::addCalcStatement(CREF(LPRDOCalc) pStatement)
{
	ASSERT(pStatement);
	m_calcStatementList.push_back(pStatement);
}

RDOCalc::RDOCalcList RDOCalcBaseStatementList::statementList()
{
	return m_calcStatementList;
}

REF(RDOValue) RDOCalcBaseStatementList::doCalc(CREF(LPRDORuntime) pRuntime)
{
	STL_FOR_ALL(m_calcStatementList, calcIt)
	{
		REF(RDOValue) tempValue = (*calcIt)->calcValue(pRuntime);
		if (tempValue.typeID() != RDOType::t_unknow)
		{
			m_value = tempValue;
		}
	}
	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcStatementList
// --------------------------------------------------------------------------------
RDOCalcStatementList::RDOCalcStatementList()
{}

REF(RDOValue) RDOCalcStatementList::doCalc(CREF(LPRDORuntime) pRuntime)
{
	STL_FOR_ALL(m_calcStatementList, calcIt)
	{
		m_value = (*calcIt)->calcValue(pRuntime);

		if (pRuntime->getFunBreakFlag() != RDORuntime::FBF_NONE)
		{
			break;
		}
	}
	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcBreakCatch
// --------------------------------------------------------------------------------
RDOCalcBreakCatch::RDOCalcBreakCatch()
{
	m_value = RDOValue(0);
}

void RDOCalcBreakCatch::addStatementList(CREF(LPRDOCalc) pStatementList)
{
	ASSERT(pStatementList);
	m_pStatementList = pStatementList;
}

REF(RDOValue) RDOCalcBreakCatch::doCalc(CREF(LPRDORuntime) pRuntime)
{
	ASSERT(m_pStatementList);

	m_pStatementList->calcValue(pRuntime);

	if (pRuntime->getFunBreakFlag() == RDORuntime::FBF_BREAK)
	{
		pRuntime->setFunBreakFlag(RDORuntime::FBF_NONE);
	}

	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcReturnCatch
// --------------------------------------------------------------------------------
RDOCalcReturnCatch::RDOCalcReturnCatch()
{}

void RDOCalcReturnCatch::setTryCalc(CREF(LPRDOCalc) pTryCalc)
{
	ASSERT(pTryCalc);
	m_pTryCalc = pTryCalc;
}

REF(RDOValue) RDOCalcReturnCatch::doCalc(CREF(LPRDORuntime) pRuntime)
{
	ASSERT(m_pTryCalc);

	m_value = m_pTryCalc->calcValue(pRuntime);

	if (pRuntime->getFunBreakFlag() == RDORuntime::FBF_RETURN)
	{
		pRuntime->setFunBreakFlag(RDORuntime::FBF_NONE);
	}

	return m_value;
}

CLOSE_RDO_RUNTIME_NAMESPACE
<|endoftext|>