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

/*! \file arch.inl
 *  \brief Inline file for arch.h.
 */

#include <string>
#include <algorithm>

#include <thrust/detail/util/blocking.h>

// #include this for make_uint3
#include <vector_functions.h>

// #include this for runtime_error
#include <stdexcept>

namespace thrust
{
namespace experimental
{
namespace arch
{
namespace detail
{

inline void checked_get_current_device_properties(cudaDeviceProp &props)
{
  int current_device = -1;

  cudaError_t error = cudaGetDevice(&current_device);

  if(error)
    throw std::runtime_error(std::string("CUDA error: ") + std::string(cudaGetErrorString(error)));

  if(current_device < 0)
    throw std::runtime_error(std::string("No CUDA device found."));

  error = cudaGetDeviceProperties(&props, current_device);

  if(error != cudaSuccess)
    throw std::runtime_error(std::string("CUDA error: ") + std::string(cudaGetErrorString(error)));
} // end checked_get_current_device_properties()

template <typename KernelFunction>
void checked_get_function_attributes(cudaFuncAttributes& attributes, KernelFunction kernel)
{
  cudaError_t error = cudaFuncGetAttributes(&attributes, kernel);

  if(error != cudaSuccess)
    throw std::runtime_error(std::string("CUDA error: ") + std::string(cudaGetErrorString(error)));
} // end checked_get_function_attributes()

} // end detail

size_t num_multiprocessors(const cudaDeviceProp& properties)
{
    return properties.multiProcessorCount;
} // end num_multiprocessors()

size_t max_active_threads_per_multiprocessor(const cudaDeviceProp& properties)
{
    // index this array by [major, minor] revision
    // \see NVIDIA_CUDA_Programming_Guide_2.1.pdf pp 82--83
    static const size_t max_active_threads_by_compute_capability[2][4] = \
        {{     0,    0,    0,    0},
         {   768,  768, 1024, 1024}};

    // produce valid results for new, unknown devices
    if (properties.major > 1 || properties.minor > 3)
        return max_active_threads_by_compute_capability[1][3];
    else
        return max_active_threads_by_compute_capability[properties.major][properties.minor];
} // end max_active_threads_per_multiprocessor()

size_t max_active_threads(const cudaDeviceProp& properties)
{
    return num_multiprocessors(properties) * max_active_threads_per_multiprocessor(properties);
} // end max_active_threads()

dim3 max_grid_dimensions(const cudaDeviceProp& properties)
{
    return make_uint3(properties.maxGridSize[0], properties.maxGridSize[1], properties.maxGridSize[2]);
} // end max_grid_dimensions()

size_t max_active_blocks_per_multiprocessor(const cudaDeviceProp& properties,
                                            const cudaFuncAttributes& attributes,
                                            size_t CTA_SIZE,
                                            size_t dynamic_smem_bytes)
{
    // Determine the maximum number of CTAs that can be run simultaneously per SM
    // This is equivalent to the calculation done in the CUDA Occupancy Calculator spreadsheet
    const size_t regAllocationUnit = (properties.major < 2 && properties.minor < 2) ? 256 : 512; // in registers
    const size_t warpAllocationMultiple = 2;
    const size_t smemAllocationUnit = 512;                                                 // in bytes
    const size_t maxThreadsPerSM = max_active_threads_per_multiprocessor(properties);      // 768, 1024, etc.
    const size_t maxBlocksPerSM = 8;

    // Number of warps (round up to nearest whole multiple of warp size & warp allocation multiple)
    const size_t numWarps = thrust::detail::util::round_i(thrust::detail::util::divide_ri(CTA_SIZE, properties.warpSize), warpAllocationMultiple);

    // Number of regs is regs per thread times number of warps times warp size
    const size_t regsPerCTA = thrust::detail::util::round_i(attributes.numRegs * properties.warpSize * numWarps, regAllocationUnit);

    const size_t smemBytes  = attributes.sharedSizeBytes + dynamic_smem_bytes;
    const size_t smemPerCTA = thrust::detail::util::round_i(smemBytes, smemAllocationUnit);

    const size_t ctaLimitRegs    = regsPerCTA > 0 ? properties.regsPerBlock / regsPerCTA : maxBlocksPerSM;
    const size_t ctaLimitSMem    = smemPerCTA > 0 ? properties.sharedMemPerBlock   / smemPerCTA : maxBlocksPerSM;
    const size_t ctaLimitThreads =                  maxThreadsPerSM                / CTA_SIZE;

    return std::min<size_t>(ctaLimitRegs, std::min<size_t>(ctaLimitSMem, std::min<size_t>(ctaLimitThreads, maxBlocksPerSM)));
}

// Functions that query the runtime for device properties

size_t num_multiprocessors(void)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);
    return num_multiprocessors(properties);
} // end num_multiprocessors()

size_t max_active_threads_per_multiprocessor(void)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);
    return max_active_threads_per_multiprocessor(properties);
}

size_t max_active_threads(void)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);
    return max_active_threads(properties);
}

dim3 max_grid_dimensions(void)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);
    return max_grid_dimensions(properties);
}

template <typename KernelFunction>
size_t max_active_blocks(KernelFunction kernel, const size_t CTA_SIZE, const size_t dynamic_smem_bytes)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);

    cudaFuncAttributes attributes;
    detail::checked_get_function_attributes(attributes, kernel);

    return num_multiprocessors(properties) * max_active_blocks_per_multiprocessor(properties, attributes, CTA_SIZE, dynamic_smem_bytes);
}

size_t max_blocksize_with_highest_occupancy(const cudaDeviceProp& properties,
                                            const cudaFuncAttributes& attributes,
                                            size_t dynamic_smem_bytes_per_thread)
{
    size_t max_occupancy = max_active_threads_per_multiprocessor(properties);

    size_t largest_blocksize  = std::min(properties.maxThreadsPerBlock, attributes.maxThreadsPerBlock);
    size_t granularity        = 32;

    size_t max_blocksize     = 0;
    size_t highest_occupancy = 0;

    for(size_t blocksize = largest_blocksize; blocksize != 0; blocksize -= granularity)
    {
        size_t occupancy = blocksize * max_active_blocks_per_multiprocessor(properties, attributes, blocksize, dynamic_smem_bytes_per_thread * blocksize);

        if (occupancy > highest_occupancy)
        {
            max_blocksize = blocksize;
            highest_occupancy = occupancy;
        }

        // early out, can't do better
        if (highest_occupancy == max_occupancy)
            return max_blocksize;
    }

    return max_blocksize;
}

template <typename KernelFunction>
size_t max_blocksize_with_highest_occupancy(KernelFunction kernel, size_t dynamic_smem_bytes_per_thread)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);

    cudaFuncAttributes attributes;
    detail::checked_get_function_attributes(attributes, kernel);

    return max_blocksize_with_highest_occupancy(properties, attributes, dynamic_smem_bytes_per_thread);
}

// TODO unify this with max_blocksize_with_highest_occupancy
size_t max_blocksize(const cudaDeviceProp& properties,
                     const cudaFuncAttributes& attributes,
                     size_t dynamic_smem_bytes_per_thread)
{
    size_t max_occupancy = max_active_threads_per_multiprocessor(properties);

    size_t largest_blocksize  = std::min(properties.maxThreadsPerBlock, attributes.maxThreadsPerBlock);
    size_t granularity        = 32;

    for(size_t blocksize = largest_blocksize; blocksize != 0; blocksize -= granularity)
    {
        if(0 < max_active_blocks_per_multiprocessor(properties, attributes, blocksize, dynamic_smem_bytes_per_thread * blocksize))
            return blocksize;
    }

    return 0;
}

template <typename KernelFunction>
size_t max_blocksize(KernelFunction kernel, size_t dynamic_smem_bytes_per_thread)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);

    cudaFuncAttributes attributes;
    detail::checked_get_function_attributes(attributes, kernel);

    return max_blocksize(properties, attributes, dynamic_smem_bytes_per_thread);
}

} // end namespace arch
} // end namespace experimental
} // end namespace thrust

<commit_msg>Eliminate unused variable from arch::max_blocksize<commit_after>/*
 *  Copyright 2008-2009 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/*! \file arch.inl
 *  \brief Inline file for arch.h.
 */

#include <string>
#include <algorithm>

#include <thrust/detail/util/blocking.h>

// #include this for make_uint3
#include <vector_functions.h>

// #include this for runtime_error
#include <stdexcept>

namespace thrust
{
namespace experimental
{
namespace arch
{
namespace detail
{

inline void checked_get_current_device_properties(cudaDeviceProp &props)
{
  int current_device = -1;

  cudaError_t error = cudaGetDevice(&current_device);

  if(error)
    throw std::runtime_error(std::string("CUDA error: ") + std::string(cudaGetErrorString(error)));

  if(current_device < 0)
    throw std::runtime_error(std::string("No CUDA device found."));

  error = cudaGetDeviceProperties(&props, current_device);

  if(error != cudaSuccess)
    throw std::runtime_error(std::string("CUDA error: ") + std::string(cudaGetErrorString(error)));
} // end checked_get_current_device_properties()

template <typename KernelFunction>
void checked_get_function_attributes(cudaFuncAttributes& attributes, KernelFunction kernel)
{
  cudaError_t error = cudaFuncGetAttributes(&attributes, kernel);

  if(error != cudaSuccess)
    throw std::runtime_error(std::string("CUDA error: ") + std::string(cudaGetErrorString(error)));
} // end checked_get_function_attributes()

} // end detail

size_t num_multiprocessors(const cudaDeviceProp& properties)
{
    return properties.multiProcessorCount;
} // end num_multiprocessors()

size_t max_active_threads_per_multiprocessor(const cudaDeviceProp& properties)
{
    // index this array by [major, minor] revision
    // \see NVIDIA_CUDA_Programming_Guide_2.1.pdf pp 82--83
    static const size_t max_active_threads_by_compute_capability[2][4] = \
        {{     0,    0,    0,    0},
         {   768,  768, 1024, 1024}};

    // produce valid results for new, unknown devices
    if (properties.major > 1 || properties.minor > 3)
        return max_active_threads_by_compute_capability[1][3];
    else
        return max_active_threads_by_compute_capability[properties.major][properties.minor];
} // end max_active_threads_per_multiprocessor()

size_t max_active_threads(const cudaDeviceProp& properties)
{
    return num_multiprocessors(properties) * max_active_threads_per_multiprocessor(properties);
} // end max_active_threads()

dim3 max_grid_dimensions(const cudaDeviceProp& properties)
{
    return make_uint3(properties.maxGridSize[0], properties.maxGridSize[1], properties.maxGridSize[2]);
} // end max_grid_dimensions()

size_t max_active_blocks_per_multiprocessor(const cudaDeviceProp& properties,
                                            const cudaFuncAttributes& attributes,
                                            size_t CTA_SIZE,
                                            size_t dynamic_smem_bytes)
{
    // Determine the maximum number of CTAs that can be run simultaneously per SM
    // This is equivalent to the calculation done in the CUDA Occupancy Calculator spreadsheet
    const size_t regAllocationUnit = (properties.major < 2 && properties.minor < 2) ? 256 : 512; // in registers
    const size_t warpAllocationMultiple = 2;
    const size_t smemAllocationUnit = 512;                                                 // in bytes
    const size_t maxThreadsPerSM = max_active_threads_per_multiprocessor(properties);      // 768, 1024, etc.
    const size_t maxBlocksPerSM = 8;

    // Number of warps (round up to nearest whole multiple of warp size & warp allocation multiple)
    const size_t numWarps = thrust::detail::util::round_i(thrust::detail::util::divide_ri(CTA_SIZE, properties.warpSize), warpAllocationMultiple);

    // Number of regs is regs per thread times number of warps times warp size
    const size_t regsPerCTA = thrust::detail::util::round_i(attributes.numRegs * properties.warpSize * numWarps, regAllocationUnit);

    const size_t smemBytes  = attributes.sharedSizeBytes + dynamic_smem_bytes;
    const size_t smemPerCTA = thrust::detail::util::round_i(smemBytes, smemAllocationUnit);

    const size_t ctaLimitRegs    = regsPerCTA > 0 ? properties.regsPerBlock / regsPerCTA : maxBlocksPerSM;
    const size_t ctaLimitSMem    = smemPerCTA > 0 ? properties.sharedMemPerBlock   / smemPerCTA : maxBlocksPerSM;
    const size_t ctaLimitThreads =                  maxThreadsPerSM                / CTA_SIZE;

    return std::min<size_t>(ctaLimitRegs, std::min<size_t>(ctaLimitSMem, std::min<size_t>(ctaLimitThreads, maxBlocksPerSM)));
}

// Functions that query the runtime for device properties

size_t num_multiprocessors(void)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);
    return num_multiprocessors(properties);
} // end num_multiprocessors()

size_t max_active_threads_per_multiprocessor(void)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);
    return max_active_threads_per_multiprocessor(properties);
}

size_t max_active_threads(void)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);
    return max_active_threads(properties);
}

dim3 max_grid_dimensions(void)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);
    return max_grid_dimensions(properties);
}

template <typename KernelFunction>
size_t max_active_blocks(KernelFunction kernel, const size_t CTA_SIZE, const size_t dynamic_smem_bytes)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);

    cudaFuncAttributes attributes;
    detail::checked_get_function_attributes(attributes, kernel);

    return num_multiprocessors(properties) * max_active_blocks_per_multiprocessor(properties, attributes, CTA_SIZE, dynamic_smem_bytes);
}

size_t max_blocksize_with_highest_occupancy(const cudaDeviceProp& properties,
                                            const cudaFuncAttributes& attributes,
                                            size_t dynamic_smem_bytes_per_thread)
{
    size_t max_occupancy = max_active_threads_per_multiprocessor(properties);

    size_t largest_blocksize  = std::min(properties.maxThreadsPerBlock, attributes.maxThreadsPerBlock);
    size_t granularity        = 32;

    size_t max_blocksize     = 0;
    size_t highest_occupancy = 0;

    for(size_t blocksize = largest_blocksize; blocksize != 0; blocksize -= granularity)
    {
        size_t occupancy = blocksize * max_active_blocks_per_multiprocessor(properties, attributes, blocksize, dynamic_smem_bytes_per_thread * blocksize);

        if (occupancy > highest_occupancy)
        {
            max_blocksize = blocksize;
            highest_occupancy = occupancy;
        }

        // early out, can't do better
        if (highest_occupancy == max_occupancy)
            return max_blocksize;
    }

    return max_blocksize;
}

template <typename KernelFunction>
size_t max_blocksize_with_highest_occupancy(KernelFunction kernel, size_t dynamic_smem_bytes_per_thread)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);

    cudaFuncAttributes attributes;
    detail::checked_get_function_attributes(attributes, kernel);

    return max_blocksize_with_highest_occupancy(properties, attributes, dynamic_smem_bytes_per_thread);
}

// TODO unify this with max_blocksize_with_highest_occupancy
size_t max_blocksize(const cudaDeviceProp& properties,
                     const cudaFuncAttributes& attributes,
                     size_t dynamic_smem_bytes_per_thread)
{
    size_t largest_blocksize  = std::min(properties.maxThreadsPerBlock, attributes.maxThreadsPerBlock);
    size_t granularity        = 32;

    for(size_t blocksize = largest_blocksize; blocksize != 0; blocksize -= granularity)
    {
        if(0 < max_active_blocks_per_multiprocessor(properties, attributes, blocksize, dynamic_smem_bytes_per_thread * blocksize))
            return blocksize;
    }

    return 0;
}

template <typename KernelFunction>
size_t max_blocksize(KernelFunction kernel, size_t dynamic_smem_bytes_per_thread)
{
    cudaDeviceProp properties;
    detail::checked_get_current_device_properties(properties);

    cudaFuncAttributes attributes;
    detail::checked_get_function_attributes(attributes, kernel);

    return max_blocksize(properties, attributes, dynamic_smem_bytes_per_thread);
}

} // end namespace arch
} // end namespace experimental
} // end namespace thrust

<|endoftext|>


<commit_before>#include "tools/cabana/chartswidget.h"

#include <QGraphicsLayout>
#include <QLabel>
#include <QPushButton>
#include <QRubberBand>
#include <QStackedLayout>
#include <QtCharts/QLineSeries>
#include <QtCharts/QValueAxis>

int64_t get_raw_value(uint8_t *data, size_t data_size, const Signal &sig) {
  int64_t ret = 0;

  int i = sig.msb / 8;
  int bits = sig.size;
  while (i >= 0 && i < data_size && bits > 0) {
    int lsb = (int)(sig.lsb / 8) == i ? sig.lsb : i * 8;
    int msb = (int)(sig.msb / 8) == i ? sig.msb : (i + 1) * 8 - 1;
    int size = msb - lsb + 1;

    uint64_t d = (data[i] >> (lsb - (i * 8))) & ((1ULL << size) - 1);
    ret |= d << (bits - size);

    bits -= size;
    i = sig.is_little_endian ? i - 1 : i + 1;
  }
  return ret;
}

ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) {
  main_layout = new QVBoxLayout(this);
  main_layout->setContentsMargins(0, 0, 0, 0);
  connect(parser, &Parser::showPlot, this, &ChartsWidget::addChart);
  connect(parser, &Parser::hidePlot, this, &ChartsWidget::removeChart);
  connect(parser, &Parser::signalRemoved, this, &ChartsWidget::removeChart);
}

void ChartsWidget::addChart(const QString &id, const QString &sig_name) {
  const QString char_name = id + sig_name;
  if (charts.find(char_name) == charts.end()) {
    auto chart = new ChartWidget(id, sig_name, this);
    main_layout->insertWidget(0, chart);
    charts[char_name] = chart;
  }
}

void ChartsWidget::removeChart(const QString &id, const QString &sig_name) {
  if (auto it = charts.find(id + sig_name); it != charts.end()) {
    it->second->deleteLater();
    charts.erase(it);
  }
}

ChartWidget::ChartWidget(const QString &id, const QString &sig_name, QWidget *parent) : id(id), sig_name(sig_name), QWidget(parent) {
  QStackedLayout *stacked = new QStackedLayout(this);
  stacked->setStackingMode(QStackedLayout::StackAll);

  QWidget *chart_widget = new QWidget(this);
  QVBoxLayout *chart_layout = new QVBoxLayout(chart_widget);
  chart_layout->setSpacing(0);
  chart_layout->setContentsMargins(0, 0, 0, 0);

  QWidget *header = new QWidget(this);
  header->setStyleSheet("background-color:white");
  QHBoxLayout *header_layout = new QHBoxLayout(header);
  header_layout->setContentsMargins(11, 11, 11, 0);
  auto title = new QLabel(tr("%1 %2").arg(parser->getMsg(id)->name.c_str()).arg(id));
  header_layout->addWidget(title);
  header_layout->addStretch();
  zoom_label = new QLabel("", this);
  header_layout->addWidget(zoom_label);
  QPushButton *zoom_in = new QPushButton("↺", this);
  zoom_in->setToolTip(tr("reset zoom"));
  QObject::connect(zoom_in, &QPushButton::clicked, []() { parser->resetRange(); });
  header_layout->addWidget(zoom_in);

  QPushButton *remove_btn = new QPushButton("✖", this);
  QObject::connect(remove_btn, &QPushButton::clicked, [=]() {
    emit parser->hidePlot(id, sig_name);
  });
  header_layout->addWidget(remove_btn);
  chart_layout->addWidget(header);

  QLineSeries *series = new QLineSeries();
  series->setUseOpenGL(true);
  auto chart = new QChart();
  chart->setTitle(sig_name);
  chart->addSeries(series);
  chart->createDefaultAxes();
  chart->legend()->hide();
  QFont font;
  font.setBold(true);
  chart->setTitleFont(font);
  chart->setMargins({0, 0, 0, 0});
  chart->layout()->setContentsMargins(0, 0, 0, 0);
  QObject::connect(dynamic_cast<QValueAxis *>(chart->axisX()), &QValueAxis::rangeChanged, parser, &Parser::setRange);

  chart_view = new QChartView(chart);
  chart_view->setFixedHeight(300);
  chart_view->setRenderHint(QPainter::Antialiasing);
  chart_view->setRubberBand(QChartView::HorizontalRubberBand);
  if (auto rubber = chart_view->findChild<QRubberBand *>()) {
    QPalette pal;
    pal.setBrush(QPalette::Base, QColor(0, 0, 0, 80));
    rubber->setPalette(pal);
  }
  chart_layout->addWidget(chart_view);
  chart_layout->addStretch();

  stacked->addWidget(chart_widget);
  line_marker = new LineMarker(chart, this);
  stacked->addWidget(line_marker);
  line_marker->setAttribute(Qt::WA_TransparentForMouseEvents, true);
  line_marker->raise();

  setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  QObject::connect(parser, &Parser::updated, this, &ChartWidget::updateState);
  QObject::connect(parser, &Parser::rangeChanged, this, &ChartWidget::rangeChanged);
  QObject::connect(parser, &Parser::eventsMerged, this, &ChartWidget::updateSeries);

  updateSeries();
}

void ChartWidget::updateState() {
  line_marker->update();
}

void ChartWidget::updateSeries() {
  const Signal *sig = parser->getSig(id, sig_name);
  auto events = parser->replay->events();
  if (!sig || !events) return;

  auto l = id.split(':');
  int bus = l[0].toInt();
  uint32_t address = l[1].toUInt(nullptr, 16);

  vals.clear();
  vals.reserve(3 * 60 * 100);
  uint64_t route_start_time = parser->replay->routeStartTime();
  for (auto &evt : *events) {
    if (evt->which == cereal::Event::Which::CAN) {
      for (auto c : evt->event.getCan()) {
        if (bus == c.getSrc() && address == c.getAddress()) {
          auto dat = c.getDat();
          int64_t val = get_raw_value((uint8_t *)dat.begin(), dat.size(), *sig);
          if (sig->is_signed) {
            val -= ((val >> (sig->size - 1)) & 0x1) ? (1ULL << sig->size) : 0;
          }
          double value = val * sig->factor + sig->offset;
          double ts = (evt->mono_time - route_start_time) / (double)1e9;  // seconds
          vals.push_back({ts, value});
        }
      }
    }
  }
  QLineSeries *series = (QLineSeries *)chart_view->chart()->series()[0];
  series->replace(vals);
  auto [begin, end] = parser->range();
  chart_view->chart()->axisX()->setRange(begin, end);
}

void ChartWidget::rangeChanged(qreal min, qreal max) {
  auto axis_x = dynamic_cast<QValueAxis *>(chart_view->chart()->axisX());
  if (axis_x->min() != min || axis_x->max() != max) {
    axis_x->setRange(min, max);
  }
  // auto zoom on yaxis
  double min_y = 0, max_y = 0;
  for (auto &p : vals) {
    if (p.x() > max) break;

    if (p.x() >= min) {
      if (p.y() < min_y) min_y = p.y();
      if (p.y() > max_y) max_y = p.y();
    }
  }
  chart_view->chart()->axisY()->setRange(min_y * 0.95, max_y * 1.05);
}

LineMarker::LineMarker(QChart *chart, QWidget *parent) : chart(chart), QWidget(parent) {}

void LineMarker::paintEvent(QPaintEvent *event) {
  auto axis_x = dynamic_cast<QValueAxis *>(chart->axisX());
  if (axis_x->max() <= axis_x->min()) return;

  double x = chart->plotArea().left() + chart->plotArea().width() * (parser->currentSec() - axis_x->min()) / (axis_x->max() - axis_x->min());
  QPainter p(this);
  QPen pen = QPen(Qt::black);
  pen.setWidth(2);
  p.setPen(pen);
  p.drawLine(QPointF{x, 50.}, QPointF{x, (qreal)height() - 11});
}
<commit_msg>cabana: Fix the incorrect Y axis (#25984)<commit_after>#include "tools/cabana/chartswidget.h"

#include <QGraphicsLayout>
#include <QLabel>
#include <QPushButton>
#include <QRubberBand>
#include <QStackedLayout>
#include <QtCharts/QLineSeries>
#include <QtCharts/QValueAxis>

int64_t get_raw_value(uint8_t *data, size_t data_size, const Signal &sig) {
  int64_t ret = 0;

  int i = sig.msb / 8;
  int bits = sig.size;
  while (i >= 0 && i < data_size && bits > 0) {
    int lsb = (int)(sig.lsb / 8) == i ? sig.lsb : i * 8;
    int msb = (int)(sig.msb / 8) == i ? sig.msb : (i + 1) * 8 - 1;
    int size = msb - lsb + 1;

    uint64_t d = (data[i] >> (lsb - (i * 8))) & ((1ULL << size) - 1);
    ret |= d << (bits - size);

    bits -= size;
    i = sig.is_little_endian ? i - 1 : i + 1;
  }
  return ret;
}

ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) {
  main_layout = new QVBoxLayout(this);
  main_layout->setContentsMargins(0, 0, 0, 0);
  connect(parser, &Parser::showPlot, this, &ChartsWidget::addChart);
  connect(parser, &Parser::hidePlot, this, &ChartsWidget::removeChart);
  connect(parser, &Parser::signalRemoved, this, &ChartsWidget::removeChart);
}

void ChartsWidget::addChart(const QString &id, const QString &sig_name) {
  const QString char_name = id + sig_name;
  if (charts.find(char_name) == charts.end()) {
    auto chart = new ChartWidget(id, sig_name, this);
    main_layout->insertWidget(0, chart);
    charts[char_name] = chart;
  }
}

void ChartsWidget::removeChart(const QString &id, const QString &sig_name) {
  if (auto it = charts.find(id + sig_name); it != charts.end()) {
    it->second->deleteLater();
    charts.erase(it);
  }
}

ChartWidget::ChartWidget(const QString &id, const QString &sig_name, QWidget *parent) : id(id), sig_name(sig_name), QWidget(parent) {
  QStackedLayout *stacked = new QStackedLayout(this);
  stacked->setStackingMode(QStackedLayout::StackAll);

  QWidget *chart_widget = new QWidget(this);
  QVBoxLayout *chart_layout = new QVBoxLayout(chart_widget);
  chart_layout->setSpacing(0);
  chart_layout->setContentsMargins(0, 0, 0, 0);

  QWidget *header = new QWidget(this);
  header->setStyleSheet("background-color:white");
  QHBoxLayout *header_layout = new QHBoxLayout(header);
  header_layout->setContentsMargins(11, 11, 11, 0);
  auto title = new QLabel(tr("%1 %2").arg(parser->getMsg(id)->name.c_str()).arg(id));
  header_layout->addWidget(title);
  header_layout->addStretch();
  zoom_label = new QLabel("", this);
  header_layout->addWidget(zoom_label);
  QPushButton *zoom_in = new QPushButton("↺", this);
  zoom_in->setToolTip(tr("reset zoom"));
  QObject::connect(zoom_in, &QPushButton::clicked, []() { parser->resetRange(); });
  header_layout->addWidget(zoom_in);

  QPushButton *remove_btn = new QPushButton("✖", this);
  QObject::connect(remove_btn, &QPushButton::clicked, [=]() {
    emit parser->hidePlot(id, sig_name);
  });
  header_layout->addWidget(remove_btn);
  chart_layout->addWidget(header);

  QLineSeries *series = new QLineSeries();
  series->setUseOpenGL(true);
  auto chart = new QChart();
  chart->setTitle(sig_name);
  chart->addSeries(series);
  chart->createDefaultAxes();
  chart->legend()->hide();
  QFont font;
  font.setBold(true);
  chart->setTitleFont(font);
  chart->setMargins({0, 0, 0, 0});
  chart->layout()->setContentsMargins(0, 0, 0, 0);
  QObject::connect(dynamic_cast<QValueAxis *>(chart->axisX()), &QValueAxis::rangeChanged, parser, &Parser::setRange);

  chart_view = new QChartView(chart);
  chart_view->setFixedHeight(300);
  chart_view->setRenderHint(QPainter::Antialiasing);
  chart_view->setRubberBand(QChartView::HorizontalRubberBand);
  if (auto rubber = chart_view->findChild<QRubberBand *>()) {
    QPalette pal;
    pal.setBrush(QPalette::Base, QColor(0, 0, 0, 80));
    rubber->setPalette(pal);
  }
  chart_layout->addWidget(chart_view);
  chart_layout->addStretch();

  stacked->addWidget(chart_widget);
  line_marker = new LineMarker(chart, this);
  stacked->addWidget(line_marker);
  line_marker->setAttribute(Qt::WA_TransparentForMouseEvents, true);
  line_marker->raise();

  setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  QObject::connect(parser, &Parser::updated, this, &ChartWidget::updateState);
  QObject::connect(parser, &Parser::rangeChanged, this, &ChartWidget::rangeChanged);
  QObject::connect(parser, &Parser::eventsMerged, this, &ChartWidget::updateSeries);

  updateSeries();
}

void ChartWidget::updateState() {
  line_marker->update();
}

void ChartWidget::updateSeries() {
  const Signal *sig = parser->getSig(id, sig_name);
  auto events = parser->replay->events();
  if (!sig || !events) return;

  auto l = id.split(':');
  int bus = l[0].toInt();
  uint32_t address = l[1].toUInt(nullptr, 16);

  vals.clear();
  vals.reserve(3 * 60 * 100);
  double min_y = 0, max_y = 0;
  uint64_t route_start_time = parser->replay->routeStartTime();
  for (auto &evt : *events) {
    if (evt->which == cereal::Event::Which::CAN) {
      for (auto c : evt->event.getCan()) {
        if (bus == c.getSrc() && address == c.getAddress()) {
          auto dat = c.getDat();
          int64_t val = get_raw_value((uint8_t *)dat.begin(), dat.size(), *sig);
          if (sig->is_signed) {
            val -= ((val >> (sig->size - 1)) & 0x1) ? (1ULL << sig->size) : 0;
          }
          double value = val * sig->factor + sig->offset;
          if (value < min_y) min_y = value;
          if (value > max_y) max_y = value;

          double ts = (evt->mono_time - route_start_time) / (double)1e9;  // seconds
          vals.push_back({ts, value});
        }
      }
    }
  }
  QLineSeries *series = (QLineSeries *)chart_view->chart()->series()[0];
  series->replace(vals);
  auto [begin, end] = parser->range();
  chart_view->chart()->axisX()->setRange(begin, end);
  chart_view->chart()->axisY()->setRange(min_y * 0.95, max_y * 1.05);
}

void ChartWidget::rangeChanged(qreal min, qreal max) {
  auto axis_x = dynamic_cast<QValueAxis *>(chart_view->chart()->axisX());
  if (axis_x->min() != min || axis_x->max() != max) {
    axis_x->setRange(min, max);
  }
  // auto zoom on yaxis
  double min_y = 0, max_y = 0;
  for (auto &p : vals) {
    if (p.x() > max) break;

    if (p.x() >= min) {
      if (p.y() < min_y) min_y = p.y();
      if (p.y() > max_y) max_y = p.y();
    }
  }
  chart_view->chart()->axisY()->setRange(min_y * 0.95, max_y * 1.05);
}

LineMarker::LineMarker(QChart *chart, QWidget *parent) : chart(chart), QWidget(parent) {}

void LineMarker::paintEvent(QPaintEvent *event) {
  auto axis_x = dynamic_cast<QValueAxis *>(chart->axisX());
  if (axis_x->max() <= axis_x->min()) return;

  double x = chart->plotArea().left() + chart->plotArea().width() * (parser->currentSec() - axis_x->min()) / (axis_x->max() - axis_x->min());
  QPainter p(this);
  QPen pen = QPen(Qt::black);
  pen.setWidth(2);
  p.setPen(pen);
  p.drawLine(QPointF{x, 50.}, QPointF{x, (qreal)height() - 11});
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/browser/ui/views/menu_bar.h"

#include <memory>
#include <set>
#include <sstream>

#include "atom/browser/ui/views/submenu_button.h"
#include "atom/common/keyboard_util.h"
#include "ui/base/models/menu_model.h"
#include "ui/views/background.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/widget/widget.h"

#if defined(USE_X11)
#include "chrome/browser/ui/libgtkui/gtk_util.h"
#endif

#if defined(OS_WIN)
#include "ui/gfx/color_utils.h"
#endif

namespace atom {

namespace {

// Default color of the menu bar.
const SkColor kDefaultColor = SkColorSetARGB(255, 233, 233, 233);

}  // namespace

const char MenuBar::kViewClassName[] = "ElectronMenuBar";

MenuBarColorUpdater::MenuBarColorUpdater(MenuBar* menu_bar)
    : menu_bar_(menu_bar) {}

MenuBarColorUpdater::~MenuBarColorUpdater() {}

void MenuBarColorUpdater::OnDidChangeFocus(views::View* focused_before,
                                           views::View* focused_now) {
  if (menu_bar_) {
    // if we've changed window focus, update menu bar colors
    const auto had_focus = menu_bar_->has_focus_;
    menu_bar_->has_focus_ = focused_now != nullptr;
    if (menu_bar_->has_focus_ != had_focus)
      menu_bar_->UpdateViewColors();
  }
}

MenuBar::MenuBar(RootView* window)
    : background_color_(kDefaultColor),
      window_(window),
      color_updater_(new MenuBarColorUpdater(this)) {
  RefreshColorCache();
  UpdateViewColors();
  SetFocusBehavior(FocusBehavior::ALWAYS);
  SetLayoutManager(
      std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal));
  window_->GetFocusManager()->AddFocusChangeListener(color_updater_.get());
}

MenuBar::~MenuBar() {
  window_->GetFocusManager()->RemoveFocusChangeListener(color_updater_.get());
}

void MenuBar::SetMenu(AtomMenuModel* model) {
  menu_model_ = model;
  RebuildChildren();
}

void MenuBar::SetAcceleratorVisibility(bool visible) {
  for (auto* child : GetChildrenInZOrder())
    static_cast<SubmenuButton*>(child)->SetAcceleratorVisibility(visible);
}

MenuBar::View* MenuBar::FindAccelChild(base::char16 key) {
  for (auto* child : GetChildrenInZOrder()) {
    if (static_cast<SubmenuButton*>(child)->accelerator() == key)
      return child;
  }
  return nullptr;
}

bool MenuBar::HasAccelerator(base::char16 key) {
  return FindAccelChild(key) != nullptr;
}

void MenuBar::ActivateAccelerator(base::char16 key) {
  auto* child = FindAccelChild(key);
  if (child)
    static_cast<SubmenuButton*>(child)->Activate(nullptr);
}

int MenuBar::GetItemCount() const {
  return menu_model_ ? menu_model_->GetItemCount() : 0;
}

bool MenuBar::GetMenuButtonFromScreenPoint(const gfx::Point& screenPoint,
                                           AtomMenuModel** menu_model,
                                           views::MenuButton** button) {
  if (!GetBoundsInScreen().Contains(screenPoint))
    return false;

  auto children = GetChildrenInZOrder();
  for (int i = 0, n = children.size(); i < n; ++i) {
    if (children[i]->GetBoundsInScreen().Contains(screenPoint) &&
        (menu_model_->GetTypeAt(i) == AtomMenuModel::TYPE_SUBMENU)) {
      *menu_model = menu_model_->GetSubmenuModelAt(i);
      *button = static_cast<views::MenuButton*>(children[i]);
      return true;
    }
  }

  return false;
}

void MenuBar::OnBeforeExecuteCommand() {
  RemovePaneFocus();
  window_->RestoreFocus();
}

void MenuBar::OnMenuClosed() {
  SetAcceleratorVisibility(true);
}

bool MenuBar::AcceleratorPressed(const ui::Accelerator& accelerator) {
  views::View* focused_view = GetFocusManager()->GetFocusedView();
  if (!ContainsForFocusSearch(this, focused_view))
    return false;

  switch (accelerator.key_code()) {
    case ui::VKEY_MENU:
    case ui::VKEY_ESCAPE: {
      RemovePaneFocus();
      window_->RestoreFocus();
      return true;
    }
    case ui::VKEY_LEFT:
      GetFocusManager()->AdvanceFocus(true);
      return true;
    case ui::VKEY_RIGHT:
      GetFocusManager()->AdvanceFocus(false);
      return true;
    case ui::VKEY_HOME:
      GetFocusManager()->SetFocusedViewWithReason(
          GetFirstFocusableChild(), views::FocusManager::kReasonFocusTraversal);
      return true;
    case ui::VKEY_END:
      GetFocusManager()->SetFocusedViewWithReason(
          GetLastFocusableChild(), views::FocusManager::kReasonFocusTraversal);
      return true;
    default: {
      auto children = GetChildrenInZOrder();
      for (int i = 0, n = children.size(); i < n; ++i) {
        auto* button = static_cast<SubmenuButton*>(children[i]);
        bool shifted = false;
        auto keycode =
            atom::KeyboardCodeFromCharCode(button->accelerator(), &shifted);

        if (keycode == accelerator.key_code()) {
          const gfx::Point p(0, 0);
          auto event = accelerator.ToKeyEvent();
          OnMenuButtonClicked(button, p, &event);
          return true;
        }
      }

      return false;
    }
  }
}

bool MenuBar::SetPaneFocus(views::View* initial_focus) {
  bool result = views::AccessiblePaneView::SetPaneFocus(initial_focus);

  if (result) {
    auto children = GetChildrenInZOrder();
    std::set<ui::KeyboardCode> reg;
    for (int i = 0, n = children.size(); i < n; ++i) {
      auto* button = static_cast<SubmenuButton*>(children[i]);
      bool shifted = false;
      auto keycode =
          atom::KeyboardCodeFromCharCode(button->accelerator(), &shifted);

      // We want the menu items to activate if the user presses the accelerator
      // key, even without alt, since we are now focused on the menu bar
      if (keycode != ui::VKEY_UNKNOWN && reg.find(keycode) != reg.end()) {
        reg.insert(keycode);
        focus_manager()->RegisterAccelerator(
            ui::Accelerator(keycode, ui::EF_NONE),
            ui::AcceleratorManager::kNormalPriority, this);
      }
    }

    // We want to remove focus / hide menu bar when alt is pressed again
    focus_manager()->RegisterAccelerator(
        ui::Accelerator(ui::VKEY_MENU, ui::EF_ALT_DOWN),
        ui::AcceleratorManager::kNormalPriority, this);
  }

  return result;
}

void MenuBar::RemovePaneFocus() {
  views::AccessiblePaneView::RemovePaneFocus();
  SetAcceleratorVisibility(false);

  auto children = GetChildrenInZOrder();
  std::set<ui::KeyboardCode> unreg;
  for (int i = 0, n = children.size(); i < n; ++i) {
    auto* button = static_cast<SubmenuButton*>(children[i]);
    bool shifted = false;
    auto keycode =
        atom::KeyboardCodeFromCharCode(button->accelerator(), &shifted);

    if (keycode != ui::VKEY_UNKNOWN && unreg.find(keycode) != unreg.end()) {
      unreg.insert(keycode);
      focus_manager()->UnregisterAccelerator(
          ui::Accelerator(keycode, ui::EF_NONE), this);
    }
  }

  focus_manager()->UnregisterAccelerator(
      ui::Accelerator(ui::VKEY_MENU, ui::EF_ALT_DOWN), this);
}

const char* MenuBar::GetClassName() const {
  return kViewClassName;
}

void MenuBar::OnMenuButtonClicked(views::MenuButton* source,
                                  const gfx::Point& point,
                                  const ui::Event* event) {
  // Hide the accelerator when a submenu is activated.
  SetAcceleratorVisibility(false);

  if (!menu_model_)
    return;

  if (!window_->HasFocus())
    window_->RequestFocus();

  int id = source->tag();
  AtomMenuModel::ItemType type = menu_model_->GetTypeAt(id);
  if (type != AtomMenuModel::TYPE_SUBMENU) {
    menu_model_->ActivatedAt(id, 0);
    return;
  }

  GetFocusManager()->SetFocusedViewWithReason(
      source, views::FocusManager::kReasonFocusTraversal);

  // Deleted in MenuDelegate::OnMenuClosed
  MenuDelegate* menu_delegate = new MenuDelegate(this);
  menu_delegate->RunMenu(menu_model_->GetSubmenuModelAt(id), source,
                         event != nullptr && event->IsKeyEvent()
                             ? ui::MENU_SOURCE_KEYBOARD
                             : ui::MENU_SOURCE_MOUSE);
  menu_delegate->AddObserver(this);
}

void MenuBar::RefreshColorCache(const ui::NativeTheme* theme) {
  if (!theme)
    theme = ui::NativeTheme::GetInstanceForNativeUi();
  if (theme) {
#if defined(USE_X11)
    background_color_ = libgtkui::GetBgColor("GtkMenuBar#menubar");
    enabled_color_ = libgtkui::GetFgColor(
        "GtkMenuBar#menubar GtkMenuItem#menuitem GtkLabel");
    disabled_color_ = libgtkui::GetFgColor(
        "GtkMenuBar#menubar GtkMenuItem#menuitem:disabled GtkLabel");
#else
    background_color_ =
        theme->GetSystemColor(ui::NativeTheme::kColorId_MenuBackgroundColor);
#endif
  }
#if defined(OS_WIN)
  background_color_ = color_utils::GetSysSkColor(COLOR_MENUBAR);
#endif
}

void MenuBar::OnNativeThemeChanged(const ui::NativeTheme* theme) {
  RefreshColorCache(theme);
  UpdateViewColors();
}

void MenuBar::RebuildChildren() {
  RemoveAllChildViews(true);
  for (int i = 0, n = GetItemCount(); i < n; ++i) {
    auto* button =
        new SubmenuButton(menu_model_->GetLabelAt(i), this, background_color_);
    button->set_tag(i);
    AddChildView(button);
  }
  UpdateViewColors();
}

void MenuBar::UpdateViewColors() {
  // set menubar background color
  SetBackground(views::CreateSolidBackground(background_color_));

  // set child colors
  if (menu_model_ == nullptr)
    return;
#if defined(USE_X11)
  const auto& textColor = has_focus_ ? enabled_color_ : disabled_color_;
  for (auto* child : GetChildrenInZOrder()) {
    auto* button = static_cast<SubmenuButton*>(child);
    button->SetTextColor(views::Button::STATE_NORMAL, textColor);
    button->SetTextColor(views::Button::STATE_DISABLED, disabled_color_);
    button->SetTextColor(views::Button::STATE_PRESSED, enabled_color_);
    button->SetTextColor(views::Button::STATE_HOVERED, textColor);
    button->SetUnderlineColor(textColor);
  }
#elif defined(OS_WIN)
  for (auto* child : GetChildrenInZOrder()) {
    auto* button = static_cast<SubmenuButton*>(child);
    button->SetUnderlineColor(color_utils::GetSysSkColor(COLOR_MENUTEXT));
  }
#endif
}

}  // namespace atom
<commit_msg>fix: check the root window in MenuBar::SetPanelFocus (#16581)<commit_after>// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/browser/ui/views/menu_bar.h"

#include <memory>
#include <set>
#include <sstream>

#include "atom/browser/ui/views/submenu_button.h"
#include "atom/common/keyboard_util.h"
#include "ui/aura/window.h"
#include "ui/base/models/menu_model.h"
#include "ui/views/background.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/widget/widget.h"

#if defined(USE_X11)
#include "chrome/browser/ui/libgtkui/gtk_util.h"
#endif

#if defined(OS_WIN)
#include "ui/gfx/color_utils.h"
#endif

namespace atom {

namespace {

// Default color of the menu bar.
const SkColor kDefaultColor = SkColorSetARGB(255, 233, 233, 233);

}  // namespace

const char MenuBar::kViewClassName[] = "ElectronMenuBar";

MenuBarColorUpdater::MenuBarColorUpdater(MenuBar* menu_bar)
    : menu_bar_(menu_bar) {}

MenuBarColorUpdater::~MenuBarColorUpdater() {}

void MenuBarColorUpdater::OnDidChangeFocus(views::View* focused_before,
                                           views::View* focused_now) {
  if (menu_bar_) {
    // if we've changed window focus, update menu bar colors
    const auto had_focus = menu_bar_->has_focus_;
    menu_bar_->has_focus_ = focused_now != nullptr;
    if (menu_bar_->has_focus_ != had_focus)
      menu_bar_->UpdateViewColors();
  }
}

MenuBar::MenuBar(RootView* window)
    : background_color_(kDefaultColor),
      window_(window),
      color_updater_(new MenuBarColorUpdater(this)) {
  RefreshColorCache();
  UpdateViewColors();
  SetFocusBehavior(FocusBehavior::ALWAYS);
  SetLayoutManager(
      std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal));
  window_->GetFocusManager()->AddFocusChangeListener(color_updater_.get());
}

MenuBar::~MenuBar() {
  window_->GetFocusManager()->RemoveFocusChangeListener(color_updater_.get());
}

void MenuBar::SetMenu(AtomMenuModel* model) {
  menu_model_ = model;
  RebuildChildren();
}

void MenuBar::SetAcceleratorVisibility(bool visible) {
  for (auto* child : GetChildrenInZOrder())
    static_cast<SubmenuButton*>(child)->SetAcceleratorVisibility(visible);
}

MenuBar::View* MenuBar::FindAccelChild(base::char16 key) {
  for (auto* child : GetChildrenInZOrder()) {
    if (static_cast<SubmenuButton*>(child)->accelerator() == key)
      return child;
  }
  return nullptr;
}

bool MenuBar::HasAccelerator(base::char16 key) {
  return FindAccelChild(key) != nullptr;
}

void MenuBar::ActivateAccelerator(base::char16 key) {
  auto* child = FindAccelChild(key);
  if (child)
    static_cast<SubmenuButton*>(child)->Activate(nullptr);
}

int MenuBar::GetItemCount() const {
  return menu_model_ ? menu_model_->GetItemCount() : 0;
}

bool MenuBar::GetMenuButtonFromScreenPoint(const gfx::Point& screenPoint,
                                           AtomMenuModel** menu_model,
                                           views::MenuButton** button) {
  if (!GetBoundsInScreen().Contains(screenPoint))
    return false;

  auto children = GetChildrenInZOrder();
  for (int i = 0, n = children.size(); i < n; ++i) {
    if (children[i]->GetBoundsInScreen().Contains(screenPoint) &&
        (menu_model_->GetTypeAt(i) == AtomMenuModel::TYPE_SUBMENU)) {
      *menu_model = menu_model_->GetSubmenuModelAt(i);
      *button = static_cast<views::MenuButton*>(children[i]);
      return true;
    }
  }

  return false;
}

void MenuBar::OnBeforeExecuteCommand() {
  RemovePaneFocus();
  window_->RestoreFocus();
}

void MenuBar::OnMenuClosed() {
  SetAcceleratorVisibility(true);
}

bool MenuBar::AcceleratorPressed(const ui::Accelerator& accelerator) {
  views::View* focused_view = GetFocusManager()->GetFocusedView();
  if (!ContainsForFocusSearch(this, focused_view))
    return false;

  switch (accelerator.key_code()) {
    case ui::VKEY_MENU:
    case ui::VKEY_ESCAPE: {
      RemovePaneFocus();
      window_->RestoreFocus();
      return true;
    }
    case ui::VKEY_LEFT:
      GetFocusManager()->AdvanceFocus(true);
      return true;
    case ui::VKEY_RIGHT:
      GetFocusManager()->AdvanceFocus(false);
      return true;
    case ui::VKEY_HOME:
      GetFocusManager()->SetFocusedViewWithReason(
          GetFirstFocusableChild(), views::FocusManager::kReasonFocusTraversal);
      return true;
    case ui::VKEY_END:
      GetFocusManager()->SetFocusedViewWithReason(
          GetLastFocusableChild(), views::FocusManager::kReasonFocusTraversal);
      return true;
    default: {
      auto children = GetChildrenInZOrder();
      for (int i = 0, n = children.size(); i < n; ++i) {
        auto* button = static_cast<SubmenuButton*>(children[i]);
        bool shifted = false;
        auto keycode =
            atom::KeyboardCodeFromCharCode(button->accelerator(), &shifted);

        if (keycode == accelerator.key_code()) {
          const gfx::Point p(0, 0);
          auto event = accelerator.ToKeyEvent();
          OnMenuButtonClicked(button, p, &event);
          return true;
        }
      }

      return false;
    }
  }
}

bool MenuBar::SetPaneFocus(views::View* initial_focus) {
  // TODO(zcbenz): Submit patch to upstream Chromium to fix the crash.
  //
  // Without this check, Electron would crash when running tests.
  //
  // Check failed: rules_->CanFocusWindow(window, nullptr).
  //   logging::LogMessage::~LogMessage
  //   wm::FocusController::SetFocusedWindow
  //   wm::FocusController::ResetFocusWithinActiveWindow
  //   views::View::OnFocus
  //   views::Button::OnFocus
  //   views::LabelButton::OnFocus
  //   views::View::Focus
  //   views::FocusManager::SetFocusedViewWithReason
  //   views::AccessiblePaneView::SetPaneFocus
  //   atom::MenuBar::SetPaneFocus
  if (initial_focus && initial_focus->GetWidget()) {
    aura::Window* window = initial_focus->GetWidget()->GetNativeWindow();
    if (!window || !window->GetRootWindow())
      return false;
  }

  bool result = views::AccessiblePaneView::SetPaneFocus(initial_focus);

  if (result) {
    auto children = GetChildrenInZOrder();
    std::set<ui::KeyboardCode> reg;
    for (int i = 0, n = children.size(); i < n; ++i) {
      auto* button = static_cast<SubmenuButton*>(children[i]);
      bool shifted = false;
      auto keycode =
          atom::KeyboardCodeFromCharCode(button->accelerator(), &shifted);

      // We want the menu items to activate if the user presses the accelerator
      // key, even without alt, since we are now focused on the menu bar
      if (keycode != ui::VKEY_UNKNOWN && reg.find(keycode) != reg.end()) {
        reg.insert(keycode);
        focus_manager()->RegisterAccelerator(
            ui::Accelerator(keycode, ui::EF_NONE),
            ui::AcceleratorManager::kNormalPriority, this);
      }
    }

    // We want to remove focus / hide menu bar when alt is pressed again
    focus_manager()->RegisterAccelerator(
        ui::Accelerator(ui::VKEY_MENU, ui::EF_ALT_DOWN),
        ui::AcceleratorManager::kNormalPriority, this);
  }

  return result;
}

void MenuBar::RemovePaneFocus() {
  views::AccessiblePaneView::RemovePaneFocus();
  SetAcceleratorVisibility(false);

  auto children = GetChildrenInZOrder();
  std::set<ui::KeyboardCode> unreg;
  for (int i = 0, n = children.size(); i < n; ++i) {
    auto* button = static_cast<SubmenuButton*>(children[i]);
    bool shifted = false;
    auto keycode =
        atom::KeyboardCodeFromCharCode(button->accelerator(), &shifted);

    if (keycode != ui::VKEY_UNKNOWN && unreg.find(keycode) != unreg.end()) {
      unreg.insert(keycode);
      focus_manager()->UnregisterAccelerator(
          ui::Accelerator(keycode, ui::EF_NONE), this);
    }
  }

  focus_manager()->UnregisterAccelerator(
      ui::Accelerator(ui::VKEY_MENU, ui::EF_ALT_DOWN), this);
}

const char* MenuBar::GetClassName() const {
  return kViewClassName;
}

void MenuBar::OnMenuButtonClicked(views::MenuButton* source,
                                  const gfx::Point& point,
                                  const ui::Event* event) {
  // Hide the accelerator when a submenu is activated.
  SetAcceleratorVisibility(false);

  if (!menu_model_)
    return;

  if (!window_->HasFocus())
    window_->RequestFocus();

  int id = source->tag();
  AtomMenuModel::ItemType type = menu_model_->GetTypeAt(id);
  if (type != AtomMenuModel::TYPE_SUBMENU) {
    menu_model_->ActivatedAt(id, 0);
    return;
  }

  GetFocusManager()->SetFocusedViewWithReason(
      source, views::FocusManager::kReasonFocusTraversal);

  // Deleted in MenuDelegate::OnMenuClosed
  MenuDelegate* menu_delegate = new MenuDelegate(this);
  menu_delegate->RunMenu(menu_model_->GetSubmenuModelAt(id), source,
                         event != nullptr && event->IsKeyEvent()
                             ? ui::MENU_SOURCE_KEYBOARD
                             : ui::MENU_SOURCE_MOUSE);
  menu_delegate->AddObserver(this);
}

void MenuBar::RefreshColorCache(const ui::NativeTheme* theme) {
  if (!theme)
    theme = ui::NativeTheme::GetInstanceForNativeUi();
  if (theme) {
#if defined(USE_X11)
    background_color_ = libgtkui::GetBgColor("GtkMenuBar#menubar");
    enabled_color_ = libgtkui::GetFgColor(
        "GtkMenuBar#menubar GtkMenuItem#menuitem GtkLabel");
    disabled_color_ = libgtkui::GetFgColor(
        "GtkMenuBar#menubar GtkMenuItem#menuitem:disabled GtkLabel");
#else
    background_color_ =
        theme->GetSystemColor(ui::NativeTheme::kColorId_MenuBackgroundColor);
#endif
  }
#if defined(OS_WIN)
  background_color_ = color_utils::GetSysSkColor(COLOR_MENUBAR);
#endif
}

void MenuBar::OnNativeThemeChanged(const ui::NativeTheme* theme) {
  RefreshColorCache(theme);
  UpdateViewColors();
}

void MenuBar::RebuildChildren() {
  RemoveAllChildViews(true);
  for (int i = 0, n = GetItemCount(); i < n; ++i) {
    auto* button =
        new SubmenuButton(menu_model_->GetLabelAt(i), this, background_color_);
    button->set_tag(i);
    AddChildView(button);
  }
  UpdateViewColors();
}

void MenuBar::UpdateViewColors() {
  // set menubar background color
  SetBackground(views::CreateSolidBackground(background_color_));

  // set child colors
  if (menu_model_ == nullptr)
    return;
#if defined(USE_X11)
  const auto& textColor = has_focus_ ? enabled_color_ : disabled_color_;
  for (auto* child : GetChildrenInZOrder()) {
    auto* button = static_cast<SubmenuButton*>(child);
    button->SetTextColor(views::Button::STATE_NORMAL, textColor);
    button->SetTextColor(views::Button::STATE_DISABLED, disabled_color_);
    button->SetTextColor(views::Button::STATE_PRESSED, enabled_color_);
    button->SetTextColor(views::Button::STATE_HOVERED, textColor);
    button->SetUnderlineColor(textColor);
  }
#elif defined(OS_WIN)
  for (auto* child : GetChildrenInZOrder()) {
    auto* button = static_cast<SubmenuButton*>(child);
    button->SetUnderlineColor(color_utils::GetSysSkColor(COLOR_MENUTEXT));
  }
#endif
}

}  // namespace atom
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "CommandProfiling.h"

#if defined(__unix__) || defined(__APPLE__)
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#endif
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <sstream>

#include "Debug.h"

namespace {

pid_t spawn(const std::string& cmd) {
#ifdef _POSIX_VERSION
  auto child = fork();
  always_assert_log(child != -1, "Failed to fork");
  if (child != 0) {
    return child;
  } else {
    int ret = execl("/bin/sh", "/bin/sh", "-c", cmd.c_str(), nullptr);
    always_assert_log(ret != -1, "exec of command failed: %s", strerror(errno));
    not_reached();
  }
#else
  std::cerr << "spawn() is a no-op on non-POSIX systems" << std::endl;
  return 0;
#endif
}

/*
 * Appends the PID of the current process to :cmd and invokes it.
 */
pid_t spawn_profiler(const std::string& cmd) {
#ifdef _POSIX_VERSION
  auto parent = getpid();
  std::ostringstream ss;
  ss << cmd << " " << parent;
  auto full_cmd = ss.str();
  return spawn(full_cmd);
#else
  std::cerr << "spawn_profiler() is a no-op on non-POSIX systems" << std::endl;
  return 0;
#endif
}

pid_t kill_and_wait(pid_t pid, int sig) {
#ifdef _POSIX_VERSION
  kill(pid, sig);
  return waitpid(pid, nullptr, 0);
#else
  std::cerr << "kill_and_wait() is a no-op on non-POSIX systems" << std::endl;
  return 0;
#endif
}

void run_and_wait(const std::string& cmd) {
#ifdef _POSIX_VERSION
  auto child = spawn(cmd);
  if (child == 0) {
    return;
  }

  int status;
  pid_t wpid = waitpid(child, &status, 0);
  always_assert_log(wpid != -1, "Failed to waitpid: %s", strerror(errno));
  if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
    std::cerr << "Failed cmd " << cmd << std::endl;
  }
#else
  std::cerr << "run_and_wait() is a no-op on non-POSIX systems" << std::endl;
#endif
}

} // namespace

ScopedCommandProfiling::ScopedCommandProfiling(
    const std::string& cmd,
    boost::optional<std::string> shutdown_cmd,
    boost::optional<std::string> post_cmd,
    const char* log_str) {
  m_shutdown_cmd = std::move(shutdown_cmd);
  m_post_cmd = std::move(post_cmd);
  if (log_str != nullptr) {
    std::cerr << "Running profiler " << log_str << "..." << std::endl;
  } else {
    std::cerr << "Running profiler..." << std::endl;
  }
  m_profiler = spawn_profiler(cmd);
}

ScopedCommandProfiling::~ScopedCommandProfiling() {
  if (m_profiler != -1) {
    std::cerr << "Waiting for profiler to finish..." << std::endl;
    if (m_shutdown_cmd) {
      run_and_wait(*m_shutdown_cmd);
    } else {
      kill_and_wait(m_profiler, SIGINT);
    }
    if (m_post_cmd) {
      run_and_wait(*m_post_cmd + " perf.data");
    }
  }
}

ScopedCommandProfiling::ScopedCommandProfiling(
    ScopedCommandProfiling&& other) noexcept {
  *this = std::move(other);
}

ScopedCommandProfiling& ScopedCommandProfiling::operator=(
    ScopedCommandProfiling&& rhs) noexcept {
  m_profiler = rhs.m_profiler;
  m_shutdown_cmd = std::move(rhs.m_shutdown_cmd);
  m_post_cmd = std::move(rhs.m_post_cmd);

  rhs.m_profiler = -1;

  return *this;
}

boost::optional<ScopedCommandProfiling::ProfilerInfo>
ScopedCommandProfiling::maybe_info_from_env(const std::string& prefix) {
  auto get_env_str =
      [](const std::string& key) -> boost::optional<std::string> {
    auto val = getenv(key.c_str());
    if (val == nullptr) {
      return boost::none;
    }
    return std::string(val);
  };

  std::string profiler_key = prefix + "PROFILE_COMMAND";
  if (getenv(profiler_key.c_str()) == nullptr) {
    return boost::none;
  }

  return boost::make_optional<ProfilerInfo>(
      ProfilerInfo{getenv(profiler_key.c_str()),
                   get_env_str(prefix + "PROFILE_SHUTDOWN_COMMAND"),
                   get_env_str(prefix + "PROFILE_POST_COMMAND")});
}

template <typename T>
boost::optional<ScopedCommandProfiling> ScopedCommandProfiling::maybe_from_info(
    const boost::optional<ProfilerInfo>& info, const T* log_str) {
  if (!info) {
    return boost::none;
  }
  return ScopedCommandProfiling(*info, log_str);
}
template boost::optional<ScopedCommandProfiling>
ScopedCommandProfiling::maybe_from_info<>(
    const boost::optional<ProfilerInfo>& info, const std::string* log_str);
template boost::optional<ScopedCommandProfiling>
ScopedCommandProfiling::maybe_from_info<>(
    const boost::optional<ProfilerInfo>& info, const char* log_str);
<commit_msg>Add sleep to profiling<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "CommandProfiling.h"

#if defined(__unix__) || defined(__APPLE__)
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#endif
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <sstream>
#include <thread>

#include "Debug.h"

namespace {

using namespace std::chrono_literals;

pid_t spawn(const std::string& cmd) {
#ifdef _POSIX_VERSION
  auto child = fork();
  always_assert_log(child != -1, "Failed to fork");
  if (child != 0) {
    // Wait a little bit to let the spawn catch up.
    std::this_thread::sleep_for(250ms);
    return child;
  } else {
    int ret = execl("/bin/sh", "/bin/sh", "-c", cmd.c_str(), nullptr);
    always_assert_log(ret != -1, "exec of command failed: %s", strerror(errno));
    not_reached();
  }
#else
  std::cerr << "spawn() is a no-op on non-POSIX systems" << std::endl;
  return 0;
#endif
}

/*
 * Appends the PID of the current process to :cmd and invokes it.
 */
pid_t spawn_profiler(const std::string& cmd) {
#ifdef _POSIX_VERSION
  auto parent = getpid();
  std::ostringstream ss;
  ss << cmd << " " << parent;
  auto full_cmd = ss.str();
  return spawn(full_cmd);
#else
  std::cerr << "spawn_profiler() is a no-op on non-POSIX systems" << std::endl;
  return 0;
#endif
}

pid_t kill_and_wait(pid_t pid, int sig) {
#ifdef _POSIX_VERSION
  kill(pid, sig);
  return waitpid(pid, nullptr, 0);
#else
  std::cerr << "kill_and_wait() is a no-op on non-POSIX systems" << std::endl;
  return 0;
#endif
}

void run_and_wait(const std::string& cmd) {
#ifdef _POSIX_VERSION
  auto child = spawn(cmd);
  if (child == 0) {
    return;
  }

  int status;
  pid_t wpid = waitpid(child, &status, 0);
  always_assert_log(wpid != -1, "Failed to waitpid: %s", strerror(errno));
  if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
    std::cerr << "Failed cmd " << cmd << std::endl;
  }
#else
  std::cerr << "run_and_wait() is a no-op on non-POSIX systems" << std::endl;
#endif
}

} // namespace

ScopedCommandProfiling::ScopedCommandProfiling(
    const std::string& cmd,
    boost::optional<std::string> shutdown_cmd,
    boost::optional<std::string> post_cmd,
    const char* log_str) {
  m_shutdown_cmd = std::move(shutdown_cmd);
  m_post_cmd = std::move(post_cmd);
  if (log_str != nullptr) {
    std::cerr << "Running profiler " << log_str << "..." << std::endl;
  } else {
    std::cerr << "Running profiler..." << std::endl;
  }
  m_profiler = spawn_profiler(cmd);
}

ScopedCommandProfiling::~ScopedCommandProfiling() {
  if (m_profiler != -1) {
    std::cerr << "Waiting for profiler to finish..." << std::endl;
    if (m_shutdown_cmd) {
      run_and_wait(*m_shutdown_cmd);
    } else {
      kill_and_wait(m_profiler, SIGINT);
    }
    if (m_post_cmd) {
      run_and_wait(*m_post_cmd + " perf.data");
    }
  }
}

ScopedCommandProfiling::ScopedCommandProfiling(
    ScopedCommandProfiling&& other) noexcept {
  *this = std::move(other);
}

ScopedCommandProfiling& ScopedCommandProfiling::operator=(
    ScopedCommandProfiling&& rhs) noexcept {
  m_profiler = rhs.m_profiler;
  m_shutdown_cmd = std::move(rhs.m_shutdown_cmd);
  m_post_cmd = std::move(rhs.m_post_cmd);

  rhs.m_profiler = -1;

  return *this;
}

boost::optional<ScopedCommandProfiling::ProfilerInfo>
ScopedCommandProfiling::maybe_info_from_env(const std::string& prefix) {
  auto get_env_str =
      [](const std::string& key) -> boost::optional<std::string> {
    auto val = getenv(key.c_str());
    if (val == nullptr) {
      return boost::none;
    }
    return std::string(val);
  };

  std::string profiler_key = prefix + "PROFILE_COMMAND";
  if (getenv(profiler_key.c_str()) == nullptr) {
    return boost::none;
  }

  return boost::make_optional<ProfilerInfo>(
      ProfilerInfo{getenv(profiler_key.c_str()),
                   get_env_str(prefix + "PROFILE_SHUTDOWN_COMMAND"),
                   get_env_str(prefix + "PROFILE_POST_COMMAND")});
}

template <typename T>
boost::optional<ScopedCommandProfiling> ScopedCommandProfiling::maybe_from_info(
    const boost::optional<ProfilerInfo>& info, const T* log_str) {
  if (!info) {
    return boost::none;
  }
  return ScopedCommandProfiling(*info, log_str);
}
template boost::optional<ScopedCommandProfiling>
ScopedCommandProfiling::maybe_from_info<>(
    const boost::optional<ProfilerInfo>& info, const std::string* log_str);
template boost::optional<ScopedCommandProfiling>
ScopedCommandProfiling::maybe_from_info<>(
    const boost::optional<ProfilerInfo>& info, const char* log_str);
<|endoftext|>


<commit_before>#include <iostream>
#include <unistd.h>

#include "benchmark.h"
#include "simdjson.h"

// #define RAPIDJSON_SSE2 // bad
// #define RAPIDJSON_SSE42 // bad
#include "rapidjson/document.h"
#include "rapidjson/reader.h" // you have to check in the submodule
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include "sajson.h"

using namespace simdjson;
using namespace rapidjson;

std::string rapid_stringme_insitu(char *json) {
  Document d;
  d.ParseInsitu(json);
  if (d.HasParseError()) {
    std::cerr << "problem!" << std::endl;
    return ""; // should do something
  }
  StringBuffer buffer;
  Writer<StringBuffer> writer(buffer);
  d.Accept(writer);
  return buffer.GetString();
}

std::string rapid_stringme(char *json) {
  Document d;
  d.Parse(json);
  if (d.HasParseError()) {
    std::cerr << "problem!" << std::endl;
    return ""; // should do something
  }
  StringBuffer buffer;
  Writer<StringBuffer> writer(buffer);
  d.Accept(writer);
  return buffer.GetString();
}

int main(int argc, char *argv[]) {
  int c;
  bool verbose = false;
  bool just_data = false;

  while ((c = getopt(argc, argv, "vt")) != -1)
    switch (c) {
    case 't':
      just_data = true;
      break;
    case 'v':
      verbose = true;
      break;
    default:
      abort();
    }
  if (optind >= argc) {
    std::cerr << "Usage: " << argv[0] << " <jsonfile>" << std::endl;
    exit(1);
  }
  const char *filename = argv[optind];
  auto [p, error] = simdjson::padded_string::load(filename);
  if (error) {
    std::cerr << "Could not load the file " << filename << std::endl;
    return EXIT_FAILURE;
  }
  if (verbose) {
    std::cout << "Input has ";
    if (p.size() > 1024 * 1024)
      std::cout << p.size() / (1024 * 1024) << " MB ";
    else if (p.size() > 1024)
      std::cout << p.size() / 1024 << " KB ";
    else
      std::cout << p.size() << " B ";
    std::cout << std::endl;
  }
  char *buffer = simdjson::internal::allocate_padded_buffer(p.size() + 1);
  memcpy(buffer, p.data(), p.size());
  buffer[p.size()] = '\0';

  int repeat = 50;
  int volume = p.size();
  if (just_data) {
    printf(
        "name cycles_per_byte cycles_per_byte_err  gb_per_s gb_per_s_err \n");
  }
  size_t strlength = rapid_stringme((char *)p.data()).size();
  if (verbose)
    std::cout << "input length is " << p.size() << " stringified length is "
              << strlength << std::endl;
  BEST_TIME_NOCHECK("despacing with RapidJSON",
                    rapid_stringme((char *)p.data()), , repeat, volume,
                    !just_data);
  BEST_TIME_NOCHECK(
      "despacing with RapidJSON Insitu", rapid_stringme_insitu((char *)buffer),
      memcpy(buffer, p.data(), p.size()), repeat, volume, !just_data);
  memcpy(buffer, p.data(), p.size());
  size_t outlength;
  uint8_t *cbuffer = (uint8_t *)buffer;
  for (auto imple : simdjson::available_implementations) {
    BEST_TIME((std::string("simdjson->minify+")+imple->name()).c_str(), (imple->minify(cbuffer, p.size(), cbuffer, outlength), outlength),
            outlength, memcpy(buffer, p.data(), p.size()), repeat, volume,
            !just_data);
  }

  printf("minisize = %zu, original size = %zu  (minified down to %.2f percent "
         "of original) \n",
         outlength, p.size(), outlength * 100.0 / p.size());

  /***
   * Is it worth it to minify before parsing?
   ***/
  rapidjson::Document d;
  BEST_TIME("RapidJSON Insitu orig", d.ParseInsitu(buffer).HasParseError(),
            false, memcpy(buffer, p.data(), p.size()), repeat, volume,
            !just_data);

  char *mini_buffer = simdjson::internal::allocate_padded_buffer(p.size() + 1);
  size_t minisize;
  simdjson::active_implementation->minify((const uint8_t *)p.data(), p.size(),
                                          (uint8_t *)mini_buffer, minisize);
  mini_buffer[minisize] = '\0';

  BEST_TIME("RapidJSON Insitu despaced", d.ParseInsitu(buffer).HasParseError(),
            false, memcpy(buffer, mini_buffer, p.size()), repeat, volume,
            !just_data);

  size_t ast_buffer_size = p.size() * 2;
  size_t *ast_buffer = (size_t *)malloc(ast_buffer_size * sizeof(size_t));

  BEST_TIME(
      "sajson orig",
      sajson::parse(sajson::bounded_allocation(ast_buffer, ast_buffer_size),
                    sajson::mutable_string_view(p.size(), buffer))
          .is_valid(),
      true, memcpy(buffer, p.data(), p.size()), repeat, volume, !just_data);

  BEST_TIME(
      "sajson despaced",
      sajson::parse(sajson::bounded_allocation(ast_buffer, ast_buffer_size),
                    sajson::mutable_string_view(minisize, buffer))
          .is_valid(),
      true, memcpy(buffer, mini_buffer, p.size()), repeat, volume, !just_data);

  simdjson::ParsedJson pj;
  bool is_alloc_ok = pj.allocate_capacity(p.size(), 1024);
  if (!is_alloc_ok) {
    fprintf(stderr, "failed to allocate memory\n");
    return EXIT_FAILURE;
  }
  bool automated_reallocation = false;
  BEST_TIME("simdjson orig",
            simdjson::json_parse((const uint8_t *)buffer, p.size(), pj,
                                 automated_reallocation),
            simdjson::SUCCESS, memcpy(buffer, p.data(), p.size()), repeat, volume,
            !just_data);

  simdjson::ParsedJson pj2;
  bool is_alloc_ok2 = pj2.allocate_capacity(p.size(), 1024);
  if (!is_alloc_ok2) {
    fprintf(stderr, "failed to allocate memory\n");
    return EXIT_FAILURE;
  }
  automated_reallocation = false;
  BEST_TIME("simdjson despaced",
            simdjson::json_parse((const uint8_t *)buffer, minisize, pj2,
                                 automated_reallocation),
            simdjson::SUCCESS, memcpy(buffer, mini_buffer, p.size()), repeat, volume,
            !just_data);

  free(buffer);
  free(ast_buffer);
  free(mini_buffer);
}
<commit_msg>migrating minifier competition to new API (#597)<commit_after>#include <iostream>
#include <unistd.h>

#include "benchmark.h"
#include "simdjson.h"

// #define RAPIDJSON_SSE2 // bad
// #define RAPIDJSON_SSE42 // bad
#include "rapidjson/document.h"
#include "rapidjson/reader.h" // you have to check in the submodule
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include "sajson.h"

using namespace simdjson;
using namespace rapidjson;

std::string rapid_stringme_insitu(char *json) {
  Document d;
  d.ParseInsitu(json);
  if (d.HasParseError()) {
    std::cerr << "problem!" << std::endl;
    return ""; // should do something
  }
  StringBuffer buffer;
  Writer<StringBuffer> writer(buffer);
  d.Accept(writer);
  return buffer.GetString();
}

std::string rapid_stringme(char *json) {
  Document d;
  d.Parse(json);
  if (d.HasParseError()) {
    std::cerr << "problem!" << std::endl;
    return ""; // should do something
  }
  StringBuffer buffer;
  Writer<StringBuffer> writer(buffer);
  d.Accept(writer);
  return buffer.GetString();
}

int main(int argc, char *argv[]) {
  int c;
  bool verbose = false;
  bool just_data = false;

  while ((c = getopt(argc, argv, "vt")) != -1)
    switch (c) {
    case 't':
      just_data = true;
      break;
    case 'v':
      verbose = true;
      break;
    default:
      abort();
    }
  if (optind >= argc) {
    std::cerr << "Usage: " << argv[0] << " <jsonfile>" << std::endl;
    exit(1);
  }
  const char *filename = argv[optind];
  auto [p, error] = simdjson::padded_string::load(filename);
  if (error) {
    std::cerr << "Could not load the file " << filename << std::endl;
    return EXIT_FAILURE;
  }
  if (verbose) {
    std::cout << "Input has ";
    if (p.size() > 1024 * 1024)
      std::cout << p.size() / (1024 * 1024) << " MB ";
    else if (p.size() > 1024)
      std::cout << p.size() / 1024 << " KB ";
    else
      std::cout << p.size() << " B ";
    std::cout << std::endl;
  }
  char *buffer = simdjson::internal::allocate_padded_buffer(p.size() + 1);
  memcpy(buffer, p.data(), p.size());
  buffer[p.size()] = '\0';

  int repeat = 50;
  int volume = p.size();
  if (just_data) {
    printf(
        "name cycles_per_byte cycles_per_byte_err  gb_per_s gb_per_s_err \n");
  }
  size_t strlength = rapid_stringme((char *)p.data()).size();
  if (verbose)
    std::cout << "input length is " << p.size() << " stringified length is "
              << strlength << std::endl;
  BEST_TIME_NOCHECK("despacing with RapidJSON",
                    rapid_stringme((char *)p.data()), , repeat, volume,
                    !just_data);
  BEST_TIME_NOCHECK(
      "despacing with RapidJSON Insitu", rapid_stringme_insitu((char *)buffer),
      memcpy(buffer, p.data(), p.size()), repeat, volume, !just_data);
  memcpy(buffer, p.data(), p.size());
  size_t outlength;
  uint8_t *cbuffer = (uint8_t *)buffer;
  for (auto imple : simdjson::available_implementations) {
    BEST_TIME((std::string("simdjson->minify+")+imple->name()).c_str(), (imple->minify(cbuffer, p.size(), cbuffer, outlength), outlength),
            outlength, memcpy(buffer, p.data(), p.size()), repeat, volume,
            !just_data);
  }

  printf("minisize = %zu, original size = %zu  (minified down to %.2f percent "
         "of original) \n",
         outlength, p.size(), outlength * 100.0 / p.size());

  /***
   * Is it worth it to minify before parsing?
   ***/
  rapidjson::Document d;
  BEST_TIME("RapidJSON Insitu orig", d.ParseInsitu(buffer).HasParseError(),
            false, memcpy(buffer, p.data(), p.size()), repeat, volume,
            !just_data);

  char *mini_buffer = simdjson::internal::allocate_padded_buffer(p.size() + 1);
  size_t minisize;
  simdjson::active_implementation->minify((const uint8_t *)p.data(), p.size(),
                                          (uint8_t *)mini_buffer, minisize);
  mini_buffer[minisize] = '\0';

  BEST_TIME("RapidJSON Insitu despaced", d.ParseInsitu(buffer).HasParseError(),
            false, memcpy(buffer, mini_buffer, p.size()), repeat, volume,
            !just_data);

  size_t ast_buffer_size = p.size() * 2;
  size_t *ast_buffer = (size_t *)malloc(ast_buffer_size * sizeof(size_t));

  BEST_TIME(
      "sajson orig",
      sajson::parse(sajson::bounded_allocation(ast_buffer, ast_buffer_size),
                    sajson::mutable_string_view(p.size(), buffer))
          .is_valid(),
      true, memcpy(buffer, p.data(), p.size()), repeat, volume, !just_data);

  BEST_TIME(
      "sajson despaced",
      sajson::parse(sajson::bounded_allocation(ast_buffer, ast_buffer_size),
                    sajson::mutable_string_view(minisize, buffer))
          .is_valid(),
      true, memcpy(buffer, mini_buffer, p.size()), repeat, volume, !just_data);

  simdjson::document::parser parser;
  bool automated_reallocation = false;
  BEST_TIME("simdjson orig",
            parser.parse((const uint8_t *)buffer, p.size(),
                                 automated_reallocation).error(),
            simdjson::SUCCESS, memcpy(buffer, p.data(), p.size()), repeat, volume,
            !just_data);
  BEST_TIME("simdjson despaced",
            parser.parse((const uint8_t *)buffer, minisize,
                                 automated_reallocation).error(),
            simdjson::SUCCESS, memcpy(buffer, mini_buffer, p.size()), repeat, volume,
            !just_data);

  free(buffer);
  free(ast_buffer);
  free(mini_buffer);
}
<|endoftext|>


<commit_before>//
// Created by andreanistico on 06/02/17.
//

#include <iostream>
#include "include/Lander/StatesClasses.hpp"
#include "Lander/Lander.h"
#include "parameters.h"

Lander::Lander()
        : _horizontaErr((double)0)    , _tauHold((double)0), _tauLost((double)0), _tauErr((double)0), _NHold(0),
          _NLost(0),_NComp(0), _initS(&_machine), _holdS(&_machine)  , _asceS(&_machine)  , _descS(&_machine),_compS(&_machine),
          _rtolS(&_machine),_landS(&_machine), _err(0,0,0), _err_int(0,0,0), _err_diff(0,0,0), _dt(0), _prevTime(0), _actualTime(0),_actualState(0),_prevState(0),
          _verticalErr(0), _holdPIDX(params_automatic::KpHold,0,params_automatic::KiHold), _holdPIDY(params_automatic::KdHold,0,params_automatic::KiHold)
{

    initStateMachine();
    _actualState = _machine.getActualNodeId();
    _err_prev = _err;

}

void Lander::setState(MavState pose) {
    _state = pose;
}

MavState Lander::getState() {
    return _state;
}

MavState Lander::getCommand() {
    return _setPoint;
}

void Lander::initStateMachine() {

    //Link signals
    _machine._horizontaErr =  &_horizontaErr;
    _machine._verticalErr  =  &_verticalErr;
    _machine._tauErr       =  &_tauErr;
    _machine._tauHold      =  &_tauHold;
    _machine._tauLost      =  &_tauLost;
    _machine._NLost        =  &_NLost;
    _machine._NHold        =  &_NHold;
    _machine._NComp        =  &_NComp;
    _machine._state        =  &_state;
    _machine._setPoint     =  &_setPoint;

    //Link states
    _initS._nextState    = &_holdS;

    _holdS._nextAscState = &_asceS;
    _holdS._nextDesState = &_descS;
    _holdS._nextState    = &_rtolS;

    _asceS._nextState    = &_holdS;

    _descS._nextState    = &_holdS;

    _rtolS._nextComState = &_compS;
    _rtolS._nextState    = &_holdS;

    _compS._nextState    = &_asceS;
    _compS._nextLanState = &_landS;

    _landS._nextState    = &_asceS;

    _machine.setStatePtr(&_initS);

    _tauHold = 0.5 * params_automatic::platformLenght;
    _tauLost = params_automatic::platformLenght * 0.7;

    //Print actual state
    std::cout << "Actual state: " << _machine.getActualNodeId() << std::endl;

}

void Lander::setPlatformState(const MavState platformState) {
    _platformState = platformState;
}

void Lander::updateSignals() {

    //Compute horizontal error
    double xTemp = _state.getX();
    double yTemp = _state.getY();
    double zTemp = _state.getZ();
    double xPlatTemp = _platformState.getX();
    double yPlatTemp = _platformState.getY();
    double zPlatTemp = _platformState.getZ();

    double dx = xPlatTemp - xTemp;
    double dy = yPlatTemp - yTemp;
    double dz = zPlatTemp - zTemp + PLATFORM_OFFSET;

    _err[0] = dx;
    _err[1] = dy;
    _err[2] = 0; //Trick, used to calculate horizontal error

    _horizontaErr = _err.norm();
    _err[2]       = dz;
    _verticalErr  = _err[2];

    if( _actualState == AbstractLandState::states::HOLD ||
        _actualState == AbstractLandState::states::ASCE ||
        _actualState == AbstractLandState::states::DESC ||
        _actualState == AbstractLandState::states::COMP ||
        _actualState == AbstractLandState::states::R2LA ){

        //Increment N if needed
        if (_horizontaErr < _tauHold) {
            _NLost = 0;
            _NHold++;
        }
        else if (_horizontaErr > _tauLost) {
            _NHold = 0;
            _NComp = 0;
            _NLost++;
        }

        if(_actualState == AbstractLandState::states::R2LA || _actualState == AbstractLandState::states::COMP){

            if(_prevState == AbstractLandState::states::HOLD) _NComp = 0;
            //Check whether we are on place to land
            if (_horizontaErr < _tauHold * 0.5) {
                _NComp++;
            } else{
                _NComp = 0;
            }
        }

        _err_prev = _err;
    }

#ifdef DEBUG

    std::cout << "**********************************" << std::endl;
    std::cout << "STATE: " << _actualState<< std::endl;
    std::cout << "HERRO: " << _horizontaErr<< std::endl;
    std::cout << "HERRV: " << _verticalErr<< std::endl;
    std::cout << "NHOLD: " << _NHold<< std::endl;
    std::cout << "NLOST: " << _NLost<< std::endl;
    std::cout << "NCOMP: " << _NComp<< std::endl;
    std::cout << "INTEX: " << _err_int[0] << std::endl;
    std::cout << "INTEY: " << _err_int[1] << std::endl;
    std::cout << "**********************************" << std::endl;
#endif

}

void Lander::handleMachine() {

    updateSignals();
    _machine.handle();
}

int Lander::getActualMachineState() {
    return _machine.getActualNodeId();
}

void Lander::run() {

    handleMachine();
    _actualState = _machine.getActualNodeId();
    managetime();

    static bool initDone = false;
    switch (_actualState){

        case (AbstractLandState::states::INIT):
            if(!initDone){
                init();
                initDone = true;
            }
            break;

        case (AbstractLandState::states::HOLD):
            initDone = false;
            clampZSP();
            hold();
            break;
        case (AbstractLandState::states::DESC):

            desc();
            clampZSP();
            break;
        case (AbstractLandState::states::ASCE):

            asce();
            clampZSP();

            break;

        case (AbstractLandState::states::R2LA):
            clampZSP();
            hold();
            break;

        case (AbstractLandState::states::COMP):
            hold();
            comp();
            break;
        case (AbstractLandState::states::LAND):
            land();
            break;

        default:
            hold();
            break;

    }
    _prevState = _actualState;

}

void Lander::resetSetPoint() {

    _setPoint = _state;
    _setPoint.setType(MavState::type::POSITION);

}

void Lander::updateIntegrals() {

    _err_int[0] +=  _dt * _err[0];
    _err_int[1] +=  _dt * _err[1];

    double tempx,tempy;

    tempx = common::clamp(_err_int[0],params_automatic::minIntValue,params_automatic::maxIntValue);
    tempy = common::clamp(_err_int[1],params_automatic::minIntValue,params_automatic::maxIntValue);

    _err_int[0] =  tempx;
    _err_int[1] =  tempy;

}

void Lander::managetime() {

    _actualTime = common::time::getTimeMilliSecond();
    double dt = _prevTime != 0 ? (_actualTime - _prevTime) * (double)MILLI2SECS : 0.0;
    _prevTime = _actualTime;
    _dt = dt;

}

void Lander::resetIntegrals() {

    _err_int[0] = 0;
    _err_int[1] = 0;

}

void Lander::init() {

    //Set point to my position
    resetSetPoint();

    //Go to max tracking height
    _setPoint.setZ(params_automatic::zMax);

}

void Lander::hold() {

    //This function is purely tracking, nothing more

    /*
     * Tracking is performed by POSITION control, issuing the position setpoint
     * in order to achieve the desired velocity calculated by:
     *
     * Vdes = K * ep + Vplat
     * or
     * Psp = Pplat + K * Vplat
     *
     * where:
     *
     * Vdes = desired velocity, K = proportional gain, ep = position error, Vplat = paltform velocity
     */

    Eigen::Vector2d tempVel(_platformState.getVx(),_platformState.getVy());

    double xTarget = _holdPIDX.getOutput(_state.getX(), _platformState.getX());
    double yTarget = _holdPIDY.getOutput(_state.getY(), _platformState.getY());
    Eigen::Vector2d targetVect(xTarget,yTarget);

    updateIntegrals();
    //PosSP = PlatPos + K * Vplat
    targetVect += params_automatic::KpHoldV * tempVel;

    //Fill right fields
    _setPoint.setPosition(targetVect(0),targetVect(1),_setPoint.getZ());
    _setPoint.setType(MavState::POSITION);

}

void Lander::asce() {

    resetIntegrals();
    _setPoint.setZ(_setPoint.getZ() + 0.1);

}

void Lander::desc() {

    _setPoint.setZ(_setPoint.getZ() - 0.1);
}

void Lander::comp() {

    //Calculate desired vertical velocity in order to compensate oscillations
    double dz = - _state.getZ() + _platformState.getZ() + PLATFORM_OFFSET;
    double desc = common::interpolate(fabs(dz), DRATE_MAX, DRATE_MIN, TMAX, TMIN);
    double z_target_v = _platformState.getVz() - desc;

    double err_v = z_target_v - _state.getVz();

    double corr = 1;

    if(_platformState.getVz() > 0) corr = 1.2;

    z_target_v += corr * params_automatic::KPCompV * (err_v);

    //Now we need to transform this velocity in a position setpoint since in Firmware:
    // VelSP = Kp * PosError then PosSP = ( VelSP / Kp ) + RobotPos

    _setPoint.setZ((z_target_v) + _state.getZ());

}

void Lander::clampZSP() {

    double temp;
    temp = common::clamp(_setPoint.getZ(),params_automatic::zMin,params_automatic::zMax);

    _setPoint.setZ(temp);
}

void Lander::land() {

    resetSetPoint();
    _setPoint.setZ(_state.getZ()-10);

}

<commit_msg>fix pid constructor<commit_after>//
// Created by andreanistico on 06/02/17.
//

#include <iostream>
#include "include/Lander/StatesClasses.hpp"
#include "Lander/Lander.h"
#include "parameters.h"

Lander::Lander()
        : _horizontaErr((double)0)    , _tauHold((double)0), _tauLost((double)0), _tauErr((double)0), _NHold(0),
          _NLost(0),_NComp(0), _initS(&_machine), _holdS(&_machine)  , _asceS(&_machine)  , _descS(&_machine),_compS(&_machine),
          _rtolS(&_machine),_landS(&_machine), _err(0,0,0), _err_int(0,0,0), _err_diff(0,0,0), _dt(0), _prevTime(0), _actualTime(0),_actualState(0),_prevState(0),
          _verticalErr(0), _holdPIDX(params_automatic::KpHold,params_automatic::KiHold,0), _holdPIDY(params_automatic::KdHold,params_automatic::KiHold,0)
{

    initStateMachine();
    _actualState = _machine.getActualNodeId();
    _err_prev = _err;

}

void Lander::setState(MavState pose) {
    _state = pose;
}

MavState Lander::getState() {
    return _state;
}

MavState Lander::getCommand() {
    return _setPoint;
}

void Lander::initStateMachine() {

    //Link signals
    _machine._horizontaErr =  &_horizontaErr;
    _machine._verticalErr  =  &_verticalErr;
    _machine._tauErr       =  &_tauErr;
    _machine._tauHold      =  &_tauHold;
    _machine._tauLost      =  &_tauLost;
    _machine._NLost        =  &_NLost;
    _machine._NHold        =  &_NHold;
    _machine._NComp        =  &_NComp;
    _machine._state        =  &_state;
    _machine._setPoint     =  &_setPoint;

    //Link states
    _initS._nextState    = &_holdS;

    _holdS._nextAscState = &_asceS;
    _holdS._nextDesState = &_descS;
    _holdS._nextState    = &_rtolS;

    _asceS._nextState    = &_holdS;

    _descS._nextState    = &_holdS;

    _rtolS._nextComState = &_compS;
    _rtolS._nextState    = &_holdS;

    _compS._nextState    = &_asceS;
    _compS._nextLanState = &_landS;

    _landS._nextState    = &_asceS;

    _machine.setStatePtr(&_initS);

    _tauHold = 0.5 * params_automatic::platformLenght;
    _tauLost = params_automatic::platformLenght * 0.7;

    //Print actual state
    std::cout << "Actual state: " << _machine.getActualNodeId() << std::endl;

}

void Lander::setPlatformState(const MavState platformState) {
    _platformState = platformState;
}

void Lander::updateSignals() {

    //Compute horizontal error
    double xTemp = _state.getX();
    double yTemp = _state.getY();
    double zTemp = _state.getZ();
    double xPlatTemp = _platformState.getX();
    double yPlatTemp = _platformState.getY();
    double zPlatTemp = _platformState.getZ();

    double dx = xPlatTemp - xTemp;
    double dy = yPlatTemp - yTemp;
    double dz = zPlatTemp - zTemp + PLATFORM_OFFSET;

    _err[0] = dx;
    _err[1] = dy;
    _err[2] = 0; //Trick, used to calculate horizontal error

    _horizontaErr = _err.norm();
    _err[2]       = dz;
    _verticalErr  = _err[2];

    if( _actualState == AbstractLandState::states::HOLD ||
        _actualState == AbstractLandState::states::ASCE ||
        _actualState == AbstractLandState::states::DESC ||
        _actualState == AbstractLandState::states::COMP ||
        _actualState == AbstractLandState::states::R2LA ){

        //Increment N if needed
        if (_horizontaErr < _tauHold) {
            _NLost = 0;
            _NHold++;
        }
        else if (_horizontaErr > _tauLost) {
            _NHold = 0;
            _NComp = 0;
            _NLost++;
        }

        if(_actualState == AbstractLandState::states::R2LA || _actualState == AbstractLandState::states::COMP){

            if(_prevState == AbstractLandState::states::HOLD) _NComp = 0;
            //Check whether we are on place to land
            if (_horizontaErr < _tauHold * 0.5) {
                _NComp++;
            } else{
                _NComp = 0;
            }
        }

        _err_prev = _err;
    }

#ifdef DEBUG

    std::cout << "**********************************" << std::endl;
    std::cout << "STATE: " << _actualState<< std::endl;
    std::cout << "HERRO: " << _horizontaErr<< std::endl;
    std::cout << "HERRV: " << _verticalErr<< std::endl;
    std::cout << "NHOLD: " << _NHold<< std::endl;
    std::cout << "NLOST: " << _NLost<< std::endl;
    std::cout << "NCOMP: " << _NComp<< std::endl;
    std::cout << "INTEX: " << _err_int[0] << std::endl;
    std::cout << "INTEY: " << _err_int[1] << std::endl;
    std::cout << "**********************************" << std::endl;
#endif

}

void Lander::handleMachine() {

    updateSignals();
    _machine.handle();
}

int Lander::getActualMachineState() {
    return _machine.getActualNodeId();
}

void Lander::run() {

    handleMachine();
    _actualState = _machine.getActualNodeId();
    managetime();

    static bool initDone = false;
    switch (_actualState){

        case (AbstractLandState::states::INIT):
            if(!initDone){
                init();
                initDone = true;
            }
            break;

        case (AbstractLandState::states::HOLD):
            initDone = false;
            clampZSP();
            hold();
            break;
        case (AbstractLandState::states::DESC):

            desc();
            clampZSP();
            break;
        case (AbstractLandState::states::ASCE):

            asce();
            clampZSP();

            break;

        case (AbstractLandState::states::R2LA):
            clampZSP();
            hold();
            break;

        case (AbstractLandState::states::COMP):
            hold();
            comp();
            break;
        case (AbstractLandState::states::LAND):
            land();
            break;

        default:
            hold();
            break;

    }
    _prevState = _actualState;

}

void Lander::resetSetPoint() {

    _setPoint = _state;
    _setPoint.setType(MavState::type::POSITION);

}

void Lander::updateIntegrals() {

    _err_int[0] +=  _dt * _err[0];
    _err_int[1] +=  _dt * _err[1];

    double tempx,tempy;

    tempx = common::clamp(_err_int[0],params_automatic::minIntValue,params_automatic::maxIntValue);
    tempy = common::clamp(_err_int[1],params_automatic::minIntValue,params_automatic::maxIntValue);

    _err_int[0] =  tempx;
    _err_int[1] =  tempy;

}

void Lander::managetime() {

    _actualTime = common::time::getTimeMilliSecond();
    double dt = _prevTime != 0 ? (_actualTime - _prevTime) * (double)MILLI2SECS : 0.0;
    _prevTime = _actualTime;
    _dt = dt;

}

void Lander::resetIntegrals() {

    _err_int[0] = 0;
    _err_int[1] = 0;

}

void Lander::init() {

    //Set point to my position
    resetSetPoint();

    //Go to max tracking height
    _setPoint.setZ(params_automatic::zMax);

}

void Lander::hold() {

    //This function is purely tracking, nothing more

    /*
     * Tracking is performed by POSITION control, issuing the position setpoint
     * in order to achieve the desired velocity calculated by:
     *
     * Vdes = K * ep + Vplat
     * or
     * Psp = Pplat + K * Vplat
     *
     * where:
     *
     * Vdes = desired velocity, K = proportional gain, ep = position error, Vplat = paltform velocity
     */

    Eigen::Vector2d tempVel(_platformState.getVx(),_platformState.getVy());

    double xTarget = _holdPIDX.getOutput(_state.getX(), _platformState.getX());
    double yTarget = _holdPIDY.getOutput(_state.getY(), _platformState.getY());
    Eigen::Vector2d targetVect(xTarget,yTarget);

    updateIntegrals();
    //PosSP = PlatPos + K * Vplat
    targetVect += params_automatic::KpHoldV * tempVel;

    //Fill right fields
    _setPoint.setPosition(targetVect(0),targetVect(1),_setPoint.getZ());
    _setPoint.setType(MavState::POSITION);

}

void Lander::asce() {

    resetIntegrals();
    _setPoint.setZ(_setPoint.getZ() + 0.1);

}

void Lander::desc() {

    _setPoint.setZ(_setPoint.getZ() - 0.1);
}

void Lander::comp() {

    //Calculate desired vertical velocity in order to compensate oscillations
    double dz = - _state.getZ() + _platformState.getZ() + PLATFORM_OFFSET;
    double desc = common::interpolate(fabs(dz), DRATE_MAX, DRATE_MIN, TMAX, TMIN);
    double z_target_v = _platformState.getVz() - desc;

    double err_v = z_target_v - _state.getVz();

    double corr = 1;

    if(_platformState.getVz() > 0) corr = 1.2;

    z_target_v += corr * params_automatic::KPCompV * (err_v);

    //Now we need to transform this velocity in a position setpoint since in Firmware:
    // VelSP = Kp * PosError then PosSP = ( VelSP / Kp ) + RobotPos

    _setPoint.setZ((z_target_v) + _state.getZ());

}

void Lander::clampZSP() {

    double temp;
    temp = common::clamp(_setPoint.getZ(),params_automatic::zMin,params_automatic::zMax);

    _setPoint.setZ(temp);
}

void Lander::land() {

    resetSetPoint();
    _setPoint.setZ(_state.getZ()-10);

}

<|endoftext|>


<commit_before>#include <MyHeaders\SocketClient.h>

SocketClient::SocketClient()
{
	Socket = 0;
}

SocketClient::SocketClient(SOCKET con)
{
	Socket = con;
}

SocketClient::SocketClient(const unsigned int major, const unsigned int minor)
{
	Socket = 0;
	Init(major, minor);
}

bool SocketClient::WinsockInitialized()
{
	SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (s == INVALID_SOCKET && WSAGetLastError() == WSANOTINITIALISED)
		return false;

	closesocket(s);
	return true;
}

SocketClient::operator SOCKET()
{
	return Socket;
}

bool SocketClient::Init(const unsigned int major, const unsigned int minor)
{
	if (!WinsockInitialized())
		return WSAStartup(MAKEWORD(major, minor), &wsaData) == 0;

	return false;
}

bool SocketClient::Connect(const TCHAR *host, const TCHAR *port)
{
	ADDRINFOT *res;
	ADDRINFOT *ptr;
	ADDRINFOT hints;

	memset(&hints, 0, sizeof(hints));

	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;

	if (GetAddrInfo(host, port, &hints, &res))
	{
		Close();
		return false;
	}

	Socket = 0;

	for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
	{
		Socket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);

		if (Socket == INVALID_SOCKET)
		{
			Socket = 0;
			continue;
		}

		if (connect(Socket, ptr->ai_addr, ptr->ai_addrlen) == SOCKET_ERROR)
		{
			closesocket(Socket);
			Socket = 0;
			continue;
		}

		break;
	}

	FreeAddrInfo(res);

	return Socket != 0;
}

int SocketClient::Send(const void *buffer, const unsigned int len, const SCSFlag flags)
{
	int res;
	if ((res = send(Socket, (const char*)buffer, len, flags)) == SOCKET_ERROR)
	{
		Close();
		return 0;
	}

	return res;
}

int SocketClient::Recieve(void *buffer, const unsigned int len, const SCRFlag flags)
{
	int res;
	if ((res = recv(Socket, (char*)buffer, len, flags)) == SOCKET_ERROR)
	{
		Close();
		return 0;
	}

	return res;
}

bool SocketClient::SetBlockingState(const bool blocking)
{
	u_long iMode = blocking ? 1 : 0;
	return ioctlsocket(Socket, FIONBIO, &iMode) == 0;
}
bool SocketClient::CheckReadability(const unsigned int secs, const unsigned int microsecs)
{
	timeval tv = { secs, microsecs };
	fd_set fd;
	FD_ZERO(&fd);
	FD_SET(Socket, &fd);
	return  select(Socket, &fd, 0, 0, &tv) > 0;
}
bool SocketClient::CheckWritability(const unsigned int secs, const unsigned int microsecs)
{
	timeval tv = { secs, microsecs };
	fd_set fd;
	FD_ZERO(&fd);
	FD_SET(Socket, &fd);
	return  select(Socket, 0, &fd, 0, &tv) > 0;
}

bool SocketClient::ShutDownRcv()
{
	if (shutdown(Socket, SD_RECEIVE) == SOCKET_ERROR)
	{
		Close();
		return false;
	}
	return true;
}

bool SocketClient::ShutDownSnd()
{
	if (shutdown(Socket, SD_SEND) == SOCKET_ERROR)
	{
		Close();
		return false;
	}
	return true;
}

unsigned int SocketClient::GetPendingDataSize()
{
	unsigned long int size = 0;
	if (ioctlsocket(Socket, FIONREAD, &size) != 0)
		return 0;

	return size;
}

void SocketClient::Close()
{
	if (Socket)
	{
		closesocket(Socket);
		Socket = 0;
	}
}

bool SocketClient::Clean()
{
	if (WinsockInitialized())
	{
		if (WSACleanup() == 0)
			return true;
	}

	return false;
}

SocketClient::~SocketClient()
{
	Close();
}<commit_msg>Minor change<commit_after>#include <MyHeaders\SocketClient.h>

SocketClient::SocketClient()
{
	Socket = 0;
}

SocketClient::SocketClient(SOCKET con)
{
	Socket = con;
}

SocketClient::SocketClient(const unsigned int major, const unsigned int minor)
{
	Socket = 0;
	Init(major, minor);
}

bool SocketClient::WinsockInitialized()
{
	SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (s == INVALID_SOCKET && WSAGetLastError() == WSANOTINITIALISED)
		return false;

	closesocket(s);
	return true;
}

SocketClient::operator SOCKET()
{
	return Socket;
}

bool SocketClient::Init(const unsigned int major, const unsigned int minor)
{
	if (!WinsockInitialized())
		return WSAStartup(MAKEWORD(major, minor), &wsaData) == 0;

	return false;
}

bool SocketClient::Connect(const TCHAR *host, const TCHAR *port)
{
	ADDRINFOT *res;
	ADDRINFOT *ptr;
	ADDRINFOT hints;

	memset(&hints, 0, sizeof(hints));

	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;

	if (GetAddrInfo(host, port, &hints, &res))
	{
		Close();
		return false;
	}

	Socket = 0;

	for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
	{
		Socket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);

		if (Socket == INVALID_SOCKET)
		{
			Socket = 0;
			continue;
		}

		if (connect(Socket, ptr->ai_addr, ptr->ai_addrlen) == SOCKET_ERROR)
		{
			closesocket(Socket);
			Socket = 0;
			continue;
		}

		break;
	}

	FreeAddrInfo(res);

	return Socket != 0;
}

int SocketClient::Send(const void *buffer, const unsigned int len, const SCSFlag flags)
{
	int res;
	if ((res = send(Socket, (const char*)buffer, len, flags)) == SOCKET_ERROR)
	{
		Close();
		return 0;
	}

	return res;
}

int SocketClient::Recieve(void *buffer, const unsigned int len, const SCRFlag flags)
{
	int res;
	if ((res = recv(Socket, (char*)buffer, len, flags)) == SOCKET_ERROR)
	{
		Close();
		return 0;
	}

	return res;
}

bool SocketClient::SetBlockingState(const bool blocking)
{
	u_long iMode = blocking ? 1 : 0;
	return ioctlsocket(Socket, FIONBIO, &iMode) == 0;
}
bool SocketClient::CheckReadability(const unsigned int secs, const unsigned int microsecs)
{
	timeval tv = { secs, microsecs };
	fd_set fd;
	FD_ZERO(&fd);
	FD_SET(Socket, &fd);
	return  select(Socket, &fd, 0, 0, &tv) > 0;
}
bool SocketClient::CheckWritability(const unsigned int secs, const unsigned int microsecs)
{
	timeval tv = { secs, microsecs };
	fd_set fd;
	FD_ZERO(&fd);
	FD_SET(Socket, &fd);
	return  select(Socket, 0, &fd, 0, &tv) > 0;
}

bool SocketClient::ShutDownRcv()
{
	if (shutdown(Socket, SD_RECEIVE) == SOCKET_ERROR)
	{
		Close();
		return false;
	}
	return true;
}

bool SocketClient::ShutDownSnd()
{
	if (shutdown(Socket, SD_SEND) == SOCKET_ERROR)
	{
		Close();
		return false;
	}
	return true;
}

unsigned int SocketClient::GetPendingDataSize()
{
	unsigned long int size = 0;
	if (ioctlsocket(Socket, FIONREAD, &size) != 0)
		return 0;

	return size;
}

void SocketClient::Close()
{
	if (Socket)
	{
		closesocket(Socket);
		Socket = 0;
	}
}

bool SocketClient::Clean()
{
	if (WinsockInitialized())
	{
		return WSACleanup() == 0;
	}

	return false;
}

SocketClient::~SocketClient()
{
	Close();
}<|endoftext|>