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

#include "./cyber_topology_message.h"
#include "./general_channel_message.h"
#include "./screen.h"

#include "cyber/message/message_traits.h"
#include "cyber/proto/topology_change.pb.h"
#include "cyber/proto/role_attributes.pb.h"

#include <ncurses.h>
#include <iomanip>
#include <iostream>

constexpr int SecondColumnOffset = 4;

CyberTopologyMessage::CyberTopologyMessage(const std::string& channel)
    : RenderableMessage(nullptr, 1),
      second_column_(SecondColumnType::MessageFrameRatio),
      pid_(getpid()),
      col1_width_(8),
      specified_channel_(channel),
      all_channels_map_() {}

CyberTopologyMessage::~CyberTopologyMessage(void) {
  for (auto item : all_channels_map_) {
    if (!GeneralChannelMessage::isErrorCode(item.second)) {
      delete item.second;
    }
  }
}

bool CyberTopologyMessage::isFromHere(const std::string& nodeName) {
  std::ostringstream outStr;
  outStr << "MonitorReader" << pid_;

  std::string templateName = outStr.str();
  const std::string baseName = nodeName.substr(0, templateName.size());

  return (templateName.compare(baseName) == 0);
}

RenderableMessage* CyberTopologyMessage::Child(int lineNo) const {
  RenderableMessage* ret = nullptr;
  auto iter = findChild(lineNo);
  if (!GeneralChannelMessage::isErrorCode(iter->second) &&
      iter->second->is_enabled()) {
    ret = iter->second;
  }
  return ret;
}

std::map<std::string, GeneralChannelMessage*>::const_iterator CyberTopologyMessage::findChild(int lineNo) const{
  --lineNo;

  std::map<std::string, GeneralChannelMessage*>::const_iterator ret = all_channels_map_.cend();

  if (lineNo > -1 && lineNo < page_item_count_) {
    int i = 0;

    auto iter = all_channels_map_.cbegin();
    while (i < page_index_ * page_item_count_) {
      ++iter;
      ++i;
    }

    for (i = 0; iter != all_channels_map_.cend(); ++iter) {
      if (i == lineNo) {
        ret = iter;
        break;
      }
      ++i;
    }
  }
  return ret;
}

void CyberTopologyMessage::TopologyChanged(
    const apollo::cyber::proto::ChangeMsg& changeMsg) {
  if (::apollo::cyber::proto::OperateType::OPT_JOIN ==
      changeMsg.operate_type()) {
    bool isWriter = true;
    if (::apollo::cyber::proto::RoleType::ROLE_READER ==
        changeMsg.role_type())
      isWriter = false;
    AddReaderWriter(changeMsg.role_attr(), isWriter);
  } else {
    auto iter = all_channels_map_.find(changeMsg.role_attr().channel_name());

    if (iter != all_channels_map_.cend() &&
        !GeneralChannelMessage::isErrorCode(iter->second)) {
      const std::string& nodeName = changeMsg.role_attr().node_name();
      if (::apollo::cyber::proto::RoleType::ROLE_WRITER ==
          changeMsg.role_type()) {
        iter->second->del_writer(nodeName);
      } else {
        iter->second->del_reader(nodeName);
      }
    }
  }
}

void CyberTopologyMessage::AddReaderWriter(
    const apollo::cyber::proto::RoleAttributes& role, bool isWriter) {
  const std::string& channelName = role.channel_name();

  if (!specified_channel_.empty() && specified_channel_ != channelName) {
    return;
  }

  if (static_cast<int>(channelName.length()) > col1_width_) {
    col1_width_ = static_cast<int>(channelName.length());
  }

  const std::string& nodeName = role.node_name();
  if (isFromHere(nodeName)) {
    return;
  }

  GeneralChannelMessage* channelMsg = nullptr;
  const std::string& msgTypeName = role.message_type();
  auto iter = all_channels_map_.find(channelName);
  if (iter == all_channels_map_.cend()) {
    static int index = 0;

    std::ostringstream outStr;
    outStr << "MonitorReader" << pid_ << '-' << index++;

    channelMsg = new GeneralChannelMessage(outStr.str(), this);

    if(channelMsg != nullptr){
      if (!GeneralChannelMessage::isErrorCode(channelMsg->OpenChannel(channelName))) {
        channelMsg->set_message_type(msgTypeName);
        channelMsg->add_reader(channelMsg->NodeName());
      }
    } else {
      channelMsg = GeneralChannelMessage::castErrorCode2Ptr(GeneralChannelMessage::ErrorCode::NewSubClassFailed);
    }
    all_channels_map_[channelName] = channelMsg;
  } else {
    channelMsg = iter->second;
  }

  if (!GeneralChannelMessage::isErrorCode(channelMsg)) {
    if (isWriter) {
      if (msgTypeName != apollo::cyber::message::MessageType<
                             apollo::cyber::message::RawMessage>()) {
        channelMsg->set_message_type(msgTypeName);
      }

      channelMsg->add_writer(nodeName);
    } else {
      channelMsg->add_reader(nodeName);
    }
  }
}

void CyberTopologyMessage::ChangeState(const Screen* s, int key) {
  switch (key) {
    case 'f':
    case 'F':
      second_column_ = SecondColumnType::MessageFrameRatio;
      break;

    case 't':
    case 'T':
      second_column_ = SecondColumnType::MessageType;
      break;

    case ' ': {
      auto iter = findChild(*line_no());
      if (!GeneralChannelMessage::isErrorCode(iter->second)) {
        GeneralChannelMessage* child = iter->second;
        if(child->is_enabled()){
          child->CloseChannel();
        } else {
          GeneralChannelMessage* ret = child->OpenChannel(iter->first);
          if(GeneralChannelMessage::isErrorCode(ret)){
            delete child;
            all_channels_map_[iter->first] = ret;
          } else {
            child->add_reader(child->NodeName());
          }
        }
      }
    }

    default: {}
  }
}

void CyberTopologyMessage::Render(const Screen* s, int key) {
  page_item_count_ = s->Height() - 1;
  pages_ = static_cast<int>(all_channels_map_.size()) / page_item_count_ + 1;
  ChangeState(s, key);
  SplitPages(key);

  s->AddStr(0, 0, Screen::WHITE_BLACK, "Channels");
  switch (second_column_) {
    case SecondColumnType::MessageType:
      s->AddStr(col1_width_ + SecondColumnOffset, 0, Screen::WHITE_BLACK,
                "TypeName");
      break;
    case SecondColumnType::MessageFrameRatio:
      s->AddStr(col1_width_ + SecondColumnOffset, 0, Screen::WHITE_BLACK,
                "FrameRatio");
      break;
  }

  auto iter = all_channels_map_.cbegin();
  register int tmp = page_index_ * page_item_count_;
  register int line = 0;
  while (line < tmp) {
    ++iter;
    ++line;
  }

  Screen::ColorPair color;
  std::ostringstream outStr;

  tmp = page_item_count_ + 1;
  for (line = 1; iter != all_channels_map_.cend() && line < tmp;
       ++iter, ++line) {
    color = Screen::RED_BLACK;

    if (!GeneralChannelMessage::isErrorCode(iter->second)) {
      if (iter->second->has_message_come()) {
        if (iter->second->is_enabled()) {
          color = Screen::GREEN_BLACK;
        } else {
          color = Screen::YELLOW_BLACK;
        }
      }
    }

    s->SetCurrentColor(color);
    s->AddStr(0, line, iter->first.c_str());

    if (!GeneralChannelMessage::isErrorCode(iter->second)) {
      switch (second_column_) {
        case SecondColumnType::MessageType:
          s->AddStr(col1_width_ + SecondColumnOffset, line,
                    iter->second->message_type().c_str());
          break;
        case SecondColumnType::MessageFrameRatio: {
          outStr.str("");
          outStr << std::fixed << std::setprecision(GeneralChannelMessage::FrameRatio_Precision)
                 << iter->second->frame_ratio();
          s->AddStr(col1_width_ + SecondColumnOffset, line,
                    outStr.str().c_str());
        } break;
      }
    } else {
      GeneralChannelMessage::ErrorCode errcode =
          GeneralChannelMessage::castPtr2ErrorCode(iter->second);
      s->AddStr(col1_width_ + SecondColumnOffset, line,
                GeneralChannelMessage::errCode2Str(errcode));
    }
    s->ClearCurrentColor();
  }
}
<commit_msg>Framework: delete the redundant code, adjust frame ratio for UI<commit_after>/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "./cyber_topology_message.h"
#include "./general_channel_message.h"
#include "./screen.h"

#include "cyber/message/message_traits.h"
#include "cyber/proto/topology_change.pb.h"
#include "cyber/proto/role_attributes.pb.h"

#include <ncurses.h>
#include <iomanip>
#include <iostream>

constexpr int SecondColumnOffset = 4;

CyberTopologyMessage::CyberTopologyMessage(const std::string& channel)
    : RenderableMessage(nullptr, 1),
      second_column_(SecondColumnType::MessageFrameRatio),
      pid_(getpid()),
      col1_width_(8),
      specified_channel_(channel),
      all_channels_map_() {}

CyberTopologyMessage::~CyberTopologyMessage(void) {
  for (auto item : all_channels_map_) {
    if (!GeneralChannelMessage::isErrorCode(item.second)) {
      delete item.second;
    }
  }
}

bool CyberTopologyMessage::isFromHere(const std::string& nodeName) {
  std::ostringstream outStr;
  outStr << "MonitorReader" << pid_;

  std::string templateName = outStr.str();
  const std::string baseName = nodeName.substr(0, templateName.size());

  return (templateName.compare(baseName) == 0);
}

RenderableMessage* CyberTopologyMessage::Child(int lineNo) const {
  RenderableMessage* ret = nullptr;
  auto iter = findChild(lineNo);
  if (!GeneralChannelMessage::isErrorCode(iter->second) &&
      iter->second->is_enabled()) {
    ret = iter->second;
  }
  return ret;
}

std::map<std::string, GeneralChannelMessage*>::const_iterator CyberTopologyMessage::findChild(int lineNo) const{
  --lineNo;

  std::map<std::string, GeneralChannelMessage*>::const_iterator ret = all_channels_map_.cend();

  if (lineNo > -1 && lineNo < page_item_count_) {
    int i = 0;

    auto iter = all_channels_map_.cbegin();
    while (i < page_index_ * page_item_count_) {
      ++iter;
      ++i;
    }

    for (i = 0; iter != all_channels_map_.cend(); ++iter) {
      if (i == lineNo) {
        ret = iter;
        break;
      }
      ++i;
    }
  }
  return ret;
}

void CyberTopologyMessage::TopologyChanged(
    const apollo::cyber::proto::ChangeMsg& changeMsg) {
  if (::apollo::cyber::proto::OperateType::OPT_JOIN ==
      changeMsg.operate_type()) {
    bool isWriter = true;
    if (::apollo::cyber::proto::RoleType::ROLE_READER ==
        changeMsg.role_type())
      isWriter = false;
    AddReaderWriter(changeMsg.role_attr(), isWriter);
  } else {
    auto iter = all_channels_map_.find(changeMsg.role_attr().channel_name());

    if (iter != all_channels_map_.cend() &&
        !GeneralChannelMessage::isErrorCode(iter->second)) {
      const std::string& nodeName = changeMsg.role_attr().node_name();
      if (::apollo::cyber::proto::RoleType::ROLE_WRITER ==
          changeMsg.role_type()) {
        iter->second->del_writer(nodeName);
      } else {
        iter->second->del_reader(nodeName);
      }
    }
  }
}

void CyberTopologyMessage::AddReaderWriter(
    const apollo::cyber::proto::RoleAttributes& role, bool isWriter) {
  const std::string& channelName = role.channel_name();

  if (!specified_channel_.empty() && specified_channel_ != channelName) {
    return;
  }

  if (static_cast<int>(channelName.length()) > col1_width_) {
    col1_width_ = static_cast<int>(channelName.length());
  }

  const std::string& nodeName = role.node_name();
  if (isFromHere(nodeName)) {
    return;
  }

  GeneralChannelMessage* channelMsg = nullptr;
  const std::string& msgTypeName = role.message_type();
  auto iter = all_channels_map_.find(channelName);
  if (iter == all_channels_map_.cend()) {
    static int index = 0;

    std::ostringstream outStr;
    outStr << "MonitorReader" << pid_ << '-' << index++;

    channelMsg = new GeneralChannelMessage(outStr.str(), this);

    if(channelMsg != nullptr){
      if (!GeneralChannelMessage::isErrorCode(channelMsg->OpenChannel(channelName))) {
        channelMsg->set_message_type(msgTypeName);
        channelMsg->add_reader(channelMsg->NodeName());
      }
    } else {
      channelMsg = GeneralChannelMessage::castErrorCode2Ptr(GeneralChannelMessage::ErrorCode::NewSubClassFailed);
    }
    all_channels_map_[channelName] = channelMsg;
  } else {
    channelMsg = iter->second;
  }

  if (!GeneralChannelMessage::isErrorCode(channelMsg)) {
    if (isWriter) {
      if (msgTypeName != apollo::cyber::message::MessageType<
                             apollo::cyber::message::RawMessage>()) {
        channelMsg->set_message_type(msgTypeName);
      }

      channelMsg->add_writer(nodeName);
    } else {
      channelMsg->add_reader(nodeName);
    }
  }
}

void CyberTopologyMessage::ChangeState(const Screen* s, int key) {
  switch (key) {
    case 'f':
    case 'F':
      second_column_ = SecondColumnType::MessageFrameRatio;
      break;

    case 't':
    case 'T':
      second_column_ = SecondColumnType::MessageType;
      break;

    case ' ': {
      auto iter = findChild(*line_no());
      if (!GeneralChannelMessage::isErrorCode(iter->second)) {
        GeneralChannelMessage* child = iter->second;
        if(child->is_enabled()){
          child->CloseChannel();
        } else {
          GeneralChannelMessage* ret = child->OpenChannel(iter->first);
          if(GeneralChannelMessage::isErrorCode(ret)){
            delete child;
            all_channels_map_[iter->first] = ret;
          } else {
            child->add_reader(child->NodeName());
          }
        }
      }
    }

    default: {}
  }
}

void CyberTopologyMessage::Render(const Screen* s, int key) {
  page_item_count_ = s->Height() - 1;
  pages_ = static_cast<int>(all_channels_map_.size()) / page_item_count_ + 1;
  ChangeState(s, key);
  SplitPages(key);

  s->AddStr(0, 0, Screen::WHITE_BLACK, "Channels");
  switch (second_column_) {
    case SecondColumnType::MessageType:
      s->AddStr(col1_width_ + SecondColumnOffset, 0, Screen::WHITE_BLACK,
                "TypeName");
      break;
    case SecondColumnType::MessageFrameRatio:
      s->AddStr(col1_width_ + SecondColumnOffset, 0, Screen::WHITE_BLACK,
                "FrameRatio");
      break;
  }

  auto iter = all_channels_map_.cbegin();
  register int tmp = page_index_ * page_item_count_;
  register int line = 0;
  while (line < tmp) {
    ++iter;
    ++line;
  }

  Screen::ColorPair color;
  std::ostringstream outStr;

  tmp = page_item_count_ + 1;
  for (line = 1; iter != all_channels_map_.cend() && line < tmp;
       ++iter, ++line) {
    color = Screen::RED_BLACK;

    if (!GeneralChannelMessage::isErrorCode(iter->second)) {
      if (iter->second->has_message_come()) {
        if (iter->second->is_enabled()) {
          color = Screen::GREEN_BLACK;
        } else {
          color = Screen::YELLOW_BLACK;
        }
      }
    }

    s->SetCurrentColor(color);
    s->AddStr(0, line, iter->first.c_str());

    if (!GeneralChannelMessage::isErrorCode(iter->second)) {
      switch (second_column_) {
        case SecondColumnType::MessageType:
          s->AddStr(col1_width_ + SecondColumnOffset, line,
                    iter->second->message_type().c_str());
          break;
        case SecondColumnType::MessageFrameRatio: {
          outStr.str("");
          outStr << std::fixed << std::setprecision(FrameRatio_Precision)
                 << iter->second->frame_ratio();
          s->AddStr(col1_width_ + SecondColumnOffset, line,
                    outStr.str().c_str());
        } break;
      }
    } else {
      GeneralChannelMessage::ErrorCode errcode =
          GeneralChannelMessage::castPtr2ErrorCode(iter->second);
      s->AddStr(col1_width_ + SecondColumnOffset, line,
                GeneralChannelMessage::errCode2Str(errcode));
    }
    s->ClearCurrentColor();
  }
}
<|endoftext|>


<commit_before>#include "drawer.hpp"
#include "proto_to_styles.hpp"

#include "../std/bind.hpp"

#include "../indexer/drawing_rules.hpp"
#include "../indexer/scales.hpp"

#include "../graphics/defines.hpp"
#include "../graphics/screen.hpp"
#include "../graphics/resource_manager.hpp"

#include "../geometry/screenbase.hpp"

#include "../base/logging.hpp"
#include "../base/buffer_vector.hpp"

Drawer::Params::Params()
  : m_visualScale(1)
{
}

di::DrawInfo::DrawInfo(string const & name,
         string const & secondaryName,
         string const & road,
         double rank)
  : m_name(name),
    m_secondaryName(secondaryName),
    m_road(road),
    m_rank(rank)
{}

string const di::DrawInfo::GetPathName() const
{
  if (m_secondaryName.empty())
    return m_name;
  else
    return m_name + "      " + m_secondaryName;
}

uint32_t di::DrawRule::GetID(size_t threadSlot) const
{
  return (m_transparent ? m_rule->GetID2(threadSlot) : m_rule->GetID(threadSlot));
}

void di::DrawRule::SetID(size_t threadSlot, uint32_t id) const
{
  m_transparent ? m_rule->SetID2(threadSlot, id) : m_rule->SetID(threadSlot, id);
}

Drawer::Drawer(Params const & params)
  : m_visualScale(params.m_visualScale)
{
  m_pScreen = shared_ptr<graphics::Screen>(new graphics::Screen(params));

  for (unsigned i = 0; i < m_pScreen->pipelinesCount(); ++i)
    m_pScreen->addClearPageFn(i, bind(&Drawer::ClearResourceCache, ThreadSlot(), i), 0);
}

namespace
{
  struct DoMakeInvalidRule
  {
    size_t m_threadSlot;
    uint32_t m_pipelineIDMask;

    DoMakeInvalidRule(size_t threadSlot, uint8_t pipelineID)
      : m_threadSlot(threadSlot), m_pipelineIDMask(pipelineID << 24)
    {}

    void operator() (int, int, int, drule::BaseRule * p)
    {
      if ((p->GetID(m_threadSlot) & 0xFF000000) == m_pipelineIDMask)
        p->MakeEmptyID(m_threadSlot);
      if ((p->GetID2(m_threadSlot) & 0xFF000000) == m_pipelineIDMask)
        p->MakeEmptyID2(m_threadSlot);
    }
  };
}

void Drawer::ClearResourceCache(size_t threadSlot, uint8_t pipelineID)
{
  drule::rules().ForEachRule(DoMakeInvalidRule(threadSlot, pipelineID));
}

void Drawer::beginFrame()
{
  m_pScreen->beginFrame();
}

void Drawer::endFrame()
{
  m_pScreen->endFrame();
}

void Drawer::clear(graphics::Color const & c, bool clearRT, float depth, bool clearDepth)
{
  m_pScreen->clear(c, clearRT, depth, clearDepth);
}

void Drawer::onSize(int w, int h)
{
  m_pScreen->onSize(w, h);
}

void Drawer::drawSymbol(m2::PointD const & pt,
                        string const & symbolName,
                        graphics::EPosition pos,
                        int depth)
{
  m_pScreen->drawSymbol(pt, symbolName, pos, depth);
}

void Drawer::drawCircle(m2::PointD const & pt, rule_ptr_t pRule,
                          graphics::EPosition pos, int depth, FeatureID const & id)
{
  graphics::Circle::Info ci;
  ConvertStyle(pRule->GetCircle(), m_visualScale, ci);

  m_pScreen->drawCircle(pt, ci, pos, depth);
}

void Drawer::drawSymbol(m2::PointD const & pt,
                        rule_ptr_t pRule,
                        graphics::EPosition pos,
                        int depth,
                        FeatureID const & id)
{
  graphics::Icon::Info info;
  ConvertStyle(pRule->GetSymbol(), info);

  graphics::SymbolElement::Params params;
  params.m_depth = depth;
  params.m_position = pos;
  params.m_pivot = pt;
  params.m_info = info;
  params.m_renderer = m_pScreen.get();
  params.m_userInfo.m_mwmID = id.first;
  params.m_userInfo.m_offset = id.second;

  m_pScreen->drawSymbol(params);
}

void Drawer::drawPath(di::PathInfo const & info, di::DrawRule const * rules, size_t count)
{
  // if any rule needs caching - cache as a whole vector
  bool flag = false;
  for (size_t i = 0; i < count; ++i)
  {
    if (rules[i].GetID(m_pScreen->threadSlot()) == drule::BaseRule::empty_id)
    {
      flag = true;
      break;
    }
  }

  buffer_vector<graphics::Pen::Info, 8> penInfos(count);
  buffer_vector<graphics::Resource::Info const*, 8> infos(count);
  buffer_vector<uint32_t, 8> resIDs(count);

  if (flag)
  {
    // collect graphics::PenInfo into array and pack them as a whole
    for (size_t i = 0; i < count; ++i)
    {
      ConvertStyle(rules[i].m_rule->GetLine(), m_visualScale, penInfos[i]);

      infos[i] = &penInfos[i];

      if (rules[i].m_transparent)
        penInfos[i].m_color.a = 100;

      resIDs[i] = m_pScreen->invalidHandle();
    }

    // map array of pens
    if (m_pScreen->mapInfo(&infos[0], &resIDs[0], count))
    {
      for (size_t i = 0; i < count; ++i)
        rules[i].SetID(ThreadSlot(), resIDs[i]);
    }
    else
    {
      LOG(LERROR, ("couldn't successfully pack a sequence of path styles as a whole"));
      return;
    }
  }

  // draw path with array of rules
  for (size_t i = 0; i < count; ++i)
    m_pScreen->drawPath(&info.m_path[0], info.m_path.size(), -info.GetOffset(), rules[i].GetID(ThreadSlot()), rules[i].m_depth);
}

void Drawer::drawArea(vector<m2::PointD> const & pts, rule_ptr_t pRule, int depth)
{
  // DO NOT cache 'id' in pRule, because one rule can use in drawPath and drawArea.
  // Leave CBaseRule::m_id for drawPath. mapColor working fast enough.

  graphics::Brush::Info info;
  ConvertStyle(pRule->GetArea(), info);

  uint32_t const id = m_pScreen->mapInfo(info);
  ASSERT ( id != -1, () );

  m_pScreen->drawTrianglesList(&pts[0], pts.size()/*, res*/, id, depth);
}

uint8_t Drawer::get_text_font_size(rule_ptr_t pRule) const
{
  return GetFontSize(pRule->GetCaption(0)) * m_visualScale;
}

bool Drawer::filter_text_size(rule_ptr_t pRule) const
{
  if (pRule->GetCaption(0))
    return (GetFontSize(pRule->GetCaption(0)) < 3);
  else
  {
    // this rule is not a caption at all
    return true;
  }
}

void Drawer::drawText(m2::PointD const & pt, di::DrawInfo const * pInfo, rule_ptr_t pRule,
                        graphics::EPosition pos, int depth, FeatureID const & id)
{
  graphics::FontDesc font;
  ConvertStyle(pRule->GetCaption(0), m_visualScale, font);
  font.SetRank(pInfo->m_rank);

  graphics::FontDesc smallFont;
  if (pRule->GetCaption(1))
  {
    ConvertStyle(pRule->GetCaption(1), m_visualScale, smallFont);
    smallFont.SetRank(pInfo->m_rank);
  }

  m_pScreen->drawTextEx(font, smallFont, pt, pos,
                        pInfo->m_name, pInfo->m_secondaryName,
                        depth, true, true);
}

bool Drawer::drawPathText(di::PathInfo const & info, di::DrawInfo const * pInfo, rule_ptr_t pRule, int depth)
{
  graphics::FontDesc font;
  ConvertStyle(pRule->GetCaption(0), m_visualScale, font);

  return m_pScreen->drawPathText(font,
                                 &info.m_path[0],
                                 info.m_path.size(),
                                 pInfo->GetPathName(),
                                 info.GetFullLength(),
                                 info.GetOffset(),
                                 graphics::EPosCenter,
                                 depth);
}

void Drawer::drawPathNumber(di::PathInfo const & path, di::DrawInfo const * pInfo)
{
  int const textHeight = static_cast<int>(12 * m_visualScale);
  m2::PointD pt;
  double const length = path.GetFullLength();
  if (length >= (pInfo->m_road.size() + 2)*textHeight)
  {
    size_t const count = size_t(length / 1000.0) + 2;

    for (size_t j = 1; j < count; ++j)
    {
      if (path.GetSmPoint(double(j) / double(count), pt))
      {
        graphics::FontDesc fontDesc(
          textHeight,
          graphics::Color(150, 75, 0, 255),   // brown
          true,
          graphics::Color(255, 255, 255, 255));

        m_pScreen->drawText(fontDesc, pt, graphics::EPosCenter, pInfo->m_road, graphics::maxDepth, true);
      }
    }
  }
}

shared_ptr<graphics::Screen> Drawer::screen() const
{
  return m_pScreen;
}

double Drawer::VisualScale() const
{
  return m_visualScale;
}

void Drawer::SetScale(int level)
{
  m_level = level;
}

void Drawer::Draw(di::DrawInfo const * pInfo, di::DrawRule const * rules, size_t count,
                    FeatureID const & id)
{
  buffer_vector<di::DrawRule, 8> pathRules;

  bool const isPath = !pInfo->m_pathes.empty();
  bool const isArea = !pInfo->m_areas.empty();

  // separating path rules from other
  for (size_t i = 0; i < count; ++i)
  {
    rule_ptr_t pRule = rules[i].m_rule;

    bool const hasSymbol = pRule->GetSymbol() != 0;
    bool const isCaption = pRule->GetCaption(0) != 0;

    if (!isCaption && isPath && !hasSymbol && (pRule->GetLine() != 0))
      pathRules.push_back(rules[i]);
  }

  if (!pathRules.empty())
  {
    for (list<di::PathInfo>::const_iterator i = pInfo->m_pathes.begin(); i != pInfo->m_pathes.end(); ++i)
    {
      drawPath(*i, pathRules.data(), pathRules.size());
    }
  }

  for (size_t i = 0; i < count; ++i)
  {
    rule_ptr_t pRule = rules[i].m_rule;
    int const depth = rules[i].m_depth;

    bool const isCaption = pRule->GetCaption(0) != 0;
    bool const hasSymbol = pRule->GetSymbol() != 0;
    bool const isCircle = pRule->GetCircle() != 0;

    if (!isCaption)
    {
      double const sm = 2.0 * m_visualScale;

      // draw area
      if (isArea)
      {
        bool const isFill = pRule->GetArea() != 0;
        bool const hasSym = hasSymbol && ((pRule->GetType() & drule::way) != 0);

        for (list<di::AreaInfo>::const_iterator i = pInfo->m_areas.begin(); i != pInfo->m_areas.end(); ++i)
        {
          if (isFill)
            drawArea(i->m_path, pRule, depth);
          else if (hasSym)
            drawSymbol(i->GetCenter() + m2::PointD(0.0, sm), pRule, graphics::EPosUnder, depth, id);
        }
      }

      // draw point symbol
      if (!isPath && !isArea && ((pRule->GetType() & drule::node) != 0))
      {
        if (hasSymbol)
          drawSymbol(pInfo->m_point + m2::PointD(0.0, sm), pRule, graphics::EPosUnder, depth, id);
        else if (isCircle)
          drawCircle(pInfo->m_point + m2::PointD(0.0, sm), pRule, graphics::EPosUnder, depth, id);
      }
    }
    else
    {
      if (!pInfo->m_name.empty())
      {
        bool isN = ((pRule->GetType() & drule::way) != 0);

        // draw area text
        if (isArea/* && isN*/)
        {
          for (list<di::AreaInfo>::const_iterator i = pInfo->m_areas.begin(); i != pInfo->m_areas.end(); ++i)
            drawText(i->GetCenter(), pInfo, pRule, graphics::EPosAbove, depth, id);
        }

        // draw way name
        if (isPath && !isArea && isN && !filter_text_size(pRule))
        {
          for (list<di::PathInfo>::const_iterator i = pInfo->m_pathes.begin(); i != pInfo->m_pathes.end(); ++i)
            drawPathText(*i, pInfo, pRule, depth);
        }

        // draw point text
        isN = ((pRule->GetType() & drule::node) != 0);
        if (!isPath && !isArea && isN)
          drawText(pInfo->m_point, pInfo, pRule, graphics::EPosAbove, depth, id);
      }
    }
  }

  // draw road numbers
  if (isPath && !pInfo->m_road.empty() && m_level >= 12)
  {
    for (list<di::PathInfo>::const_iterator i = pInfo->m_pathes.begin(); i != pInfo->m_pathes.end(); ++i)
      drawPathNumber(*i, pInfo);
  }
}

int Drawer::ThreadSlot() const
{
  return m_pScreen->threadSlot();
}
<commit_msg>aligning area texts to center point.<commit_after>#include "drawer.hpp"
#include "proto_to_styles.hpp"

#include "../std/bind.hpp"

#include "../indexer/drawing_rules.hpp"
#include "../indexer/scales.hpp"

#include "../graphics/defines.hpp"
#include "../graphics/screen.hpp"
#include "../graphics/resource_manager.hpp"

#include "../geometry/screenbase.hpp"

#include "../base/logging.hpp"
#include "../base/buffer_vector.hpp"

Drawer::Params::Params()
  : m_visualScale(1)
{
}

di::DrawInfo::DrawInfo(string const & name,
         string const & secondaryName,
         string const & road,
         double rank)
  : m_name(name),
    m_secondaryName(secondaryName),
    m_road(road),
    m_rank(rank)
{}

string const di::DrawInfo::GetPathName() const
{
  if (m_secondaryName.empty())
    return m_name;
  else
    return m_name + "      " + m_secondaryName;
}

uint32_t di::DrawRule::GetID(size_t threadSlot) const
{
  return (m_transparent ? m_rule->GetID2(threadSlot) : m_rule->GetID(threadSlot));
}

void di::DrawRule::SetID(size_t threadSlot, uint32_t id) const
{
  m_transparent ? m_rule->SetID2(threadSlot, id) : m_rule->SetID(threadSlot, id);
}

Drawer::Drawer(Params const & params)
  : m_visualScale(params.m_visualScale)
{
  m_pScreen = shared_ptr<graphics::Screen>(new graphics::Screen(params));

  for (unsigned i = 0; i < m_pScreen->pipelinesCount(); ++i)
    m_pScreen->addClearPageFn(i, bind(&Drawer::ClearResourceCache, ThreadSlot(), i), 0);
}

namespace
{
  struct DoMakeInvalidRule
  {
    size_t m_threadSlot;
    uint32_t m_pipelineIDMask;

    DoMakeInvalidRule(size_t threadSlot, uint8_t pipelineID)
      : m_threadSlot(threadSlot), m_pipelineIDMask(pipelineID << 24)
    {}

    void operator() (int, int, int, drule::BaseRule * p)
    {
      if ((p->GetID(m_threadSlot) & 0xFF000000) == m_pipelineIDMask)
        p->MakeEmptyID(m_threadSlot);
      if ((p->GetID2(m_threadSlot) & 0xFF000000) == m_pipelineIDMask)
        p->MakeEmptyID2(m_threadSlot);
    }
  };
}

void Drawer::ClearResourceCache(size_t threadSlot, uint8_t pipelineID)
{
  drule::rules().ForEachRule(DoMakeInvalidRule(threadSlot, pipelineID));
}

void Drawer::beginFrame()
{
  m_pScreen->beginFrame();
}

void Drawer::endFrame()
{
  m_pScreen->endFrame();
}

void Drawer::clear(graphics::Color const & c, bool clearRT, float depth, bool clearDepth)
{
  m_pScreen->clear(c, clearRT, depth, clearDepth);
}

void Drawer::onSize(int w, int h)
{
  m_pScreen->onSize(w, h);
}

void Drawer::drawSymbol(m2::PointD const & pt,
                        string const & symbolName,
                        graphics::EPosition pos,
                        int depth)
{
  m_pScreen->drawSymbol(pt, symbolName, pos, depth);
}

void Drawer::drawCircle(m2::PointD const & pt, rule_ptr_t pRule,
                          graphics::EPosition pos, int depth, FeatureID const & id)
{
  graphics::Circle::Info ci;
  ConvertStyle(pRule->GetCircle(), m_visualScale, ci);

  m_pScreen->drawCircle(pt, ci, pos, depth);
}

void Drawer::drawSymbol(m2::PointD const & pt,
                        rule_ptr_t pRule,
                        graphics::EPosition pos,
                        int depth,
                        FeatureID const & id)
{
  graphics::Icon::Info info;
  ConvertStyle(pRule->GetSymbol(), info);

  graphics::SymbolElement::Params params;
  params.m_depth = depth;
  params.m_position = pos;
  params.m_pivot = pt;
  params.m_info = info;
  params.m_renderer = m_pScreen.get();
  params.m_userInfo.m_mwmID = id.first;
  params.m_userInfo.m_offset = id.second;

  m_pScreen->drawSymbol(params);
}

void Drawer::drawPath(di::PathInfo const & info, di::DrawRule const * rules, size_t count)
{
  // if any rule needs caching - cache as a whole vector
  bool flag = false;
  for (size_t i = 0; i < count; ++i)
  {
    if (rules[i].GetID(m_pScreen->threadSlot()) == drule::BaseRule::empty_id)
    {
      flag = true;
      break;
    }
  }

  buffer_vector<graphics::Pen::Info, 8> penInfos(count);
  buffer_vector<graphics::Resource::Info const*, 8> infos(count);
  buffer_vector<uint32_t, 8> resIDs(count);

  if (flag)
  {
    // collect graphics::PenInfo into array and pack them as a whole
    for (size_t i = 0; i < count; ++i)
    {
      ConvertStyle(rules[i].m_rule->GetLine(), m_visualScale, penInfos[i]);

      infos[i] = &penInfos[i];

      if (rules[i].m_transparent)
        penInfos[i].m_color.a = 100;

      resIDs[i] = m_pScreen->invalidHandle();
    }

    // map array of pens
    if (m_pScreen->mapInfo(&infos[0], &resIDs[0], count))
    {
      for (size_t i = 0; i < count; ++i)
        rules[i].SetID(ThreadSlot(), resIDs[i]);
    }
    else
    {
      LOG(LERROR, ("couldn't successfully pack a sequence of path styles as a whole"));
      return;
    }
  }

  // draw path with array of rules
  for (size_t i = 0; i < count; ++i)
    m_pScreen->drawPath(&info.m_path[0], info.m_path.size(), -info.GetOffset(), rules[i].GetID(ThreadSlot()), rules[i].m_depth);
}

void Drawer::drawArea(vector<m2::PointD> const & pts, rule_ptr_t pRule, int depth)
{
  // DO NOT cache 'id' in pRule, because one rule can use in drawPath and drawArea.
  // Leave CBaseRule::m_id for drawPath. mapColor working fast enough.

  graphics::Brush::Info info;
  ConvertStyle(pRule->GetArea(), info);

  uint32_t const id = m_pScreen->mapInfo(info);
  ASSERT ( id != -1, () );

  m_pScreen->drawTrianglesList(&pts[0], pts.size()/*, res*/, id, depth);
}

uint8_t Drawer::get_text_font_size(rule_ptr_t pRule) const
{
  return GetFontSize(pRule->GetCaption(0)) * m_visualScale;
}

bool Drawer::filter_text_size(rule_ptr_t pRule) const
{
  if (pRule->GetCaption(0))
    return (GetFontSize(pRule->GetCaption(0)) < 3);
  else
  {
    // this rule is not a caption at all
    return true;
  }
}

void Drawer::drawText(m2::PointD const & pt, di::DrawInfo const * pInfo, rule_ptr_t pRule,
                        graphics::EPosition pos, int depth, FeatureID const & id)
{
  graphics::FontDesc font;
  ConvertStyle(pRule->GetCaption(0), m_visualScale, font);
  font.SetRank(pInfo->m_rank);

  graphics::FontDesc smallFont;
  if (pRule->GetCaption(1))
  {
    ConvertStyle(pRule->GetCaption(1), m_visualScale, smallFont);
    smallFont.SetRank(pInfo->m_rank);
  }

  m_pScreen->drawTextEx(font, smallFont, pt, pos,
                        pInfo->m_name, pInfo->m_secondaryName,
                        depth, true, true);
}

bool Drawer::drawPathText(di::PathInfo const & info, di::DrawInfo const * pInfo, rule_ptr_t pRule, int depth)
{
  graphics::FontDesc font;
  ConvertStyle(pRule->GetCaption(0), m_visualScale, font);

  return m_pScreen->drawPathText(font,
                                 &info.m_path[0],
                                 info.m_path.size(),
                                 pInfo->GetPathName(),
                                 info.GetFullLength(),
                                 info.GetOffset(),
                                 graphics::EPosCenter,
                                 depth);
}

void Drawer::drawPathNumber(di::PathInfo const & path, di::DrawInfo const * pInfo)
{
  int const textHeight = static_cast<int>(12 * m_visualScale);
  m2::PointD pt;
  double const length = path.GetFullLength();
  if (length >= (pInfo->m_road.size() + 2)*textHeight)
  {
    size_t const count = size_t(length / 1000.0) + 2;

    for (size_t j = 1; j < count; ++j)
    {
      if (path.GetSmPoint(double(j) / double(count), pt))
      {
        graphics::FontDesc fontDesc(
          textHeight,
          graphics::Color(150, 75, 0, 255),   // brown
          true,
          graphics::Color(255, 255, 255, 255));

        m_pScreen->drawText(fontDesc, pt, graphics::EPosCenter, pInfo->m_road, graphics::maxDepth, true);
      }
    }
  }
}

shared_ptr<graphics::Screen> Drawer::screen() const
{
  return m_pScreen;
}

double Drawer::VisualScale() const
{
  return m_visualScale;
}

void Drawer::SetScale(int level)
{
  m_level = level;
}

void Drawer::Draw(di::DrawInfo const * pInfo, di::DrawRule const * rules, size_t count,
                    FeatureID const & id)
{
  buffer_vector<di::DrawRule, 8> pathRules;

  bool const isPath = !pInfo->m_pathes.empty();
  bool const isArea = !pInfo->m_areas.empty();

  // separating path rules from other
  for (size_t i = 0; i < count; ++i)
  {
    rule_ptr_t pRule = rules[i].m_rule;

    bool const hasSymbol = pRule->GetSymbol() != 0;
    bool const isCaption = pRule->GetCaption(0) != 0;

    if (!isCaption && isPath && !hasSymbol && (pRule->GetLine() != 0))
      pathRules.push_back(rules[i]);
  }

  if (!pathRules.empty())
  {
    for (list<di::PathInfo>::const_iterator i = pInfo->m_pathes.begin(); i != pInfo->m_pathes.end(); ++i)
    {
      drawPath(*i, pathRules.data(), pathRules.size());
    }
  }

  for (size_t i = 0; i < count; ++i)
  {
    rule_ptr_t pRule = rules[i].m_rule;
    int const depth = rules[i].m_depth;

    bool const isCaption = pRule->GetCaption(0) != 0;
    bool const hasSymbol = pRule->GetSymbol() != 0;
    bool const isCircle = pRule->GetCircle() != 0;

    if (!isCaption)
    {
      double const sm = 2.0 * m_visualScale;

      // draw area
      if (isArea)
      {
        bool const isFill = pRule->GetArea() != 0;
        bool const hasSym = hasSymbol && ((pRule->GetType() & drule::way) != 0);

        for (list<di::AreaInfo>::const_iterator i = pInfo->m_areas.begin(); i != pInfo->m_areas.end(); ++i)
        {
          if (isFill)
            drawArea(i->m_path, pRule, depth);
          else if (hasSym)
            drawSymbol(i->GetCenter() + m2::PointD(0.0, sm), pRule, graphics::EPosUnder, depth, id);
        }
      }

      // draw point symbol
      if (!isPath && !isArea && ((pRule->GetType() & drule::node) != 0))
      {
        if (hasSymbol)
          drawSymbol(pInfo->m_point + m2::PointD(0.0, sm), pRule, graphics::EPosUnder, depth, id);
        else if (isCircle)
          drawCircle(pInfo->m_point + m2::PointD(0.0, sm), pRule, graphics::EPosUnder, depth, id);
      }
    }
    else
    {
      if (!pInfo->m_name.empty())
      {
        bool isN = ((pRule->GetType() & drule::way) != 0);

        // draw area text
        if (isArea/* && isN*/)
        {
          for (list<di::AreaInfo>::const_iterator i = pInfo->m_areas.begin(); i != pInfo->m_areas.end(); ++i)
            drawText(i->GetCenter(), pInfo, pRule, graphics::EPosCenter, depth, id);
        }

        // draw way name
        if (isPath && !isArea && isN && !filter_text_size(pRule))
        {
          for (list<di::PathInfo>::const_iterator i = pInfo->m_pathes.begin(); i != pInfo->m_pathes.end(); ++i)
            drawPathText(*i, pInfo, pRule, depth);
        }

        // draw point text
        isN = ((pRule->GetType() & drule::node) != 0);
        if (!isPath && !isArea && isN)
          drawText(pInfo->m_point, pInfo, pRule, graphics::EPosAbove, depth, id);
      }
    }
  }

  // draw road numbers
  if (isPath && !pInfo->m_road.empty() && m_level >= 12)
  {
    for (list<di::PathInfo>::const_iterator i = pInfo->m_pathes.begin(); i != pInfo->m_pathes.end(); ++i)
      drawPathNumber(*i, pInfo);
  }
}

int Drawer::ThreadSlot() const
{
  return m_pScreen->threadSlot();
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtCore/qurl.h>

#include "qmediasource.h"

class QMediaSourcePrivate : public QSharedData
{
public:
    QMediaSourcePrivate() {}
    QMediaSourcePrivate(const QMediaResourceList &r):
        resources(r) {}

    QMediaResourceList  resources;
};

/*!
    \class QMediaSource
    \preliminary
    \brief The QMediaSource class provides access to the resources relating to a media content.

    QMediaSource is used within the multimedia framework as the logical handle
    to media content.  Media content can have multiple forms or other meta-data
    like items attached, some examples would be different quality variants of
    the primary stream, or extended meta-data such as a Poster for a movie.

    A non-null QMediaSource will always have a primary or canonical reference to
    the content available through the contentUri() or contentResource()
    methods, all other resources are optional.
*/

/*!
    Constructs a null QMediaSource.
*/

QMediaSource::QMediaSource()
{
}

/*!
    Constructs a media source with \a contentUri providing a reference to the content.
*/

QMediaSource::QMediaSource(const QUrl &contentUri):
    d(new QMediaSourcePrivate)
{
    d->resources << QMediaResource(contentUrl);
}

/*!
    Constructs a media source with \a contentResource providing a reference to the content.
*/

QMediaSource::QMediaSource(const QMediaResource &contentResource):
    d(new QMediaSourcePrivate)
{
    d->resources << contentResource;
}

/*!
    Constructs a media source with \a resources providing a reference to the content.
*/

QMediaSource::QMediaSource(const QMediaResourceList &resources):
    d(new QMediaSourcePrivate(resources))
{
}

/*!
    Constructs a copy of media source \a other.
*/

QMediaSource::QMediaSource(const QMediaSource &other):
    d(other.d)
{
}

/*!
    Destroys the media source object.
*/

QMediaSource::~QMediaSource()
{
}

/*!
    Assigns the value of \a other to this media source.
*/

QMediaSource& QMediaSource::operator=(const QMediaSource &other)
{
    d = other.d;
    return *this;
}

/*!
    Returns true if \a other is equivalent to this media source; false otherwise.
*/

bool QMediaSource::operator==(const QMediaSource &other) const
{
    return (d.constData() == 0 && other.d.constData() == 0) ||
            (d.constData() != 0 && other.d.constData() != 0 &&
             d->resources == other.d->resources);
}

/*!
    Returns true if \a other is not equivalent to this media source; false otherwise.
*/

bool QMediaSource::operator!=(const QMediaSource &other) const
{
    return !(*this == other);
}

/*!
    Returns true if this media source is null (uninitialized); false otherwise.
*/

bool QMediaSource::isNull() const
{
    return d.constData() == 0;
}

/*!
    Returns a QUrl that represents that canonical content resource for this media source.
*/

QUrl QMediaSource::contentUri() const
{
    return contentResource().uri();
}

/*!
    Returns a QMediaResource that represents that canonical content resource for this media source.
*/

QMediaResource QMediaSource::contentResource() const
{
    foreach (const QMediaResource &resource, d->resources) {
        if (resource.role() == QMediaResource::ContentRole)
            return resource;
    }

    return QMediaResource();
}

/*!
    Returns a QMediaResourceList that contains all the QMediaResources that match the resource \a role.

    \sa QMediaResource::ResourceRole
*/

QMediaResourceList QMediaSource::resources(QMediaResource::ResourceRole role) const
{
    QMediaResourceList rc;

    foreach (const QMediaResource &resource, d->resources) {
        if (resource.role() == role)
            rc << resource;
    }

    return rc;
}

<commit_msg>Fix typo<commit_after>/****************************************************************************
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtCore/qurl.h>

#include "qmediasource.h"

class QMediaSourcePrivate : public QSharedData
{
public:
    QMediaSourcePrivate() {}
    QMediaSourcePrivate(const QMediaResourceList &r):
        resources(r) {}

    QMediaResourceList  resources;
};

/*!
    \class QMediaSource
    \preliminary
    \brief The QMediaSource class provides access to the resources relating to a media content.

    QMediaSource is used within the multimedia framework as the logical handle
    to media content.  Media content can have multiple forms or other meta-data
    like items attached, some examples would be different quality variants of
    the primary stream, or extended meta-data such as a Poster for a movie.

    A non-null QMediaSource will always have a primary or canonical reference to
    the content available through the contentUri() or contentResource()
    methods, all other resources are optional.
*/

/*!
    Constructs a null QMediaSource.
*/

QMediaSource::QMediaSource()
{
}

/*!
    Constructs a media source with \a contentUri providing a reference to the content.
*/

QMediaSource::QMediaSource(const QUrl &contentUri):
    d(new QMediaSourcePrivate)
{
    d->resources << QMediaResource(contentUri);
}

/*!
    Constructs a media source with \a contentResource providing a reference to the content.
*/

QMediaSource::QMediaSource(const QMediaResource &contentResource):
    d(new QMediaSourcePrivate)
{
    d->resources << contentResource;
}

/*!
    Constructs a media source with \a resources providing a reference to the content.
*/

QMediaSource::QMediaSource(const QMediaResourceList &resources):
    d(new QMediaSourcePrivate(resources))
{
}

/*!
    Constructs a copy of media source \a other.
*/

QMediaSource::QMediaSource(const QMediaSource &other):
    d(other.d)
{
}

/*!
    Destroys the media source object.
*/

QMediaSource::~QMediaSource()
{
}

/*!
    Assigns the value of \a other to this media source.
*/

QMediaSource& QMediaSource::operator=(const QMediaSource &other)
{
    d = other.d;
    return *this;
}

/*!
    Returns true if \a other is equivalent to this media source; false otherwise.
*/

bool QMediaSource::operator==(const QMediaSource &other) const
{
    return (d.constData() == 0 && other.d.constData() == 0) ||
            (d.constData() != 0 && other.d.constData() != 0 &&
             d->resources == other.d->resources);
}

/*!
    Returns true if \a other is not equivalent to this media source; false otherwise.
*/

bool QMediaSource::operator!=(const QMediaSource &other) const
{
    return !(*this == other);
}

/*!
    Returns true if this media source is null (uninitialized); false otherwise.
*/

bool QMediaSource::isNull() const
{
    return d.constData() == 0;
}

/*!
    Returns a QUrl that represents that canonical content resource for this media source.
*/

QUrl QMediaSource::contentUri() const
{
    return contentResource().uri();
}

/*!
    Returns a QMediaResource that represents that canonical content resource for this media source.
*/

QMediaResource QMediaSource::contentResource() const
{
    foreach (const QMediaResource &resource, d->resources) {
        if (resource.role() == QMediaResource::ContentRole)
            return resource;
    }

    return QMediaResource();
}

/*!
    Returns a QMediaResourceList that contains all the QMediaResources that match the resource \a role.

    \sa QMediaResource::ResourceRole
*/

QMediaResourceList QMediaSource::resources(QMediaResource::ResourceRole role) const
{
    QMediaResourceList rc;

    foreach (const QMediaResource &resource, d->resources) {
        if (resource.role() == role)
            rc << resource;
    }

    return rc;
}

<|endoftext|>


<commit_before>/* ffsdumper.cpp

Copyright (c) 2015, Nikolaj Schlej. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution.  The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php

THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

*/

#include "ffsdumper.h"

#include <fstream>

USTATUS FfsDumper::dump(const UModelIndex & root, const UString & path, const DumpMode dumpMode, const UINT8 sectionType, const UString & guid)
{
    dumped = false;
    counterHeader = counterBody = counterRaw = counterInfo = 0;

    if (changeDirectory(path))
        return U_DIR_ALREADY_EXIST;

    USTATUS result = recursiveDump(root, path, dumpMode, sectionType, guid);
    if (result)
        return result;
    else if (!dumped)
        return U_ITEM_NOT_FOUND;
    return U_SUCCESS;
}

USTATUS FfsDumper::recursiveDump(const UModelIndex & index, const UString & path, const DumpMode dumpMode, const UINT8 sectionType, const UString & guid)
{
    if (!index.isValid())
        return U_INVALID_PARAMETER;

    if (guid.isEmpty() ||
        (model->subtype(index) == EFI_SECTION_FREEFORM_SUBTYPE_GUID &&
        guidToUString(readMisaligned((const EFI_GUID*)(model->header(index).constData() + sizeof(EFI_COMMON_SECTION_HEADER)))) == guid) ||
        guidToUString(readMisaligned((const EFI_GUID*)model->header(index).constData())) == guid ||
        guidToUString(readMisaligned((const EFI_GUID*)model->header(model->findParentOfType(index, Types::File)).constData())) == guid) {

        if (!changeDirectory(path) && !makeDirectory(path))
            return U_DIR_CREATE;

        counterHeader = counterBody = counterRaw = counterInfo = 0;

        if (dumpMode == DUMP_ALL || model->rowCount(index) == 0)  { // Dump if leaf item or dumpAll is true
            if (dumpMode == DUMP_ALL || dumpMode == DUMP_CURRENT || dumpMode == DUMP_HEADER) {
                if (!model->header(index).isEmpty() && (sectionType == IgnoreSectionType || model->subtype(index) == sectionType)) {
                    UString filename;
                    if (counterHeader == 0)
                        filename = usprintf("%s/header.bin", path.toLocal8Bit());
                    else
                        filename = usprintf("%s/header_%d.bin", path.toLocal8Bit(), counterHeader);
                    counterHeader++;
                    std::ofstream file(filename.toLocal8Bit(), std::ofstream::binary);
                    if (!file)
                        return U_FILE_OPEN;
                    const UByteArray &data = model->header(index);
                    file.write(data.constData(), data.size());
                }
            }

            if (dumpMode == DUMP_ALL || dumpMode == DUMP_CURRENT || dumpMode == DUMP_BODY) {
                if (!model->body(index).isEmpty() && (sectionType == IgnoreSectionType || model->subtype(index) == sectionType)) {
                    UString filename;
                    if (counterBody == 0)
                        filename = usprintf("%s/body.bin", path.toLocal8Bit());
                    else
                        filename = usprintf("%s/body_%d.bin", path.toLocal8Bit(), counterBody);
                    counterBody++;
                    std::ofstream file(filename.toLocal8Bit(), std::ofstream::binary);
                    if (!file)
                        return U_FILE_OPEN;
                    const UByteArray &data = model->body(index);
                    file.write(data.constData(), data.size());
                }
            }

            if (dumpMode == DUMP_FILE && (sectionType == IgnoreSectionType || model->subtype(index) == sectionType)) {
                UModelIndex fileIndex = model->findParentOfType(index, Types::File);
                if (!fileIndex.isValid())
                    fileIndex = index;
                UString filename;
                if (counterRaw == 0)
                    filename = usprintf("%s/file.ffs", path.toLocal8Bit());
                else
                    filename = usprintf("%s/file_%d.bin", path.toLocal8Bit(), counterRaw);
                counterRaw++;
                std::ofstream file(filename.toLocal8Bit(), std::ofstream::binary);
                if (!file)
                    return U_FILE_OPEN;
                const UByteArray &headerData = model->header(index);
                const UByteArray &bodyData = model->body(index);
                const UByteArray &tailData = model->tail(index);
                file.write(headerData.constData(), headerData.size());
                file.write(bodyData.constData(), bodyData.size());
                file.write(tailData.constData(), tailData.size());
            }
        }

        // Always dump info unless explicitly prohibited
        if ((dumpMode == DUMP_ALL || dumpMode == DUMP_CURRENT || dumpMode == DUMP_INFO)
            && (sectionType == IgnoreSectionType || model->subtype(index) == sectionType)) {
            UString info = usprintf("Type: %s\nSubtype: %s\n%s%s\n",
                itemTypeToUString(model->type(index)).toLocal8Bit(),
                itemSubtypeToUString(model->type(index), model->subtype(index)).toLocal8Bit(),
                (model->text(index).isEmpty() ? UString("") :
                    usprintf("Text: %s\n", model->text(index).toLocal8Bit())).toLocal8Bit(),
                model->info(index).toLocal8Bit());
            UString filename;
            if (counterInfo == 0)
                filename = usprintf("%s/info.txt", path.toLocal8Bit());
            else
                filename = usprintf("%s/info_%d.txt", path.toLocal8Bit(), counterInfo);
            counterInfo++;
            std::ofstream file(filename.toLocal8Bit());
            if (!file)
                return U_FILE_OPEN;
            file << info.toLocal8Bit();
        }

        dumped = true;
    }

    USTATUS result;
    for (int i = 0; i < model->rowCount(index); i++) {
        UModelIndex childIndex = index.child(i, 0);
        bool useText = FALSE;
        if (model->type(childIndex) != Types::Volume)
            useText = !model->text(childIndex).isEmpty();

        UString childPath = path;
        if (dumpMode == DUMP_ALL || dumpMode == DUMP_CURRENT)
            childPath = usprintf("%s/%d %s", path.toLocal8Bit(), i,
                (useText ? model->text(childIndex) : model->name(childIndex)).toLocal8Bit());
        result = recursiveDump(childIndex, childPath, dumpMode, sectionType, guid);
        if (result)
            return result;
    }

    return U_SUCCESS;
}
<commit_msg>Fix file extraction in UEFIExtract<commit_after>/* ffsdumper.cpp

Copyright (c) 2015, Nikolaj Schlej. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution.  The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php

THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

*/

#include "ffsdumper.h"

#include <fstream>

USTATUS FfsDumper::dump(const UModelIndex & root, const UString & path, const DumpMode dumpMode, const UINT8 sectionType, const UString & guid)
{
    dumped = false;
    counterHeader = counterBody = counterRaw = counterInfo = 0;

    if (changeDirectory(path))
        return U_DIR_ALREADY_EXIST;

    USTATUS result = recursiveDump(root, path, dumpMode, sectionType, guid);
    if (result)
        return result;
    else if (!dumped)
        return U_ITEM_NOT_FOUND;
    return U_SUCCESS;
}

USTATUS FfsDumper::recursiveDump(const UModelIndex & index, const UString & path, const DumpMode dumpMode, const UINT8 sectionType, const UString & guid)
{
    if (!index.isValid())
        return U_INVALID_PARAMETER;

    if (guid.isEmpty() ||
        (model->subtype(index) == EFI_SECTION_FREEFORM_SUBTYPE_GUID &&
        guidToUString(readMisaligned((const EFI_GUID*)(model->header(index).constData() + sizeof(EFI_COMMON_SECTION_HEADER)))) == guid) ||
        guidToUString(readMisaligned((const EFI_GUID*)model->header(index).constData())) == guid ||
        guidToUString(readMisaligned((const EFI_GUID*)model->header(model->findParentOfType(index, Types::File)).constData())) == guid) {

        if (!changeDirectory(path) && !makeDirectory(path))
            return U_DIR_CREATE;

        counterHeader = counterBody = counterRaw = counterInfo = 0;

        if (dumpMode == DUMP_ALL || model->rowCount(index) == 0)  { // Dump if leaf item or dumpAll is true
            if (dumpMode == DUMP_ALL || dumpMode == DUMP_CURRENT || dumpMode == DUMP_HEADER) {
                if (!model->header(index).isEmpty() && (sectionType == IgnoreSectionType || model->subtype(index) == sectionType)) {
                    UString filename;
                    if (counterHeader == 0)
                        filename = usprintf("%s/header.bin", path.toLocal8Bit());
                    else
                        filename = usprintf("%s/header_%d.bin", path.toLocal8Bit(), counterHeader);
                    counterHeader++;
                    std::ofstream file(filename.toLocal8Bit(), std::ofstream::binary);
                    if (!file)
                        return U_FILE_OPEN;
                    const UByteArray &data = model->header(index);
                    file.write(data.constData(), data.size());
                }
            }

            if (dumpMode == DUMP_ALL || dumpMode == DUMP_CURRENT || dumpMode == DUMP_BODY) {
                if (!model->body(index).isEmpty() && (sectionType == IgnoreSectionType || model->subtype(index) == sectionType)) {
                    UString filename;
                    if (counterBody == 0)
                        filename = usprintf("%s/body.bin", path.toLocal8Bit());
                    else
                        filename = usprintf("%s/body_%d.bin", path.toLocal8Bit(), counterBody);
                    counterBody++;
                    std::ofstream file(filename.toLocal8Bit(), std::ofstream::binary);
                    if (!file)
                        return U_FILE_OPEN;
                    const UByteArray &data = model->body(index);
                    file.write(data.constData(), data.size());
                }
            }

            if (dumpMode == DUMP_FILE && (sectionType == IgnoreSectionType || model->subtype(index) == sectionType)) {
                UModelIndex fileIndex = model->findParentOfType(index, Types::File);
                if (!fileIndex.isValid())
                    fileIndex = index;
                UString filename;
                if (counterRaw == 0)
                    filename = usprintf("%s/file.ffs", path.toLocal8Bit());
                else
                    filename = usprintf("%s/file_%d.bin", path.toLocal8Bit(), counterRaw);
                counterRaw++;
                std::ofstream file(filename.toLocal8Bit(), std::ofstream::binary);
                if (!file)
                    return U_FILE_OPEN;
                const UByteArray &headerData = model->header(fileIndex);
                const UByteArray &bodyData = model->body(fileIndex);
                const UByteArray &tailData = model->tail(fileIndex);
                file.write(headerData.constData(), headerData.size());
                file.write(bodyData.constData(), bodyData.size());
                file.write(tailData.constData(), tailData.size());
            }
        }

        // Always dump info unless explicitly prohibited
        if ((dumpMode == DUMP_ALL || dumpMode == DUMP_CURRENT || dumpMode == DUMP_INFO)
            && (sectionType == IgnoreSectionType || model->subtype(index) == sectionType)) {
            UString info = usprintf("Type: %s\nSubtype: %s\n%s%s\n",
                itemTypeToUString(model->type(index)).toLocal8Bit(),
                itemSubtypeToUString(model->type(index), model->subtype(index)).toLocal8Bit(),
                (model->text(index).isEmpty() ? UString("") :
                    usprintf("Text: %s\n", model->text(index).toLocal8Bit())).toLocal8Bit(),
                model->info(index).toLocal8Bit());
            UString filename;
            if (counterInfo == 0)
                filename = usprintf("%s/info.txt", path.toLocal8Bit());
            else
                filename = usprintf("%s/info_%d.txt", path.toLocal8Bit(), counterInfo);
            counterInfo++;
            std::ofstream file(filename.toLocal8Bit());
            if (!file)
                return U_FILE_OPEN;
            file << info.toLocal8Bit();
        }

        dumped = true;
    }

    USTATUS result;
    for (int i = 0; i < model->rowCount(index); i++) {
        UModelIndex childIndex = index.child(i, 0);
        bool useText = FALSE;
        if (model->type(childIndex) != Types::Volume)
            useText = !model->text(childIndex).isEmpty();

        UString childPath = path;
        if (dumpMode == DUMP_ALL || dumpMode == DUMP_CURRENT)
            childPath = usprintf("%s/%d %s", path.toLocal8Bit(), i,
                (useText ? model->text(childIndex) : model->name(childIndex)).toLocal8Bit());
        result = recursiveDump(childIndex, childPath, dumpMode, sectionType, guid);
        if (result)
            return result;
    }

    return U_SUCCESS;
}
<|endoftext|>


<commit_before>/* Copyright (C) 2003 MySQL AB

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

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#ifndef NDB_VECTOR_HPP
#define NDB_VECTOR_HPP

#include <ndb_global.h>
#include <NdbMutex.h>

template<class T>
struct Vector {
public:
  Vector(int sz = 10);
  ~Vector();

  T& operator[](unsigned i);
  const T& operator[](unsigned i) const;
  unsigned size() const { return m_size; };

  void push_back(const T &);
  T& back();

  void erase(unsigned index);

  void clear();

  void fill(unsigned new_size, T & obj);

  Vector<T>& operator=(const Vector<T>&);

  T* getBase() { return m_items;}
  const T* getBase() const { return m_items;}
private:
  T * m_items;
  unsigned m_size;
  unsigned m_incSize;
  unsigned m_arraySize;
};

template<class T>
Vector<T>::Vector(int i){
  m_items = new T[i];
  m_size = 0;
  m_arraySize = i;
  m_incSize = 50;
}

template<class T>
Vector<T>::~Vector(){
  delete[] m_items;
  // safety for placement new usage
  m_items = 0;
  m_size = 0;
  m_arraySize = 0;
}

template<class T>
T &
Vector<T>::operator[](unsigned i){
  if(i >= m_size)
    abort();
  return m_items[i];
}

template<class T>
const T &
Vector<T>::operator[](unsigned i) const {
  if(i >= m_size)
    abort();
  return m_items[i];
}

template<class T>
T &
Vector<T>::back(){
  return (* this)[m_size - 1];
}

template<class T>
void
Vector<T>::push_back(const T & t){
  if(m_size == m_arraySize){
    T * tmp = new T [m_arraySize + m_incSize];
    for (unsigned k = 0; k < m_size; k++)
      tmp[k] = m_items[k];
    delete[] m_items;
    m_items = tmp;
    m_arraySize = m_arraySize + m_incSize;
  }
  m_items[m_size] = t;
  m_size++;
}

template<class T>
void
Vector<T>::erase(unsigned i){
  if(i >= m_size)
    abort();

  for (unsigned k = i; k + 1 < m_size; k++)
    m_items[k] = m_items[k + 1];
  m_size--;
}

template<class T>
void
Vector<T>::clear(){
  m_size = 0;
}

template<class T>
void
Vector<T>::fill(unsigned new_size, T & obj){
  while(m_size <= new_size)
    push_back(obj);
}

template<class T>
Vector<T>&
Vector<T>::operator=(const Vector<T>& obj){
  if(this != &obj){
    clear();
    for(size_t i = 0; i<obj.size(); i++){
      push_back(obj[i]);
    }
  }
  return * this;
}

template<class T>
struct MutexVector : public NdbLockable {
  MutexVector(int sz = 10);
  ~MutexVector();

  T& operator[](unsigned i);
  const T& operator[](unsigned i) const;
  unsigned size() const { return m_size; };

  void push_back(const T &);
  void push_back(const T &, bool lockMutex);
  T& back();

  void erase(unsigned index);
  void erase(unsigned index, bool lockMutex);

  void clear();
  void clear(bool lockMutex);

  void fill(unsigned new_size, T & obj);
private:
  T * m_items;
  unsigned m_size;
  unsigned m_incSize;
  unsigned m_arraySize;
};

template<class T>
MutexVector<T>::MutexVector(int i){
  m_items = new T[i];
  m_size = 0;
  m_arraySize = i;
  m_incSize = 50;
}

template<class T>
MutexVector<T>::~MutexVector(){
  delete[] m_items;
  // safety for placement new usage
  m_items = 0;
  m_size = 0;
  m_arraySize = 0;
}

template<class T>
T &
MutexVector<T>::operator[](unsigned i){
  if(i >= m_size)
    abort();
  return m_items[i];
}

template<class T>
const T &
MutexVector<T>::operator[](unsigned i) const {
  if(i >= m_size)
    abort();
  return m_items[i];
}

template<class T>
T &
MutexVector<T>::back(){
  return (* this)[m_size - 1];
}

template<class T>
void
MutexVector<T>::push_back(const T & t){
  lock();
  if(m_size == m_arraySize){
    T * tmp = new T [m_arraySize + m_incSize];
    for (unsigned k = 0; k < m_size; k++)
      tmp[k] = m_items[k];
    delete[] m_items;
    m_items = tmp;
    m_arraySize = m_arraySize + m_incSize;
  }
  m_items[m_size] = t;
  m_size++;
  unlock();
}

template<class T>
void
MutexVector<T>::push_back(const T & t, bool lockMutex){
  if(lockMutex)
    lock();
  if(m_size == m_arraySize){
    T * tmp = new T [m_arraySize + m_incSize];
    for (unsigned k = 0; k < m_size; k++)
      tmp[k] = m_items[k];
    delete[] m_items;
    m_items = tmp;
    m_arraySize = m_arraySize + m_incSize;
  }
  m_items[m_size] = t;
  m_size++;
  if(lockMutex)
    unlock();
}

template<class T>
void
MutexVector<T>::erase(unsigned i){
  if(i >= m_size)
    abort();

  lock();
  for (unsigned k = i; k + 1 < m_size; k++)
    m_items[k] = m_items[k + 1];
  m_size--;
  unlock();
}

template<class T>
void
MutexVector<T>::erase(unsigned i, bool _lock){
  if(i >= m_size)
    abort();

  if(_lock)
    lock();
  for (unsigned k = i; k + 1 < m_size; k++)
    m_items[k] = m_items[k + 1];
  m_size--;
  if(_lock)
    unlock();
}

template<class T>
void
MutexVector<T>::clear(){
  lock();
  m_size = 0;
  unlock();
}

template<class T>
void
MutexVector<T>::clear(bool l){
  if(l) lock();
  m_size = 0;
  if(l) unlock();
}

template<class T>
void
MutexVector<T>::fill(unsigned new_size, T & obj){
  while(m_size <= new_size)
    push_back(obj);
}

#endif
<commit_msg>BUG#22299 mgmd crash due to unchecked TransporterFacade::ThreadData expand()<commit_after>/* Copyright (C) 2003 MySQL AB

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

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#ifndef NDB_VECTOR_HPP
#define NDB_VECTOR_HPP

#include <ndb_global.h>
#include <NdbMutex.h>

template<class T>
struct Vector {
public:
  Vector(int sz = 10);
  ~Vector();

  T& operator[](unsigned i);
  const T& operator[](unsigned i) const;
  unsigned size() const { return m_size; };

  void push_back(const T &);
  T& back();

  void erase(unsigned index);

  void clear();

  void fill(unsigned new_size, T & obj);

  Vector<T>& operator=(const Vector<T>&);

  T* getBase() { return m_items;}
  const T* getBase() const { return m_items;}
private:
  T * m_items;
  unsigned m_size;
  unsigned m_incSize;
  unsigned m_arraySize;
};

template<class T>
Vector<T>::Vector(int i){
  m_items = new T[i];
  m_size = 0;
  m_arraySize = i;
  m_incSize = 50;
}

template<class T>
Vector<T>::~Vector(){
  delete[] m_items;
  // safety for placement new usage
  m_items = 0;
  m_size = 0;
  m_arraySize = 0;
}

template<class T>
T &
Vector<T>::operator[](unsigned i){
  if(i >= m_size)
    abort();
  return m_items[i];
}

template<class T>
const T &
Vector<T>::operator[](unsigned i) const {
  if(i >= m_size)
    abort();
  return m_items[i];
}

template<class T>
T &
Vector<T>::back(){
  return (* this)[m_size - 1];
}

template<class T>
void
Vector<T>::push_back(const T & t){
  if(m_size == m_arraySize){
    T * tmp = new T [m_arraySize + m_incSize];
    if(!tmp)
      abort();
    for (unsigned k = 0; k < m_size; k++)
      tmp[k] = m_items[k];
    delete[] m_items;
    m_items = tmp;
    m_arraySize = m_arraySize + m_incSize;
  }
  m_items[m_size] = t;
  m_size++;
}

template<class T>
void
Vector<T>::erase(unsigned i){
  if(i >= m_size)
    abort();

  for (unsigned k = i; k + 1 < m_size; k++)
    m_items[k] = m_items[k + 1];
  m_size--;
}

template<class T>
void
Vector<T>::clear(){
  m_size = 0;
}

template<class T>
void
Vector<T>::fill(unsigned new_size, T & obj){
  while(m_size <= new_size)
    push_back(obj);
}

template<class T>
Vector<T>&
Vector<T>::operator=(const Vector<T>& obj){
  if(this != &obj){
    clear();
    for(size_t i = 0; i<obj.size(); i++){
      push_back(obj[i]);
    }
  }
  return * this;
}

template<class T>
struct MutexVector : public NdbLockable {
  MutexVector(int sz = 10);
  ~MutexVector();

  T& operator[](unsigned i);
  const T& operator[](unsigned i) const;
  unsigned size() const { return m_size; };

  void push_back(const T &);
  void push_back(const T &, bool lockMutex);
  T& back();

  void erase(unsigned index);
  void erase(unsigned index, bool lockMutex);

  void clear();
  void clear(bool lockMutex);

  void fill(unsigned new_size, T & obj);
private:
  T * m_items;
  unsigned m_size;
  unsigned m_incSize;
  unsigned m_arraySize;
};

template<class T>
MutexVector<T>::MutexVector(int i){
  m_items = new T[i];
  m_size = 0;
  m_arraySize = i;
  m_incSize = 50;
}

template<class T>
MutexVector<T>::~MutexVector(){
  delete[] m_items;
  // safety for placement new usage
  m_items = 0;
  m_size = 0;
  m_arraySize = 0;
}

template<class T>
T &
MutexVector<T>::operator[](unsigned i){
  if(i >= m_size)
    abort();
  return m_items[i];
}

template<class T>
const T &
MutexVector<T>::operator[](unsigned i) const {
  if(i >= m_size)
    abort();
  return m_items[i];
}

template<class T>
T &
MutexVector<T>::back(){
  return (* this)[m_size - 1];
}

template<class T>
void
MutexVector<T>::push_back(const T & t){
  lock();
  if(m_size == m_arraySize){
    T * tmp = new T [m_arraySize + m_incSize];
    for (unsigned k = 0; k < m_size; k++)
      tmp[k] = m_items[k];
    delete[] m_items;
    m_items = tmp;
    m_arraySize = m_arraySize + m_incSize;
  }
  m_items[m_size] = t;
  m_size++;
  unlock();
}

template<class T>
void
MutexVector<T>::push_back(const T & t, bool lockMutex){
  if(lockMutex)
    lock();
  if(m_size == m_arraySize){
    T * tmp = new T [m_arraySize + m_incSize];
    for (unsigned k = 0; k < m_size; k++)
      tmp[k] = m_items[k];
    delete[] m_items;
    m_items = tmp;
    m_arraySize = m_arraySize + m_incSize;
  }
  m_items[m_size] = t;
  m_size++;
  if(lockMutex)
    unlock();
}

template<class T>
void
MutexVector<T>::erase(unsigned i){
  if(i >= m_size)
    abort();

  lock();
  for (unsigned k = i; k + 1 < m_size; k++)
    m_items[k] = m_items[k + 1];
  m_size--;
  unlock();
}

template<class T>
void
MutexVector<T>::erase(unsigned i, bool _lock){
  if(i >= m_size)
    abort();

  if(_lock)
    lock();
  for (unsigned k = i; k + 1 < m_size; k++)
    m_items[k] = m_items[k + 1];
  m_size--;
  if(_lock)
    unlock();
}

template<class T>
void
MutexVector<T>::clear(){
  lock();
  m_size = 0;
  unlock();
}

template<class T>
void
MutexVector<T>::clear(bool l){
  if(l) lock();
  m_size = 0;
  if(l) unlock();
}

template<class T>
void
MutexVector<T>::fill(unsigned new_size, T & obj){
  while(m_size <= new_size)
    push_back(obj);
}

#endif
<|endoftext|>


<commit_before>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2017 BMW Car IT GmbH
 * %%
 * 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.
 * #L%
 */

#include <cassert>
#include <chrono>
#include <memory>
#include <string>
#include <stdexcept>

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/program_options.hpp>

#include "joynr/JoynrRuntime.h"
#include "joynr/Logger.h"
#include "joynr/Semaphore.h"
#include "joynr/types/ProviderQos.h"
#include "joynr/types/ProviderScope.h"
#include "SystemIntegrationTestProvider.h"
#include "SitUtil.h"
#ifdef JOYNR_ENABLE_DLT_LOGGING
#include <dlt/dlt.h>
#endif // JOYNR_ENABLE_DLT_LOGGING

using namespace joynr;

int main(int argc, char* argv[])
{
#ifdef JOYNR_ENABLE_DLT_LOGGING
    // Register app at the dlt-daemon for logging
    DLT_REGISTER_APP("JYSP", argv[0]);
#endif // JOYNR_ENABLE_DLT_LOGGING

    // Get a logger
    Logger logger("ProviderApplication");

    namespace po = boost::program_options;

    po::positional_options_description positionalCmdLineOptions;
    positionalCmdLineOptions.add("domain", 1);
    positionalCmdLineOptions.add("runForever", 1);

    std::string providerDomain;
    bool runForever = false;
    std::string pathToSettings;
    std::string sslCertFilename;
    std::string sslPrivateKeyFilename;
    std::string sslCaCertFilename;

    po::options_description cmdLineOptions;
    cmdLineOptions.add_options()("domain,d", po::value(&providerDomain)->required())(
            "runForever,r", po::value(&runForever)->default_value(false))(
            "pathtosettings,p", po::value(&pathToSettings))(
            "ssl-cert-pem", po::value(&sslCertFilename))(
            "ssl-privatekey-pem", po::value(&sslPrivateKeyFilename))(
            "ssl-ca-cert-pem", po::value(&sslCaCertFilename));

    try {
        po::variables_map variablesMap;
        po::store(po::command_line_parser(argc, argv)
                          .options(cmdLineOptions)
                          .positional(positionalCmdLineOptions)
                          .run(),
                  variablesMap);
        po::notify(variablesMap);
    } catch (const std::exception& e) {
        std::cerr << e.what();
        return -1;
    }

    JOYNR_LOG_INFO(logger, "Registering provider on domain {}", providerDomain);

    if (pathToSettings.empty()) {
        boost::filesystem::path appFilename = boost::filesystem::path(argv[0]);
        std::string appDirectory =
                boost::filesystem::system_complete(appFilename).parent_path().string();
        pathToSettings = appDirectory + "/resources/systemintegrationtest-provider.settings";
    }

    const std::string pathToMessagingSettingsDefault("");
    std::shared_ptr<IKeychain> keychain;

    try {
        keychain = tryLoadKeychainFromCmdLineArgs(
                sslCertFilename, sslPrivateKeyFilename, sslCaCertFilename);
    } catch (const std::invalid_argument& e) {
        JOYNR_LOG_FATAL(logger, e.what());
        return -1;
    }

    std::shared_ptr<JoynrRuntime> runtime =
            JoynrRuntime::createRuntime(pathToSettings, pathToMessagingSettingsDefault, keychain);

    joynr::Semaphore semaphore;

    auto provider = std::make_shared<SystemIntegrationTestProvider>([&]() { semaphore.notify(); });

    joynr::types::ProviderQos providerQos;
    std::chrono::milliseconds millisSinceEpoch =
            std::chrono::duration_cast<std::chrono::milliseconds>(
                    std::chrono::system_clock::now().time_since_epoch());
    providerQos.setPriority(millisSinceEpoch.count());
    providerQos.setScope(joynr::types::ProviderScope::GLOBAL);

    // Register the provider
    runtime->registerProvider<test::SystemIntegrationTestProvider>(
            providerDomain, provider, providerQos);

    if (runForever) {
        while (true) {
            semaphore.wait();
        }
    } else {
        bool successful = semaphore.waitFor(std::chrono::milliseconds(30000));

        // Unregister the provider
        runtime->unregisterProvider<test::SystemIntegrationTestProvider>(providerDomain, provider);

        return successful ? 0 : -1;
    }
}
<commit_msg>[C++] Catch exceptions in ProviderApplication to avoid std::terminate<commit_after>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2017 BMW Car IT GmbH
 * %%
 * 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.
 * #L%
 */

#include <cassert>
#include <chrono>
#include <memory>
#include <string>
#include <stdexcept>

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/program_options.hpp>

#include "joynr/JoynrRuntime.h"
#include "joynr/Logger.h"
#include "joynr/Semaphore.h"
#include "joynr/types/ProviderQos.h"
#include "joynr/types/ProviderScope.h"
#include "SystemIntegrationTestProvider.h"
#include "SitUtil.h"
#ifdef JOYNR_ENABLE_DLT_LOGGING
#include <dlt/dlt.h>
#endif // JOYNR_ENABLE_DLT_LOGGING

using namespace joynr;

int main(int argc, char* argv[])
{
#ifdef JOYNR_ENABLE_DLT_LOGGING
    // Register app at the dlt-daemon for logging
    DLT_REGISTER_APP("JYSP", argv[0]);
#endif // JOYNR_ENABLE_DLT_LOGGING

    // Get a logger
    Logger logger("ProviderApplication");

    namespace po = boost::program_options;

    po::positional_options_description positionalCmdLineOptions;
    positionalCmdLineOptions.add("domain", 1);
    positionalCmdLineOptions.add("runForever", 1);

    std::string providerDomain;
    bool runForever = false;
    std::string pathToSettings;
    std::string sslCertFilename;
    std::string sslPrivateKeyFilename;
    std::string sslCaCertFilename;

    po::options_description cmdLineOptions;
    cmdLineOptions.add_options()("domain,d", po::value(&providerDomain)->required())(
            "runForever,r", po::value(&runForever)->default_value(false))(
            "pathtosettings,p", po::value(&pathToSettings))(
            "ssl-cert-pem", po::value(&sslCertFilename))(
            "ssl-privatekey-pem", po::value(&sslPrivateKeyFilename))(
            "ssl-ca-cert-pem", po::value(&sslCaCertFilename));

    try {
        po::variables_map variablesMap;
        po::store(po::command_line_parser(argc, argv)
                          .options(cmdLineOptions)
                          .positional(positionalCmdLineOptions)
                          .run(),
                  variablesMap);
        po::notify(variablesMap);
    } catch (const std::exception& e) {
        std::cerr << e.what();
        return EXIT_FAILURE;
    }

    JOYNR_LOG_INFO(logger, "Registering provider on domain {}", providerDomain);

    if (pathToSettings.empty()) {
        boost::filesystem::path appFilename = boost::filesystem::path(argv[0]);
        std::string appDirectory =
                boost::filesystem::system_complete(appFilename).parent_path().string();
        pathToSettings = appDirectory + "/resources/systemintegrationtest-provider.settings";
    }

    const std::string pathToMessagingSettingsDefault("");
    std::shared_ptr<IKeychain> keychain;

    try {
        keychain = tryLoadKeychainFromCmdLineArgs(
                sslCertFilename, sslPrivateKeyFilename, sslCaCertFilename);
    } catch (const std::invalid_argument& e) {
        JOYNR_LOG_FATAL(logger, e.what());
        return EXIT_FAILURE;
    }

    try {
        std::shared_ptr<JoynrRuntime> runtime = JoynrRuntime::createRuntime(
                pathToSettings, pathToMessagingSettingsDefault, keychain);

        joynr::Semaphore semaphore;

        auto provider =
                std::make_shared<SystemIntegrationTestProvider>([&]() { semaphore.notify(); });

        joynr::types::ProviderQos providerQos;
        std::chrono::milliseconds millisSinceEpoch =
                std::chrono::duration_cast<std::chrono::milliseconds>(
                        std::chrono::system_clock::now().time_since_epoch());
        providerQos.setPriority(millisSinceEpoch.count());
        providerQos.setScope(joynr::types::ProviderScope::GLOBAL);

        // Register the provider
        runtime->registerProvider<test::SystemIntegrationTestProvider>(
                providerDomain, provider, providerQos);

        if (runForever) {
            while (true) {
                semaphore.wait();
            }
        } else {
            bool successful = semaphore.waitFor(std::chrono::milliseconds(30000));

            // Unregister the provider
            runtime->unregisterProvider<test::SystemIntegrationTestProvider>(
                    providerDomain, provider);

            return successful ? EXIT_SUCCESS : EXIT_FAILURE;
        }
    } catch (exceptions::JoynrRuntimeException& e) {
        JOYNR_LOG_FATAL(logger, e.what());
        return EXIT_FAILURE;
    }
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 * Point Cloud Library (PCL) - www.pointclouds.org
 * Copyright (c) 2009-2011, Willow Garage, Inc.
 *
 * 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 Willow Garage, Inc. 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 OWNER 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.
 *
 * $Id$
 *
 *
 */

// STL
#include <iostream>

// PCL
#include <boost/thread/thread.hpp>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/features/normal_3d.h>
#include <pcl/kdtree/kdtree.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/segmentation/extract_clusters.h>

int
main(int argc, char **argv)
{
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr (new pcl::PointCloud<pcl::PointXYZ> ());
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal> ());
  pcl::PCDWriter writer;

  if(pcl::io::loadPCDFile<pcl::PointXYZ> (argv[1], *cloud_ptr) == -1)
  {
    cout<<"Couldn't read the file "<<argv[1]<<endl;
    return -1;
  }
  std::cout << "Loaded pcd file " << argv[1] << " with " << cloud_ptr->points.size () << std::endl;

  // Normal estimation
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
  ne.setInputCloud(cloud_ptr);

  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree_n (new pcl::search::KdTree<pcl::PointXYZ>());
  ne.setSearchMethod(tree_n);
  ne.setRadiusSearch(0.03);
  ne.compute(*cloud_normals);
  std::cout << "Estimated the normals" << std::endl;

  // Creating the kdtree object for the search method of the extraction
  boost::shared_ptr<pcl::KdTree<pcl::PointXYZ> > tree_ec  (new pcl::KdTreeFLANN<pcl::PointXYZ> ());
  tree_ec->setInputCloud (cloud_ptr);

  // Extracting Euclidean clusters using cloud and its normals
  std::vector<int> indices;
  std::vector<pcl::PointIndices> cluster_indices;
  const float tolerance = 0.5f; // 50cm tolerance in (x, y, z) coordinate system
  const double eps_angle = 5*(M_PI/180); // 5degree tolerance in normals
  const unsigned int min_cluster_size = 50;

  pcl::extractEuclideanClusters(*cloud_ptr, *cloud_normals, tolerance, tree_ec, cluster_indices, eps_angle, min_cluster_size);

  std::cout << "No of clusters formed are " << cluster_indices.size () << std::endl;

  int j = 0;
  for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
  {
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>);
    for (std::vector<int>::const_iterator pit = it->indices.begin (); pit != it->indices.end (); pit++)
      cloud_cluster->points.push_back (cloud_ptr->points[*pit]);
    cloud_cluster->width = cloud_cluster->points.size ();
    cloud_cluster->height = 1;
    cloud_cluster->is_dense = true;

    std::cout << "PointCloud representing the Cluster using xyzn: " << cloud_cluster->points.size () << " data points." << std::endl;
    std::stringstream ss;
    ss << "./cloud_cluster_" << j << ".pcd";
    writer.write<pcl::PointXYZ> (ss.str (), *cloud_cluster, false);
    j++;
  }

  return 0;
}
<commit_msg>adding some comments to example_extract_clusters_normals.cpp<commit_after>/*
 * Software License Agreement (BSD License)
 *
 * Point Cloud Library (PCL) - www.pointclouds.org
 * Copyright (c) 2009-2011, Willow Garage, Inc.
 *
 * 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 Willow Garage, Inc. 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 OWNER 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.
 *
 * $Id$
 *
 *
 */

// STL
#include <iostream>

// PCL
#include <boost/thread/thread.hpp>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/features/normal_3d.h>
#include <pcl/kdtree/kdtree.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/segmentation/extract_clusters.h>

int
main(int argc, char **argv)
{
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr (new pcl::PointCloud<pcl::PointXYZ> ());
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal> ());
  pcl::PCDWriter writer;

  if(pcl::io::loadPCDFile<pcl::PointXYZ> (argv[1], *cloud_ptr) == -1)
  {
    cout<<"Couldn't read the file "<<argv[1]<<endl;
    return -1;
  }
  std::cout << "Loaded pcd file " << argv[1] << " with " << cloud_ptr->points.size () << std::endl;

  // Normal estimation
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
  ne.setInputCloud(cloud_ptr);

  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree_n (new pcl::search::KdTree<pcl::PointXYZ>());
  ne.setSearchMethod(tree_n);
  ne.setRadiusSearch(0.03);
  ne.compute(*cloud_normals);
  std::cout << "Estimated the normals" << std::endl;

  // Creating the kdtree object for the search method of the extraction
  boost::shared_ptr<pcl::KdTree<pcl::PointXYZ> > tree_ec  (new pcl::KdTreeFLANN<pcl::PointXYZ> ());
  tree_ec->setInputCloud (cloud_ptr);

  // Extracting Euclidean clusters using cloud and its normals
  std::vector<int> indices;
  std::vector<pcl::PointIndices> cluster_indices;
  const float tolerance = 0.5f; // 50cm tolerance in (x, y, z) coordinate system
  const double eps_angle = 5*(M_PI/180); // 5degree tolerance in normals
  const unsigned int min_cluster_size = 50;

  pcl::extractEuclideanClusters(*cloud_ptr, *cloud_normals, tolerance, tree_ec, cluster_indices, eps_angle, min_cluster_size);

  std::cout << "No of clusters formed are " << cluster_indices.size () << std::endl;

  // Saving the clusters in seperate pcd files
  int j = 0;
  for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
  {
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>);
    for (std::vector<int>::const_iterator pit = it->indices.begin (); pit != it->indices.end (); pit++)
      cloud_cluster->points.push_back (cloud_ptr->points[*pit]);
    cloud_cluster->width = cloud_cluster->points.size ();
    cloud_cluster->height = 1;
    cloud_cluster->is_dense = true;

    std::cout << "PointCloud representing the Cluster using xyzn: " << cloud_cluster->points.size () << " data points." << std::endl;
    std::stringstream ss;
    ss << "./cloud_cluster_" << j << ".pcd";
    writer.write<pcl::PointXYZ> (ss.str (), *cloud_cluster, false);
    j++;
  }

  return 0;
}
<|endoftext|>