<commit_before>/******************************************************************************

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/
#include "vtkChartHistogram.h"

#include "vtkAxis.h"
#include "vtkCommand.h"
#include "vtkContext2D.h"
#include "vtkContextMouseEvent.h"
#include "vtkContextScene.h"
#include "vtkObjectFactory.h"
#include "vtkPiecewiseFunction.h"
#include "vtkPiecewiseFunctionItem.h"
#include "vtkPiecewiseControlPointsItem.h"
#include "vtkPen.h"
#include "vtkPlot.h"
#include "vtkPlotBar.h"
#include "vtkScalarsToColors.h"
#include "vtkTable.h"
#include "vtkTransform2D.h"

//-----------------------------------------------------------------------------
class vtkHistogramMarker : public vtkPlot
{
public:
  static vtkHistogramMarker * New();
  double PositionX;

  bool Paint(vtkContext2D *painter) override
  {
    vtkNew<vtkPen> pen;
    pen->SetColor(255, 0, 0, 255);
    pen->SetWidth(2.0);
    painter->ApplyPen(pen.Get());
    painter->DrawLine(PositionX, 0, PositionX, 1e9);
    return true;
  }
};
vtkStandardNewMacro(vtkHistogramMarker)

//-----------------------------------------------------------------------------
vtkStandardNewMacro(vtkChartHistogram)

//-----------------------------------------------------------------------------
vtkChartHistogram::vtkChartHistogram()
{
  this->SetBarWidthFraction(1.0);
  this->SetRenderEmpty(true);
  this->SetAutoAxes(false);
  this->ZoomWithMouseWheelOff();
  this->GetAxis(vtkAxis::LEFT)->SetTitle("");
  this->GetAxis(vtkAxis::BOTTOM)->SetTitle("");
  this->GetAxis(vtkAxis::BOTTOM)->SetBehavior(vtkAxis::FIXED);
  this->GetAxis(vtkAxis::BOTTOM)->SetRange(0, 255);
  this->GetAxis(vtkAxis::LEFT)->SetBehavior(vtkAxis::FIXED);
  this->GetAxis(vtkAxis::LEFT)->SetRange(0.0001, 10);
  this->GetAxis(vtkAxis::LEFT)->SetMinimumLimit(1);
  this->GetAxis(vtkAxis::LEFT)->SetLogScale(true);
  this->GetAxis(vtkAxis::RIGHT)->SetBehavior(vtkAxis::FIXED);
  this->GetAxis(vtkAxis::RIGHT)->SetRange(0.0, 1.0);
  this->GetAxis(vtkAxis::RIGHT)->SetVisible(true);

  // Set up the plot bar
  this->AddPlot(this->HistogramPlotBar.Get());
  this->HistogramPlotBar->SetColor(0, 0, 255, 255);
  this->HistogramPlotBar->GetPen()->SetLineType(vtkPen::NO_PEN);

  // Set up and add the opacity editor chart items
  this->OpacityFunctionItem->SetOpacity(0.0); // don't show the transfer function
  this->AddPlot(this->OpacityFunctionItem.Get());
  this->SetPlotCorner(this->OpacityFunctionItem.Get(), 1);

  this->OpacityControlPointsItem->SetEndPointsXMovable(false);
  this->OpacityControlPointsItem->SetEndPointsYMovable(true);

  vtkPen* pen = this->OpacityControlPointsItem->GetPen();
  pen->SetLineType(vtkPen::SOLID_LINE);
  pen->SetColor(0, 0, 0);
  pen->SetOpacity(255);
  pen->SetWidth(2.0);
  this->AddPlot(this->OpacityControlPointsItem.Get());
  this->SetPlotCorner(this->OpacityControlPointsItem.Get(), 1);
}

//-----------------------------------------------------------------------------
bool vtkChartHistogram::MouseDoubleClickEvent(const vtkContextMouseEvent &m)
{
  // Determine the location of the click, and emit something we can listen to!
  vtkPlotBar *histo = nullptr;
  if (this->GetNumberOfPlots() > 0)
  {
    histo = vtkPlotBar::SafeDownCast(this->GetPlot(0));
  }
  if (!histo)
  {
    return false;
  }
  this->CalculateUnscaledPlotTransform(histo->GetXAxis(), histo->GetYAxis(),
                                       this->Transform.Get());
  vtkVector2f pos;
  this->Transform->InverseTransformPoints(m.GetScenePos().GetData(), pos.GetData(),
                                          1);
  this->PositionX = pos.GetX();
  this->Marker->PositionX = this->PositionX;
  this->Marker->Modified();
  this->Scene->SetDirty(true);
  if (this->GetNumberOfPlots() == 1)
  {
    // Work around a bug in the charts - ensure corner is invalid for the plot.
    this->Marker->SetXAxis(nullptr);
    this->Marker->SetYAxis(nullptr);
    this->AddPlot(this->Marker.Get());
  }
  this->InvokeEvent(vtkCommand::CursorChangedEvent);
  return true;
}

//-----------------------------------------------------------------------------
void vtkChartHistogram::SetHistogramInputData(vtkTable* table,
                                              const char* xAxisColumn,
                                              const char* yAxisColumn)
{
  this->HistogramPlotBar->SetInputData(table, xAxisColumn, yAxisColumn);
}

//-----------------------------------------------------------------------------
void vtkChartHistogram::SetScalarVisibility(bool visible)
{
  this->HistogramPlotBar->SetScalarVisibility(visible);
}

//-----------------------------------------------------------------------------
void vtkChartHistogram::ScalarVisibilityOn()
{
  this->HistogramPlotBar->ScalarVisibilityOn();
}

//-----------------------------------------------------------------------------
void vtkChartHistogram::SetLookupTable(vtkScalarsToColors* lut)
{
  this->HistogramPlotBar->SetLookupTable(lut);
}

//-----------------------------------------------------------------------------
void vtkChartHistogram::SelectColorArray(const char* arrayName)
{
  this->HistogramPlotBar->SelectColorArray(arrayName);
}

//-----------------------------------------------------------------------------
void vtkChartHistogram::SetOpacityFunction(vtkPiecewiseFunction* opacityFunction)
{
  this->OpacityFunctionItem->SetPiecewiseFunction(opacityFunction);
  this->OpacityControlPointsItem->SetPiecewiseFunction(opacityFunction);
}
<commit_msg>Prevent endpoint removal from opacity function editor<commit_after>/******************************************************************************

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/
#include "vtkChartHistogram.h"

#include "vtkAxis.h"
#include "vtkCommand.h"
#include "vtkContext2D.h"
#include "vtkContextMouseEvent.h"
#include "vtkContextScene.h"
#include "vtkObjectFactory.h"
#include "vtkPiecewiseFunction.h"
#include "vtkPiecewiseFunctionItem.h"
#include "vtkPiecewiseControlPointsItem.h"
#include "vtkPen.h"
#include "vtkPlot.h"
#include "vtkPlotBar.h"
#include "vtkScalarsToColors.h"
#include "vtkTable.h"
#include "vtkTransform2D.h"

//-----------------------------------------------------------------------------
class vtkHistogramMarker : public vtkPlot
{
public:
  static vtkHistogramMarker * New();
  double PositionX;

  bool Paint(vtkContext2D *painter) override
  {
    vtkNew<vtkPen> pen;
    pen->SetColor(255, 0, 0, 255);
    pen->SetWidth(2.0);
    painter->ApplyPen(pen.Get());
    painter->DrawLine(PositionX, 0, PositionX, 1e9);
    return true;
  }
};
vtkStandardNewMacro(vtkHistogramMarker)

//-----------------------------------------------------------------------------
vtkStandardNewMacro(vtkChartHistogram)

//-----------------------------------------------------------------------------
vtkChartHistogram::vtkChartHistogram()
{
  this->SetBarWidthFraction(1.0);
  this->SetRenderEmpty(true);
  this->SetAutoAxes(false);
  this->ZoomWithMouseWheelOff();
  this->GetAxis(vtkAxis::LEFT)->SetTitle("");
  this->GetAxis(vtkAxis::BOTTOM)->SetTitle("");
  this->GetAxis(vtkAxis::BOTTOM)->SetBehavior(vtkAxis::FIXED);
  this->GetAxis(vtkAxis::BOTTOM)->SetRange(0, 255);
  this->GetAxis(vtkAxis::LEFT)->SetBehavior(vtkAxis::FIXED);
  this->GetAxis(vtkAxis::LEFT)->SetRange(0.0001, 10);
  this->GetAxis(vtkAxis::LEFT)->SetMinimumLimit(1);
  this->GetAxis(vtkAxis::LEFT)->SetLogScale(true);
  this->GetAxis(vtkAxis::RIGHT)->SetBehavior(vtkAxis::FIXED);
  this->GetAxis(vtkAxis::RIGHT)->SetRange(0.0, 1.0);
  this->GetAxis(vtkAxis::RIGHT)->SetVisible(true);

  // Set up the plot bar
  this->AddPlot(this->HistogramPlotBar.Get());
  this->HistogramPlotBar->SetColor(0, 0, 255, 255);
  this->HistogramPlotBar->GetPen()->SetLineType(vtkPen::NO_PEN);

  // Set up and add the opacity editor chart items
  this->OpacityFunctionItem->SetOpacity(0.0); // don't show the transfer function
  this->AddPlot(this->OpacityFunctionItem.Get());
  this->SetPlotCorner(this->OpacityFunctionItem.Get(), 1);

  this->OpacityControlPointsItem->SetEndPointsXMovable(false);
  this->OpacityControlPointsItem->SetEndPointsYMovable(true);
  this->OpacityControlPointsItem->SetEndPointsRemovable(false);

  vtkPen* pen = this->OpacityControlPointsItem->GetPen();
  pen->SetLineType(vtkPen::SOLID_LINE);
  pen->SetColor(0, 0, 0);
  pen->SetOpacity(255);
  pen->SetWidth(2.0);
  this->AddPlot(this->OpacityControlPointsItem.Get());
  this->SetPlotCorner(this->OpacityControlPointsItem.Get(), 1);
}

//-----------------------------------------------------------------------------
bool vtkChartHistogram::MouseDoubleClickEvent(const vtkContextMouseEvent &m)
{
  // Determine the location of the click, and emit something we can listen to!
  vtkPlotBar *histo = nullptr;
  if (this->GetNumberOfPlots() > 0)
  {
    histo = vtkPlotBar::SafeDownCast(this->GetPlot(0));
  }
  if (!histo)
  {
    return false;
  }
  this->CalculateUnscaledPlotTransform(histo->GetXAxis(), histo->GetYAxis(),
                                       this->Transform.Get());
  vtkVector2f pos;
  this->Transform->InverseTransformPoints(m.GetScenePos().GetData(), pos.GetData(),
                                          1);
  this->PositionX = pos.GetX();
  this->Marker->PositionX = this->PositionX;
  this->Marker->Modified();
  this->Scene->SetDirty(true);
  if (this->GetNumberOfPlots() == 1)
  {
    // Work around a bug in the charts - ensure corner is invalid for the plot.
    this->Marker->SetXAxis(nullptr);
    this->Marker->SetYAxis(nullptr);
    this->AddPlot(this->Marker.Get());
  }
  this->InvokeEvent(vtkCommand::CursorChangedEvent);
  return true;
}

//-----------------------------------------------------------------------------
void vtkChartHistogram::SetHistogramInputData(vtkTable* table,
                                              const char* xAxisColumn,
                                              const char* yAxisColumn)
{
  this->HistogramPlotBar->SetInputData(table, xAxisColumn, yAxisColumn);
}

//-----------------------------------------------------------------------------
void vtkChartHistogram::SetScalarVisibility(bool visible)
{
  this->HistogramPlotBar->SetScalarVisibility(visible);
}

//-----------------------------------------------------------------------------
void vtkChartHistogram::ScalarVisibilityOn()
{
  this->HistogramPlotBar->ScalarVisibilityOn();
}

//-----------------------------------------------------------------------------
void vtkChartHistogram::SetLookupTable(vtkScalarsToColors* lut)
{
  this->HistogramPlotBar->SetLookupTable(lut);
}

//-----------------------------------------------------------------------------
void vtkChartHistogram::SelectColorArray(const char* arrayName)
{
  this->HistogramPlotBar->SelectColorArray(arrayName);
}

//-----------------------------------------------------------------------------
void vtkChartHistogram::SetOpacityFunction(vtkPiecewiseFunction* opacityFunction)
{
  this->OpacityFunctionItem->SetPiecewiseFunction(opacityFunction);
  this->OpacityControlPointsItem->SetPiecewiseFunction(opacityFunction);
}
<|endoftext|>


<commit_before>#ifndef ESTIMATE_NORMALS_H
#define ESTIMATE_NORMALS_H

/// PROJECT
#include <csapex/model/node.h>
#include <csapex_point_cloud/point_cloud_message.h>
#include <csapex_point_cloud/normals_message.h>
#include <csapex/model/node_modifier.h>
#include <csapex/msg/io.h>
#include <csapex/utility/register_apex_plugin.h>

/// SYSTEM
#include <pcl/point_types.h>
#include <pcl/features/normal_3d.h>
#include <pcl/features/integral_image_normal.h>
#include <pcl/search/impl/kdtree.hpp>

using namespace csapex::connection_types;

namespace csapex
{

class EstimateNormals : public Node
{
public:
    EstimateNormals()
    {

    }

    virtual void setup(csapex::NodeModifier& node_modifier) override
    {
        input_ = node_modifier.addInput<PointCloudMessage>("cloud");
        output_ = node_modifier.addOutput<NormalsMessage>("normals");
    }

    void setupParameters(Parameterizable& parameters)
    {

    }

    virtual void process() override
    {
        PointCloudMessage::ConstPtr msg(msg::getMessage<PointCloudMessage>(input_));

        boost::apply_visitor (PointCloudMessage::Dispatch<EstimateNormals>(this, msg), msg->value);
    }

    template <class PointT>
    void inputCloud(typename pcl::PointCloud<PointT>::ConstPtr cloud)
    {
        NormalsMessage::Ptr out_msg(new NormalsMessage(cloud->header.frame_id, cloud->header.stamp));
        pcl::PointCloud<pcl::Normal>::Ptr msg(new pcl::PointCloud<pcl::Normal>);
        out_msg->value = msg;

        bool dense = cloud->width > 1 && cloud->height > 1;
        if(!dense) {
            pcl::NormalEstimation<PointT, pcl::Normal> ne;
            ne.setInputCloud (cloud);

            // Create an empty kdtree representation, and pass it to the normal estimation object.
            // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
            typename pcl::search::KdTree<PointT>::Ptr tree (new pcl::search::KdTree<PointT> ());
            ne.setSearchMethod (tree);

            // Use all neighbors in a sphere of radius 3cm
            ne.setRadiusSearch (0.03);

            // Compute the features
            ne.compute (*msg);

        }  else {
            pcl::IntegralImageNormalEstimation<PointT, pcl::Normal> ne;
            ne.setNormalEstimationMethod (ne.AVERAGE_3D_GRADIENT);
            ne.setMaxDepthChangeFactor(0.02f);
            ne.setNormalSmoothingSize(10.0f);
            ne.setInputCloud(cloud);
            ne.compute(*msg);
        }

        msg::publish(output_, out_msg);
    }

private:
    Input*  input_;
    Output* output_;

};

}

CSAPEX_REGISTER_CLASS(csapex::EstimateNormals, csapex::Node)

#endif // ESTIMATE_NORMALS_H
<commit_msg>parameters<commit_after>#ifndef ESTIMATE_NORMALS_H
#define ESTIMATE_NORMALS_H

/// PROJECT
#include <csapex/model/node.h>
#include <csapex_point_cloud/point_cloud_message.h>
#include <csapex_point_cloud/normals_message.h>
#include <csapex/model/node_modifier.h>
#include <csapex/msg/io.h>
#include <csapex/utility/register_apex_plugin.h>
#include <csapex/param/parameter_factory.h>

/// SYSTEM
#include <pcl/point_types.h>
#include <pcl/features/normal_3d.h>
#include <pcl/features/integral_image_normal.h>
#include <pcl/search/impl/kdtree.hpp>

using namespace csapex::connection_types;

namespace csapex
{

class EstimateNormals : public Node
{
public:
    EstimateNormals()
    {

    }

    virtual void setup(csapex::NodeModifier& node_modifier) override
    {
        input_ = node_modifier.addInput<PointCloudMessage>("cloud");
        output_ = node_modifier.addOutput<NormalsMessage>("normals");
    }

    void setupParameters(Parameterizable& parameters)
    {

        parameters.addParameter(param::ParameterFactory::declareRange("max_depth_change_factor",
                                                                      0.0, 0.5, 0.02, 0.001),
                                max_depth_change_factor);
        parameters.addParameter(param::ParameterFactory::declareRange("normal_smoothing_size",
                                                                      0.0, 50.0, 10.0, 0.1),
                                normal_smoothing_size);

        typedef pcl::IntegralImageNormalEstimation<pcl::PointXYZ, pcl::Normal> T;

        std::map<std::string, int> methods {
            {"COVARIANCE_MATRIX", T::COVARIANCE_MATRIX},
            {"AVERAGE_3D_GRADIENT", T::AVERAGE_3D_GRADIENT},
            {"AVERAGE_DEPTH_CHANGE", T::AVERAGE_DEPTH_CHANGE},
            {"SIMPLE_3D_GRADIENT", T::SIMPLE_3D_GRADIENT}
        };
        parameters.addParameter(param::ParameterFactory::declareParameterSet("method", methods,
                                                                             (int) T::AVERAGE_3D_GRADIENT),
                                method);
    }

    virtual void process() override
    {
        PointCloudMessage::ConstPtr msg(msg::getMessage<PointCloudMessage>(input_));

        boost::apply_visitor (PointCloudMessage::Dispatch<EstimateNormals>(this, msg), msg->value);
    }

    template <class PointT>
    void inputCloud(typename pcl::PointCloud<PointT>::ConstPtr cloud)
    {
        NormalsMessage::Ptr out_msg(new NormalsMessage(cloud->header.frame_id, cloud->header.stamp));
        pcl::PointCloud<pcl::Normal>::Ptr msg(new pcl::PointCloud<pcl::Normal>);
        out_msg->value = msg;

        bool dense = cloud->width > 1 && cloud->height > 1;
        if(!dense) {
            pcl::NormalEstimation<PointT, pcl::Normal> ne;
            ne.setInputCloud (cloud);

            // Create an empty kdtree representation, and pass it to the normal estimation object.
            // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
            typename pcl::search::KdTree<PointT>::Ptr tree (new pcl::search::KdTree<PointT> ());
            ne.setSearchMethod (tree);

            // Use all neighbors in a sphere of radius 3cm
            ne.setRadiusSearch (0.03);

            // Compute the features
            ne.compute (*msg);

        }  else {
            typedef pcl::IntegralImageNormalEstimation<PointT, pcl::Normal> N;
            N ne;
            ne.setNormalEstimationMethod (static_cast<typename N::NormalEstimationMethod>(method));
            ne.setMaxDepthChangeFactor(max_depth_change_factor);
            ne.setNormalSmoothingSize(normal_smoothing_size);
            ne.setInputCloud(cloud);
            ne.compute(*msg);
        }

        msg::publish(output_, out_msg);
    }

private:
    Input*  input_;
    Output* output_;

    int method;
    double max_depth_change_factor;
    double normal_smoothing_size;
};

}

CSAPEX_REGISTER_CLASS(csapex::EstimateNormals, csapex::Node)

#endif // ESTIMATE_NORMALS_H
<|endoftext|>


<commit_before>#include "acf_depth_channel.hpp"

#include <csapex/msg/io.h>
#include <csapex/msg/generic_vector_message.hpp>
#include <csapex/model/node_modifier.h>
#include <csapex/param/parameter_factory.h>
#include <csapex/utility/register_apex_plugin.h>

#include <csapex_opencv/cv_mat_message.h>
#include <csapex_opencv/roi_message.h>
#include <csapex_ml/features_message.h>

CSAPEX_REGISTER_CLASS(csapex::vision::ACFDepthChannel, csapex::Node)

using namespace csapex;
using namespace csapex::vision;
using namespace csapex::connection_types;

void ACFDepthChannel::setup(csapex::NodeModifier& node_modifier)
{
    in_image_      = node_modifier.addInput<CvMatMessage>("Depth Map");
    in_rois_       = node_modifier.addOptionalInput<GenericVectorMessage, RoiMessage>("ROIs");
    out_channels_  = node_modifier.addOutput<GenericVectorMessage, FeaturesMessage>("Channel Features");
    out_visualize_ = node_modifier.addOutput<CvMatMessage>("Visualize");
}

void ACFDepthChannel::setupParameters(csapex::Parameterizable& parameters)
{
    parameters.addParameter(param::ParameterFactory::declareRange("window/width",
                                                                  10, 1024, 64, 1),
                            std::bind(&ACFDepthChannel::updateWindow, this));
    parameters.addParameter(param::ParameterFactory::declareRange("window/height",
                                                                  10, 1024, 128, 1),
                            std::bind(&ACFDepthChannel::updateWindow, this));
    parameters.addParameter(param::ParameterFactory::declareBool("window/keep_ratio",
                                                                 false),
                            keep_ratio_);
    parameters.addParameter(param::ParameterFactory::declareBool("window/mirror",
                                                                 false),
                            mirror_);

    parameters.addParameter(param::ParameterFactory::declareRange("aggregate/block_size",
                                                                  1, 32, 4, 1),
                            block_size_);

    static const std::map<std::string, int> available_types = {
            { "binary", static_cast<int>(Type::BINARY) },
            { "ternary", static_cast<int>(Type::TERNARY) },
    };
    parameters.addParameter(param::ParameterFactory::declareParameterSet("channel/type",
                                                                        available_types,
                                                                        static_cast<int>(Type::BINARY)),
                            reinterpret_cast<int&>(type_));

    static const std::map<std::string, int> available_methods = {
            { "median", static_cast<int>(Method::MEDIAN) },
            { "mean", static_cast<int>(Method::MEAN) },
            { "histogram", static_cast<int>(Method::HISTOGRAM) },
    };
    parameters.addParameter(param::ParameterFactory::declareParameterSet("channel/method",
                                                                        available_methods,
                                                                        static_cast<int>(Method::MEDIAN)),
                            reinterpret_cast<int&>(method_));

    parameters.addParameter(param::ParameterFactory::declareRange("channel/threshold",
                                                                 0.0, 1000.0, 0.1, 0.01),
                           threshold_);

   parameters.addParameter(param::ParameterFactory::declareBool("channel/normalize",
                                                                false),
                           normalize_);
}

void ACFDepthChannel::updateWindow()
{
    int old_height = window_height_;

    window_width_  = readParameter<int>("window/width");
    window_height_ = readParameter<int>("window/height");
    if (window_ratio_ == 0.0)
        window_ratio_ = window_height_ / double(window_width_);

    if (keep_ratio_)
    {
        if (window_height_ != old_height)
        {
            window_width_ = window_height_ / window_ratio_;
            setParameter<int>("window/width", window_width_);
        } else
        {
            window_height_ = window_width_ * window_ratio_;
            setParameter<int>("window/height", window_height_);
        }
    }
}

std::vector<float> ACFDepthChannel::extractChannel(const cv::Mat& depth_map) const
{
    cv::Mat aggregated_depth_map;
    cv::resize(depth_map, aggregated_depth_map, cv::Size(depth_map.cols / block_size_, depth_map.rows / block_size_));
    const cv::Mat valid_pixel_mask = aggregated_depth_map > 0;

    double min_value;
    double max_value;
    cv::minMaxLoc(aggregated_depth_map, &min_value, &max_value);

    float center = 0.0f;
    switch (method_)
    {
        case Method::HISTOGRAM:
        {
            const static float BIN_SIZE = 0.25f;
            static const int channels[] = { 0 };
            const int bins[] = { int((max_value - min_value) / BIN_SIZE) };
            const float value_range[] = { float(min_value), float(max_value) + std::numeric_limits<float>::epsilon() };
            const float* ranges[] = { value_range };

            cv::Mat hist;
            cv::calcHist(&aggregated_depth_map, 1, channels, valid_pixel_mask, hist, 1, bins, ranges, true);

            cv::Point max;
            cv::minMaxLoc(hist, nullptr, nullptr, nullptr, &max);

            center = min_value + (max.y + 0.5f) * BIN_SIZE;
            break;
        }
        case Method::MEDIAN:
        {
            cv::Mat values = aggregated_depth_map.reshape(0, 1).clone();
            const int invalid_pixel_count = values.cols - cv::countNonZero(valid_pixel_mask);

            const auto middle = invalid_pixel_count + (values.cols - invalid_pixel_count) / 2;
            std::nth_element(values.begin<float>(), values.begin<float>() + middle, values.end<float>());
            center = values.at<float>(0, middle);
            break;
        }
        case Method::MEAN:
            center = cv::mean(aggregated_depth_map, valid_pixel_mask)[0];
            break;
    }

    std::vector<float> feature;
    feature.reserve(aggregated_depth_map.rows * aggregated_depth_map.cols);

    switch (type_)
    {
        case Type::TERNARY:
            std::transform(aggregated_depth_map.begin<float>(), aggregated_depth_map.end<float>(),
                           std::back_inserter(feature),
                           [&](float value)
                           {
                               if (normalize_)
                               {
                                   const float delta = value - center;
                                   if (delta > threshold_)
                                       return delta / float(max_value - (center + threshold_));
                                   else if (delta < -threshold_)
                                       return delta / float(center - threshold_ - min_value);
                                   else
                                       return 0.f;
                               }
                               else
                               {
                                   if (value > center + threshold_)
                                       return 1.f;
                                   else if (value < center - threshold_)
                                       return -1.f;
                                   else
                                       return 0.f;
                               }
                           });
            break;
        case Type::BINARY:
            std::transform(aggregated_depth_map.begin<float>(), aggregated_depth_map.end<float>(),
                           std::back_inserter(feature),
                           [&](float value)
                           {
                               if (normalize_)
                               {
                                   const float delta = value - center;
                                   if (delta > threshold_)
                                       return delta / float(max_value - (center + threshold_));
                                   else if (delta < -threshold_)
                                       return -delta / float(center - threshold_ - min_value);
                                   else
                                       return 0.f;
                               }
                               else
                               {
                                   if (std::abs(value - center) > threshold_)
                                       return 1.f;
                                   else
                                       return 0.f;
                               }
                           });
            break;
    }

    return std::move(feature);
}

void ACFDepthChannel::process()
{
    CvMatMessage::ConstPtr in_image = msg::getMessage<CvMatMessage>(in_image_);
    const cv::Mat& image = in_image->value;

    std::shared_ptr<std::vector<RoiMessage> const> in_rois;
    if (msg::hasMessage(in_rois_))
        in_rois = msg::getMessage<GenericVectorMessage, RoiMessage>(in_rois_);

    if (image.channels() != 1 || image.type() != CV_32F)
        throw std::runtime_error("Only 1 channel float images (depth maps) are supported");

    CvMatMessage::Ptr out_visualize;
    if (msg::isConnected(out_visualize_))
    {
        out_visualize = std::make_shared<CvMatMessage>(enc::bgr, in_image->stamp_micro_seconds);
        out_visualize->frame_id = in_image->frame_id;
        out_visualize->value = cv::Mat(image.rows, image.cols, CV_8UC3, cv::Scalar(0, 0, 0));
    }

    auto out_features = std::make_shared<std::vector<FeaturesMessage>>();

    const auto process_roi = [&](const Roi& roi)
    {
        const cv::Rect roi_region = roi.rect() & cv::Rect(0, 0, image.cols, image.rows);

        FeaturesMessage feature(in_image->stamp_micro_seconds);
        feature.classification = roi.classification();

        cv::Mat image_region;
        cv::resize(cv::Mat(image, roi_region), image_region, cv::Size(window_width_, window_height_));

        feature.value = extractChannel(image_region);
        out_features->push_back(feature);

        if (out_visualize)
        {
            const float scale_x = float(image_region.cols / block_size_) / roi_region.width;
            const float scale_y = float(image_region.rows / block_size_) / roi_region.height;

            for (int dy = 0; dy < roi_region.height; ++dy)
                for (int dx = 0; dx < roi_region.width; ++dx)
                {
                    const int ldx = dx * scale_x;
                    const int ldy = dy * scale_y;
                    const int step = window_width_ / block_size_;

                    const float value = feature.value[ldx + step * ldy];
                    cv::Vec3b& dst = out_visualize->value.at<cv::Vec3b>(roi_region.y + dy, roi_region.x + dx);

                    if (value == 0)
                         dst = cv::Vec3b(0, 255, 0);
                    else if (value < 0)
                        dst = cv::Vec3b(0, 0, 255) * std::abs(value);
                    else if (value > 0)
                        dst = cv::Vec3b(255, 0, 0) * std::abs(value);
                }
        }

        if (mirror_)
        {
            cv::flip(image_region, image_region, 1);

            feature.value = extractChannel(image_region);
            out_features->push_back(std::move(feature));
        }
    };

    if (in_rois)
    {
        for (const RoiMessage& roi : *in_rois)
            process_roi(roi.value);
    }
    else
        process_roi(csapex::Roi(0, 0, image.cols, image.rows));

    msg::publish<GenericVectorMessage, FeaturesMessage>(out_channels_, out_features);
    if (out_visualize)
        msg::publish(out_visualize_, out_visualize);
}
<commit_msg>vision: ACFDepthChannel - skip invalid points for all methods<commit_after>#include "acf_depth_channel.hpp"

#include <csapex/msg/io.h>
#include <csapex/msg/generic_vector_message.hpp>
#include <csapex/model/node_modifier.h>
#include <csapex/param/parameter_factory.h>
#include <csapex/utility/register_apex_plugin.h>

#include <csapex_opencv/cv_mat_message.h>
#include <csapex_opencv/roi_message.h>
#include <csapex_ml/features_message.h>

CSAPEX_REGISTER_CLASS(csapex::vision::ACFDepthChannel, csapex::Node)

using namespace csapex;
using namespace csapex::vision;
using namespace csapex::connection_types;

void ACFDepthChannel::setup(csapex::NodeModifier& node_modifier)
{
    in_image_      = node_modifier.addInput<CvMatMessage>("Depth Map");
    in_rois_       = node_modifier.addOptionalInput<GenericVectorMessage, RoiMessage>("ROIs");
    out_channels_  = node_modifier.addOutput<GenericVectorMessage, FeaturesMessage>("Channel Features");
    out_visualize_ = node_modifier.addOutput<CvMatMessage>("Visualize");
}

void ACFDepthChannel::setupParameters(csapex::Parameterizable& parameters)
{
    parameters.addParameter(param::ParameterFactory::declareRange("window/width",
                                                                  10, 1024, 64, 1),
                            std::bind(&ACFDepthChannel::updateWindow, this));
    parameters.addParameter(param::ParameterFactory::declareRange("window/height",
                                                                  10, 1024, 128, 1),
                            std::bind(&ACFDepthChannel::updateWindow, this));
    parameters.addParameter(param::ParameterFactory::declareBool("window/keep_ratio",
                                                                 false),
                            keep_ratio_);
    parameters.addParameter(param::ParameterFactory::declareBool("window/mirror",
                                                                 false),
                            mirror_);

    parameters.addParameter(param::ParameterFactory::declareRange("aggregate/block_size",
                                                                  1, 32, 4, 1),
                            block_size_);

    static const std::map<std::string, int> available_types = {
            { "binary", static_cast<int>(Type::BINARY) },
            { "ternary", static_cast<int>(Type::TERNARY) },
    };
    parameters.addParameter(param::ParameterFactory::declareParameterSet("channel/type",
                                                                        available_types,
                                                                        static_cast<int>(Type::BINARY)),
                            reinterpret_cast<int&>(type_));

    static const std::map<std::string, int> available_methods = {
            { "median", static_cast<int>(Method::MEDIAN) },
            { "mean", static_cast<int>(Method::MEAN) },
            { "histogram", static_cast<int>(Method::HISTOGRAM) },
    };
    parameters.addParameter(param::ParameterFactory::declareParameterSet("channel/method",
                                                                        available_methods,
                                                                        static_cast<int>(Method::MEDIAN)),
                            reinterpret_cast<int&>(method_));

    parameters.addParameter(param::ParameterFactory::declareRange("channel/threshold",
                                                                 0.0, 1000.0, 0.1, 0.01),
                           threshold_);

   parameters.addParameter(param::ParameterFactory::declareBool("channel/normalize",
                                                                false),
                           normalize_);
}

void ACFDepthChannel::updateWindow()
{
    int old_height = window_height_;

    window_width_  = readParameter<int>("window/width");
    window_height_ = readParameter<int>("window/height");
    if (window_ratio_ == 0.0)
        window_ratio_ = window_height_ / double(window_width_);

    if (keep_ratio_)
    {
        if (window_height_ != old_height)
        {
            window_width_ = window_height_ / window_ratio_;
            setParameter<int>("window/width", window_width_);
        } else
        {
            window_height_ = window_width_ * window_ratio_;
            setParameter<int>("window/height", window_height_);
        }
    }
}

std::vector<float> ACFDepthChannel::extractChannel(const cv::Mat& depth_map) const
{
    cv::Mat aggregated_depth_map;
    cv::resize(depth_map, aggregated_depth_map, cv::Size(depth_map.cols / block_size_, depth_map.rows / block_size_));
    const cv::Mat valid_pixel_mask = aggregated_depth_map > 0;

    double min_value;
    double max_value;
    cv::minMaxLoc(aggregated_depth_map, &min_value, &max_value);

    float center = 0.0f;
    switch (method_)
    {
        case Method::HISTOGRAM:
        {
            const static float BIN_SIZE = 0.25f;
            static const int channels[] = { 0 };
            const int bins[] = { int((max_value - min_value) / BIN_SIZE) };
            const float value_range[] = { float(min_value), float(max_value) + std::numeric_limits<float>::epsilon() };
            const float* ranges[] = { value_range };

            cv::Mat hist;
            cv::calcHist(&aggregated_depth_map, 1, channels, valid_pixel_mask, hist, 1, bins, ranges, true);

            cv::Point max;
            cv::minMaxLoc(hist, nullptr, nullptr, nullptr, &max);

            center = min_value + (max.y + 0.5f) * BIN_SIZE;
            break;
        }
        case Method::MEDIAN:
        {
            cv::Mat values = aggregated_depth_map.reshape(0, 1).clone();
            const int invalid_pixel_count = values.cols - cv::countNonZero(valid_pixel_mask);

            // invalid points are <0 and thus will be at the beginning of the (partial) sort, so we have to skip them
            const auto middle = invalid_pixel_count + (values.cols - invalid_pixel_count) / 2;
            std::nth_element(values.begin<float>(), values.begin<float>() + middle, values.end<float>());
            center = values.at<float>(0, middle);
            break;
        }
        case Method::MEAN:
            center = cv::mean(aggregated_depth_map, valid_pixel_mask)[0];
            break;
    }

    std::vector<float> feature;
    feature.reserve(aggregated_depth_map.rows * aggregated_depth_map.cols);

    switch (type_)
    {
        case Type::TERNARY:
            std::transform(aggregated_depth_map.begin<float>(), aggregated_depth_map.end<float>(),
                           std::back_inserter(feature),
                           [&](float value)
                           {
                               if (normalize_)
                               {
                                   const float delta = value - center;
                                   if (delta > threshold_)
                                       return delta / float(max_value - (center + threshold_));
                                   else if (delta < -threshold_)
                                       return delta / float(center - threshold_ - min_value);
                                   else
                                       return 0.f;
                               }
                               else
                               {
                                   if (value > center + threshold_)
                                       return 1.f;
                                   else if (value < center - threshold_)
                                       return -1.f;
                                   else
                                       return 0.f;
                               }
                           });
            break;
        case Type::BINARY:
            std::transform(aggregated_depth_map.begin<float>(), aggregated_depth_map.end<float>(),
                           std::back_inserter(feature),
                           [&](float value)
                           {
                               if (normalize_)
                               {
                                   const float delta = value - center;
                                   if (delta > threshold_)
                                       return delta / float(max_value - (center + threshold_));
                                   else if (delta < -threshold_)
                                       return -delta / float(center - threshold_ - min_value);
                                   else
                                       return 0.f;
                               }
                               else
                               {
                                   if (std::abs(value - center) > threshold_)
                                       return 1.f;
                                   else
                                       return 0.f;
                               }
                           });
            break;
    }

    return std::move(feature);
}

void ACFDepthChannel::process()
{
    CvMatMessage::ConstPtr in_image = msg::getMessage<CvMatMessage>(in_image_);
    const cv::Mat& image = in_image->value;

    std::shared_ptr<std::vector<RoiMessage> const> in_rois;
    if (msg::hasMessage(in_rois_))
        in_rois = msg::getMessage<GenericVectorMessage, RoiMessage>(in_rois_);

    if (image.channels() != 1 || image.type() != CV_32F)
        throw std::runtime_error("Only 1 channel float images (depth maps) are supported");

    CvMatMessage::Ptr out_visualize;
    if (msg::isConnected(out_visualize_))
    {
        out_visualize = std::make_shared<CvMatMessage>(enc::bgr, in_image->stamp_micro_seconds);
        out_visualize->frame_id = in_image->frame_id;
        out_visualize->value = cv::Mat(image.rows, image.cols, CV_8UC3, cv::Scalar(0, 0, 0));
    }

    auto out_features = std::make_shared<std::vector<FeaturesMessage>>();

    const auto process_roi = [&](const Roi& roi)
    {
        const cv::Rect roi_region = roi.rect() & cv::Rect(0, 0, image.cols, image.rows);

        FeaturesMessage feature(in_image->stamp_micro_seconds);
        feature.classification = roi.classification();

        cv::Mat image_region;
        cv::resize(cv::Mat(image, roi_region), image_region, cv::Size(window_width_, window_height_));

        feature.value = extractChannel(image_region);
        out_features->push_back(feature);

        if (out_visualize)
        {
            const float scale_x = float(image_region.cols / block_size_) / roi_region.width;
            const float scale_y = float(image_region.rows / block_size_) / roi_region.height;

            for (int dy = 0; dy < roi_region.height; ++dy)
                for (int dx = 0; dx < roi_region.width; ++dx)
                {
                    const int ldx = dx * scale_x;
                    const int ldy = dy * scale_y;
                    const int step = window_width_ / block_size_;

                    const float value = feature.value[ldx + step * ldy];
                    cv::Vec3b& dst = out_visualize->value.at<cv::Vec3b>(roi_region.y + dy, roi_region.x + dx);

                    if (value == 0)
                         dst = cv::Vec3b(0, 255, 0);
                    else if (value < 0)
                        dst = cv::Vec3b(0, 0, 255) * std::abs(value);
                    else if (value > 0)
                        dst = cv::Vec3b(255, 0, 0) * std::abs(value);
                }
        }

        if (mirror_)
        {
            cv::flip(image_region, image_region, 1);

            feature.value = extractChannel(image_region);
            out_features->push_back(std::move(feature));
        }
    };

    if (in_rois)
    {
        for (const RoiMessage& roi : *in_rois)
            process_roi(roi.value);
    }
    else
        process_roi(csapex::Roi(0, 0, image.cols, image.rows));

    msg::publish<GenericVectorMessage, FeaturesMessage>(out_channels_, out_features);
    if (out_visualize)
        msg::publish(out_visualize_, out_visualize);
}
<|endoftext|>


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

#include <chrono>
#include <fstream>
#include <iostream>
#include <random>
#include <string>
#include <vector>

#include "src/ext/cpputil/include/command_line/command_line.h"
#include "src/ext/cpputil/include/serialize/span_reader.h"
#include "src/ext/cpputil/include/signal/debug_handler.h"
#include "src/ext/cpputil/include/system/terminal.h"

#include "src/state/cpu_states.h"
#include "src/stategen/stategen.h"
#include "tools/args/target.h"
#include "tools/gadgets/sandbox.h"
#include "tools/gadgets/target.h"
#include "tools/io/tunit.h"

using namespace cpputil;
using namespace std;
using namespace stoke;

auto& io_opt = Heading::create("I/O options:");
auto& bin = ValueArg<string>::create("bin")
            .usage("<path/to/bin>")
            .description("Executable binary containing function to generate testcases for")
            .default_val("./a.out");
auto& args = ValueArg<string>::create("args")
             .usage("<arg1 arg2 ... argn>")
             .description("Optional command line arguments to pass to binary")
             .default_val("");
auto& out = ValueArg<string>::create("o")
            .alternate("out")
            .usage("<path/to/file.tc>")
            .description("File to write testcases to (defaults to console if unspecified)")
            .default_val("");

auto& common_opt = Heading::create("Common options:");
auto& max_tc = ValueArg<size_t>::create("max_testcases")
               .usage("<int>")
               .description("The maximum number of testcases to generate")
               .default_val(16);

auto& trace_opt = Heading::create("Trace options:");
auto& fxn = ValueArg<string>::create("fxn")
            .usage("<string>")
            .description("Function to generate testcases for")
            .default_val("main");
auto& begin_line = ValueArg<size_t>::create("begin_line")
                   .usage("<int>")
                   .description("The line number to begin recording from")
                   .default_val(1);
auto& end_lines = ValueArg<vector<size_t>>::create("end_lines")
                  .usage("{ 0 1 ... 9 }")
                  .description("Line number to end recording on; recording always stops on returns")
                  .default_val({});
auto& max_stack = ValueArg<uint64_t>::create("max_stack")
                  .usage("<bytes>")
                  .description("The maximum number of bytes to assume could be stack")
                  .default_val(1024);

auto& autogen_opt = Heading::create("Autogen options:");
auto& max_attempts = ValueArg<uint64_t>::create("max_attempts")
                     .usage("<int>")
                     .description("The maximum number of attempts to make at generating a testcase")
                     .default_val(16);
auto& max_memory = ValueArg<uint64_t>::create("max_memory")
                   .usage("<bytes>")
                   .description("The maximum number of bytes to allocate to stack or heap")
                   .default_val(1024);
auto& stack_size = ValueArg<size_t>::create("stack_size")
                     .usage("<int>")
                     .description("The minimum stack size available to the testcase")
                     .default_val(16);

auto& conv_opt = Heading::create("File conversion options:");
auto& compress = FlagArg::create("compress")
                 .description("Convert testcase file from text to binary");
auto& decompress = FlagArg::create("decompress")
                   .description("Convert testcase file from binary to text");
auto& in = ValueArg<string>::create("in")
           .alternate("i")
           .usage("<path/to/file.tc>")
           .description("Path to testcases file")
           .default_val("in.tc");

int auto_gen() {
  TargetGadget target;
  SandboxGadget sb({});

  StateGen sg(&sb, stack_size.value());
  sg.set_max_attempts(max_attempts.value())
  .set_max_memory(max_stack.value());

  CpuStates tcs;
  for (size_t i = 0, ie = max_tc.value(); i < ie; ++i) {
    CpuState tc;
    if (sg.get(tc, target)) {
      tcs.push_back(tc);
    }
  }

  if (tcs.empty()) {
    cout << "Unable to generate testcases!" << endl;
    return 1;
  }

  if (out.value() != "") {
    ofstream ofs(out.value());
    tcs.write_text(ofs);
  } else {
    tcs.write_text(cout);
    cout << endl;
  }

  return 0;
}

int trace(const string& argv0) {
  string here = argv0;
  here = here.substr(0, here.find_last_of("/") + 1);

  const string pin_path = here + "../src/ext/pin-2.13-62732-gcc.4.4.7-linux/";
  const string so_path = pin_path + "source/tools/stoke/obj-intel64/";

  Terminal term;
  term << pin_path << "pin -injection child -t " << so_path << "testcase.so ";

  term << "-f " << fxn.value() << " ";
  if (out.value() != "") {
    term << "-o " << out.value() << " ";
  }
  term << "-x " << max_stack.value() << " ";
  term << "-n " << max_tc.value() << " ";
  term << "-b " << begin_line.value() << " ";
  term << "-e \" ";
  for (auto e : end_lines.value()) {
    term << e << " ";
  }
  term << "\" ";

  term << " -- " << bin.value() << " " << args.value() << endl;

  return 0;
}

int do_compress() {
  ifstream ifs(in.value());
  if (!ifs.is_open()) {
    cout << "Unable to open input file: " << in.value() << "!" << endl;
    return 1;
  }

  CpuStates cs;
  cs.read_text(ifs);
  if (ifs.fail()) {
    cout << "Unable to read input file: " << in.value() << "!" << endl;
    return 1;
  }

  if (out.value() != "") {
    ofstream ofs(out.value());
    cs.write_bin(ofs);
  } else {
    cs.write_bin(cout);
    cout << endl;
  }

  return 0;
}

int do_decompress() {
  ifstream ifs(in.value());
  if (!ifs.is_open()) {
    cout << "Unable to open input file: " << in.value() << "!" << endl;
    return 1;
  }

  CpuStates cs;
  cs.read_bin(ifs);
  if (ifs.fail()) {
    cout << "Unable to read input file: " << in.value() << "!" << endl;
    return 1;
  }

  if (out.value() != "") {
    ofstream ofs(out.value());
    cs.write_text(ofs);
  } else {
    cs.write_text(cout);
    cout << endl;
  }

  return 0;
}

int main(int argc, char** argv) {
  CommandLineConfig::strict_with_convenience(argc, argv);
  DebugHandler::install_sigsegv();
  DebugHandler::install_sigill();

  if (compress.value()) {
    return do_compress();
  } else if (decompress.value()) {
    return do_decompress();
  } else if (target_arg.value().name != "anon") {
    return auto_gen();
  } else {
    return trace(argv[0]);
  }
}

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

#include <chrono>
#include <fstream>
#include <iostream>
#include <random>
#include <string>
#include <vector>

#include "src/ext/cpputil/include/command_line/command_line.h"
#include "src/ext/cpputil/include/serialize/span_reader.h"
#include "src/ext/cpputil/include/signal/debug_handler.h"
#include "src/ext/cpputil/include/system/terminal.h"

#include "src/state/cpu_states.h"
#include "src/stategen/stategen.h"
#include "tools/args/target.h"
#include "tools/gadgets/sandbox.h"
#include "tools/gadgets/target.h"
#include "tools/io/tunit.h"

using namespace cpputil;
using namespace std;
using namespace stoke;

auto& io_opt = Heading::create("I/O options:");
auto& bin = ValueArg<string>::create("bin")
            .usage("<path/to/bin>")
            .description("Executable binary containing function to generate testcases for")
            .default_val("./a.out");
auto& args = ValueArg<string>::create("args")
             .usage("<arg1 arg2 ... argn>")
             .description("Optional command line arguments to pass to binary")
             .default_val("");
auto& out = ValueArg<string>::create("o")
            .alternate("out")
            .usage("<path/to/file.tc>")
            .description("File to write testcases to (defaults to console if unspecified)")
            .default_val("");

auto& common_opt = Heading::create("Common options:");
auto& max_tc = ValueArg<size_t>::create("max_testcases")
               .usage("<int>")
               .description("The maximum number of testcases to generate")
               .default_val(16);

auto& trace_opt = Heading::create("Trace options:");
auto& fxn = ValueArg<string>::create("fxn")
            .usage("<string>")
            .description("Function to generate testcases for")
            .default_val("main");
auto& begin_line = ValueArg<size_t>::create("begin_line")
                   .usage("<int>")
                   .description("The line number to begin recording from")
                   .default_val(1);
auto& end_lines = ValueArg<vector<size_t>>::create("end_lines")
                  .usage("{ 0 1 ... 9 }")
                  .description("Line number to end recording on; recording always stops on returns")
                  .default_val({});
auto& max_stack = ValueArg<uint64_t>::create("max_stack")
                  .usage("<bytes>")
                  .description("The maximum number of bytes to assume could be stack")
                  .default_val(1024);

auto& autogen_opt = Heading::create("Autogen options:");
auto& max_attempts = ValueArg<uint64_t>::create("max_attempts")
                     .usage("<int>")
                     .description("The maximum number of attempts to make at generating a testcase")
                     .default_val(16);
auto& max_memory = ValueArg<uint64_t>::create("max_memory")
                   .usage("<bytes>")
                   .description("The maximum number of bytes to allocate to stack or heap")
                   .default_val(1024);
auto& stack_size = ValueArg<size_t>::create("stack_size")
                   .usage("<int>")
                   .description("The minimum stack size available to the testcase")
                   .default_val(16);

auto& conv_opt = Heading::create("File conversion options:");
auto& compress = FlagArg::create("compress")
                 .description("Convert testcase file from text to binary");
auto& decompress = FlagArg::create("decompress")
                   .description("Convert testcase file from binary to text");
auto& in = ValueArg<string>::create("in")
           .alternate("i")
           .usage("<path/to/file.tc>")
           .description("Path to testcases file")
           .default_val("in.tc");

int auto_gen() {
  TargetGadget target;
  SandboxGadget sb({});

  StateGen sg(&sb, stack_size.value());
  sg.set_max_attempts(max_attempts.value())
  .set_max_memory(max_stack.value());

  CpuStates tcs;
  for (size_t i = 0, ie = max_tc.value(); i < ie; ++i) {
    CpuState tc;
    if (sg.get(tc, target)) {
      tcs.push_back(tc);
    }
  }

  if (tcs.empty()) {
    cout << "Unable to generate testcases!" << endl;
    return 1;
  }

  if (out.value() != "") {
    ofstream ofs(out.value());
    tcs.write_text(ofs);
  } else {
    tcs.write_text(cout);
    cout << endl;
  }

  return 0;
}

int trace(const string& argv0) {
  string here = argv0;
  here = here.substr(0, here.find_last_of("/") + 1);

  const string pin_path = here + "../src/ext/pin-2.13-62732-gcc.4.4.7-linux/";
  const string so_path = pin_path + "source/tools/stoke/obj-intel64/";

  Terminal term;
  term << pin_path << "pin -injection child -t " << so_path << "testcase.so ";

  term << "-f " << fxn.value() << " ";
  if (out.value() != "") {
    term << "-o " << out.value() << " ";
  }
  term << "-x " << max_stack.value() << " ";
  term << "-n " << max_tc.value() << " ";
  term << "-b " << begin_line.value() << " ";
  term << "-e \" ";
  for (auto e : end_lines.value()) {
    term << e << " ";
  }
  term << "\" ";

  term << " -- " << bin.value() << " " << args.value() << endl;

  return 0;
}

int do_compress() {
  ifstream ifs(in.value());
  if (!ifs.is_open()) {
    cout << "Unable to open input file: " << in.value() << "!" << endl;
    return 1;
  }

  CpuStates cs;
  cs.read_text(ifs);
  if (ifs.fail()) {
    cout << "Unable to read input file: " << in.value() << "!" << endl;
    return 1;
  }

  if (out.value() != "") {
    ofstream ofs(out.value());
    cs.write_bin(ofs);
  } else {
    cs.write_bin(cout);
    cout << endl;
  }

  return 0;
}

int do_decompress() {
  ifstream ifs(in.value());
  if (!ifs.is_open()) {
    cout << "Unable to open input file: " << in.value() << "!" << endl;
    return 1;
  }

  CpuStates cs;
  cs.read_bin(ifs);
  if (ifs.fail()) {
    cout << "Unable to read input file: " << in.value() << "!" << endl;
    return 1;
  }

  if (out.value() != "") {
    ofstream ofs(out.value());
    cs.write_text(ofs);
  } else {
    cs.write_text(cout);
    cout << endl;
  }

  return 0;
}

int main(int argc, char** argv) {
  CommandLineConfig::strict_with_convenience(argc, argv);
  DebugHandler::install_sigsegv();
  DebugHandler::install_sigill();

  if (compress.value()) {
    return do_compress();
  } else if (decompress.value()) {
    return do_decompress();
  } else if (target_arg.value().name != "anon") {
    return auto_gen();
  } else {
    return trace(argv[0]);
  }
}

<|endoftext|>


<commit_before>//===- GenerateCode.cpp - Functions for generating executable files  ------===//
//
// This file contains functions for generating executable files once linking
// has finished.  This includes generating a shell script to run the JIT or
// a native executable derived from the bytecode.
//
//===----------------------------------------------------------------------===//

#include "gccld.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/Linker.h"
#include "Support/SystemUtils.h"

//
// Function: GenerateBytecode ()
//
// Description:
//  This function generates a bytecode file from the specified module.
//
// Inputs:
//  M           - The module for which bytecode should be generated.
//  Strip       - Flags whether symbols should be stripped from the output.
//  Internalize - Flags whether all symbols should be marked internal.
//  Out         - Pointer to file stream to which to write the output.
//
// Outputs:
//  None.
//
// Return value:
//  0 - No error.
//  1 - Error.
//
int
GenerateBytecode (Module *M, bool Strip, bool Internalize, std::ostream *Out) {
  // In addition to just linking the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  PassManager Passes;

  // Add an appropriate TargetData instance for this module...
  Passes.add(new TargetData("gccld", M));

  // Linking modules together can lead to duplicated global constants, only keep
  // one copy of each constant...
  Passes.add(createConstantMergePass());

  // If the -s command line option was specified, strip the symbols out of the
  // resulting program to make it smaller.  -s is a GCC option that we are
  // supporting.
  if (Strip)
    Passes.add(createSymbolStrippingPass());

  // Often if the programmer does not specify proper prototypes for the
  // functions they are calling, they end up calling a vararg version of the
  // function that does not get a body filled in (the real function has typed
  // arguments).  This pass merges the two functions.
  Passes.add(createFunctionResolvingPass());

  if (Internalize) {
    // Now that composite has been compiled, scan through the module, looking
    // for a main function.  If main is defined, mark all other functions
    // internal.
    Passes.add(createInternalizePass());
  }

  // Remove unused arguments from functions...
  Passes.add(createDeadArgEliminationPass());

  // The FuncResolve pass may leave cruft around if functions were prototyped
  // differently than they were defined.  Remove this cruft.
  Passes.add(createInstructionCombiningPass());

  // Delete basic blocks, which optimization passes may have killed...
  Passes.add(createCFGSimplificationPass());

  // Now that we have optimized the program, discard unreachable functions...
  Passes.add(createGlobalDCEPass());

  // Add the pass that writes bytecode to the output file...
  Passes.add(new WriteBytecodePass(Out));

  // Run our queue of passes all at once now, efficiently.
  Passes.run(*M);

  return 0;
}

//
// Function: GenerateAssembly ()
//
// Description:
//  This function generates a native assembly language source file from the
//  specified bytecode file.
//
// Inputs:
//  InputFilename  - The name of the output bytecode file.
//  OutputFilename - The name of the file to generate.
//  llc            - The pathname to use for LLC.
//  envp           - The environment to use when running LLC.
//
// Outputs:
//  None.
//
// Return value:
//  0 - Success
//  1 - Failure
//
int
GenerateAssembly(const std::string &OutputFilename,
                 const std::string &InputFilename,
                 const std::string &llc,
                 char ** const envp)
{
  // Run LLC to convert the bytecode file into assembly code.
  const char *cmd[8];

  cmd[0] = llc.c_str();
  cmd[1] = "-f";
  cmd[2] = "-o";
  cmd[3] = OutputFilename.c_str();
  cmd[4] = InputFilename.c_str();
  cmd[5] = NULL;

  return ExecWait(cmd, envp);
}

//
// Function: GenerateNative ()
//
// Description:
//  This function generates a native assembly language source file from the
//  specified assembly source file.
//
// Inputs:
//  InputFilename  - The name of the output bytecode file.
//  OutputFilename - The name of the file to generate.
//  Libraries      - The list of libraries with which to link.
//  LibPaths       - The list of directories in which to find libraries.
//  gcc            - The pathname to use for GGC.
//  envp           - A copy of the process's current environment.
//
// Outputs:
//  None.
//
// Return value:
//  0 - Success
//  1 - Failure
//
int
GenerateNative(const std::string &OutputFilename,
               const std::string &InputFilename,
               const std::vector<std::string> &Libraries,
               const std::vector<std::string> &LibPaths,
               const std::string &gcc,
               char ** const envp) {
  // Remove these environment variables from the environment of the
  // programs that we will execute.  It appears that GCC sets these
  // environment variables so that the programs it uses can configure
  // themselves identically.
  //
  // However, when we invoke GCC below, we want it to use its normal
  // configuration.  Hence, we must sanitize its environment.
  char ** clean_env = CopyEnv(envp);
  if (clean_env == NULL)
    return 1;
  RemoveEnv("LIBRARY_PATH", clean_env);
  RemoveEnv("COLLECT_GCC_OPTIONS", clean_env);
  RemoveEnv("GCC_EXEC_PREFIX", clean_env);
  RemoveEnv("COMPILER_PATH", clean_env);
  RemoveEnv("COLLECT_GCC", clean_env);

  std::vector<const char *> cmd;

  // Run GCC to assemble and link the program into native code.
  //
  // Note:
  //  We can't just assemble and link the file with the system assembler
  //  and linker because we don't know where to put the _start symbol.
  //  GCC mysteriously knows how to do it.
  cmd.push_back(gcc.c_str());
  cmd.push_back("-o");
  cmd.push_back(OutputFilename.c_str());
  cmd.push_back(InputFilename.c_str());

  // Adding the library paths creates a problem for native generation.  If we
  // include the search paths from llvmgcc, then we'll be telling normal gcc
  // to look inside of llvmgcc's library directories for libraries.  This is
  // bad because those libraries hold only bytecode files (not native object
  // files).  In the end, we attempt to link the bytecode libgcc into a native
  // program.
#if 0
  // Add in the library path options.
  for (unsigned index=0; index < LibPaths.size(); index++) {
    cmd.push_back("-L");
    cmd.push_back(LibPaths[index].c_str());
  }
#endif

  // Add in the libraries to link.
  std::vector<std::string> Libs(Libraries);
  for (unsigned index = 0; index < Libs.size(); index++) {
    Libs[index] = "-l" + Libs[index];
    cmd.push_back(Libs[index].c_str());
  }
  cmd.push_back(NULL);

  // Run the compiler to assembly and link together the program.
  return ExecWait(&(cmd[0]), clean_env);
}
<commit_msg>Doxygen-ified function comments.<commit_after>//===- GenerateCode.cpp - Functions for generating executable files  ------===//
//
// This file contains functions for generating executable files once linking
// has finished.  This includes generating a shell script to run the JIT or
// a native executable derived from the bytecode.
//
//===----------------------------------------------------------------------===//

#include "gccld.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/Linker.h"
#include "Support/SystemUtils.h"

/// GenerateBytecode - generates a bytecode file from the specified module.
///
/// Inputs:
///  M           - The module for which bytecode should be generated.
///  Strip       - Flags whether symbols should be stripped from the output.
///  Internalize - Flags whether all symbols should be marked internal.
///  Out         - Pointer to file stream to which to write the output.
///
/// Outputs:
///  None.
///
/// Returns non-zero value on error.
///
int
GenerateBytecode (Module *M, bool Strip, bool Internalize, std::ostream *Out) {
  // In addition to just linking the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  PassManager Passes;

  // Add an appropriate TargetData instance for this module...
  Passes.add(new TargetData("gccld", M));

  // Linking modules together can lead to duplicated global constants, only keep
  // one copy of each constant...
  Passes.add(createConstantMergePass());

  // If the -s command line option was specified, strip the symbols out of the
  // resulting program to make it smaller.  -s is a GCC option that we are
  // supporting.
  if (Strip)
    Passes.add(createSymbolStrippingPass());

  // Often if the programmer does not specify proper prototypes for the
  // functions they are calling, they end up calling a vararg version of the
  // function that does not get a body filled in (the real function has typed
  // arguments).  This pass merges the two functions.
  Passes.add(createFunctionResolvingPass());

  if (Internalize) {
    // Now that composite has been compiled, scan through the module, looking
    // for a main function.  If main is defined, mark all other functions
    // internal.
    Passes.add(createInternalizePass());
  }

  // Remove unused arguments from functions...
  Passes.add(createDeadArgEliminationPass());

  // The FuncResolve pass may leave cruft around if functions were prototyped
  // differently than they were defined.  Remove this cruft.
  Passes.add(createInstructionCombiningPass());

  // Delete basic blocks, which optimization passes may have killed...
  Passes.add(createCFGSimplificationPass());

  // Now that we have optimized the program, discard unreachable functions...
  Passes.add(createGlobalDCEPass());

  // Add the pass that writes bytecode to the output file...
  Passes.add(new WriteBytecodePass(Out));

  // Run our queue of passes all at once now, efficiently.
  Passes.run(*M);

  return 0;
}

/// GenerateAssembly - generates a native assembly language source file from the
/// specified bytecode file.
///
/// Inputs:
///  InputFilename  - The name of the output bytecode file.
///  OutputFilename - The name of the file to generate.
///  llc            - The pathname to use for LLC.
///  envp           - The environment to use when running LLC.
///
/// Outputs:
///  None.
///
/// Return non-zero value on error.
///
int
GenerateAssembly(const std::string &OutputFilename,
                 const std::string &InputFilename,
                 const std::string &llc,
                 char ** const envp)
{
  // Run LLC to convert the bytecode file into assembly code.
  const char *cmd[8];

  cmd[0] = llc.c_str();
  cmd[1] = "-f";
  cmd[2] = "-o";
  cmd[3] = OutputFilename.c_str();
  cmd[4] = InputFilename.c_str();
  cmd[5] = NULL;

  return ExecWait(cmd, envp);
}

/// GenerateNative - generates a native assembly language source file from the
/// specified assembly source file.
///
/// Inputs:
///  InputFilename  - The name of the output bytecode file.
///  OutputFilename - The name of the file to generate.
///  Libraries      - The list of libraries with which to link.
///  LibPaths       - The list of directories in which to find libraries.
///  gcc            - The pathname to use for GGC.
///  envp           - A copy of the process's current environment.
///
/// Outputs:
///  None.
///
/// Returns non-zero value on error.
///
int
GenerateNative(const std::string &OutputFilename,
               const std::string &InputFilename,
               const std::vector<std::string> &Libraries,
               const std::vector<std::string> &LibPaths,
               const std::string &gcc,
               char ** const envp) {
  // Remove these environment variables from the environment of the
  // programs that we will execute.  It appears that GCC sets these
  // environment variables so that the programs it uses can configure
  // themselves identically.
  //
  // However, when we invoke GCC below, we want it to use its normal
  // configuration.  Hence, we must sanitize its environment.
  char ** clean_env = CopyEnv(envp);
  if (clean_env == NULL)
    return 1;
  RemoveEnv("LIBRARY_PATH", clean_env);
  RemoveEnv("COLLECT_GCC_OPTIONS", clean_env);
  RemoveEnv("GCC_EXEC_PREFIX", clean_env);
  RemoveEnv("COMPILER_PATH", clean_env);
  RemoveEnv("COLLECT_GCC", clean_env);

  std::vector<const char *> cmd;

  // Run GCC to assemble and link the program into native code.
  //
  // Note:
  //  We can't just assemble and link the file with the system assembler
  //  and linker because we don't know where to put the _start symbol.
  //  GCC mysteriously knows how to do it.
  cmd.push_back(gcc.c_str());
  cmd.push_back("-o");
  cmd.push_back(OutputFilename.c_str());
  cmd.push_back(InputFilename.c_str());

  // Adding the library paths creates a problem for native generation.  If we
  // include the search paths from llvmgcc, then we'll be telling normal gcc
  // to look inside of llvmgcc's library directories for libraries.  This is
  // bad because those libraries hold only bytecode files (not native object
  // files).  In the end, we attempt to link the bytecode libgcc into a native
  // program.
#if 0
  // Add in the library path options.
  for (unsigned index=0; index < LibPaths.size(); index++) {
    cmd.push_back("-L");
    cmd.push_back(LibPaths[index].c_str());
  }
#endif

  // Add in the libraries to link.
  std::vector<std::string> Libs(Libraries);
  for (unsigned index = 0; index < Libs.size(); index++) {
    Libs[index] = "-l" + Libs[index];
    cmd.push_back(Libs[index].c_str());
  }
  cmd.push_back(NULL);

  // Run the compiler to assembly and link together the program.
  return ExecWait(&(cmd[0]), clean_env);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: comdep.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2007-11-02 13:01:41 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _COMDEP_HXX
#define _COMDEP_HXX

#include <tools/fsys.hxx>

#define ACCESSDELIM(e)  ( (e == FSYS_STYLE_MAC) ? ":" : \
                        ( ( e == FSYS_STYLE_VFAT || e == FSYS_STYLE_HPFS || \
                            e == FSYS_STYLE_FAT ) || e == FSYS_STYLE_NTFS ) \
                          ? "\\" : "/" )
#define ACCESSDELIM_C(e)(char)\
                        ( (e == FSYS_STYLE_MAC) ? ':' : \
                        ( ( e == FSYS_STYLE_VFAT || e == FSYS_STYLE_HPFS || \
                            e == FSYS_STYLE_FAT ) || e == FSYS_STYLE_NTFS ) \
                          ? '\\' : '/' )
#define SEARCHDELIM(e)  ( (e == FSYS_STYLE_SYSV || e == FSYS_STYLE_BSD) ? ":" \
                        : ";" )
#define SEARCHDELIM_C(e)(char)\
                        ( (e == FSYS_STYLE_SYSV || e == FSYS_STYLE_BSD) ? ':' \
                        : ';' )
#define ACTPARENT(e)    ( (e == FSYS_STYLE_MAC) ? ":" : ".." )
#define ACTCURRENT(e)   ( (e == FSYS_STYLE_MAC) ? "" : "." )

#if defined UNX
#include "unx.hxx"
#elif defined WNT
#include "wntmsc.hxx"
#elif defined OS2
#include "os2.hxx"
#endif

//--------------------------------------------------------------------

#ifndef LINUX
DIR *opendir( const char* pPfad );
dirent *readdir( DIR *pDir );
int closedir( DIR *pDir );
char *volumeid( const char* pPfad );
#endif

//--------------------------------------------------------------------

struct DirReader_Impl
{
    Dir*        pDir;
    DIR*        pDosDir;
    dirent*     pDosEntry;
    DirEntry*   pParent;
    String      aPath;
    ByteString  aBypass;
    BOOL        bReady;
    BOOL        bInUse;

                DirReader_Impl( Dir &rDir )
                :   pDir( &rDir ),
                    pDosEntry( 0 ),
                    pParent( 0 ),
                    aPath( GUI2FSYS(rDir.GetFull()) ),
                    bReady ( FALSE ),
                    bInUse( FALSE )
                {
#ifndef BOOTSTRAP
                    // Redirection
                    FSysRedirector::DoRedirect( aPath );
#endif

                    // nur den String der Memer-Var nehmen!

#if defined(UNX) || defined(OS2) //for further exlpanation see DirReader_Impl::Read() in unx.cxx
                    pDosDir = NULL;
#else
                    aBypass = ByteString(aPath, osl_getThreadTextEncoding());
                    pDosDir = opendir( (char*) aBypass.GetBuffer() );
#endif

                    // Parent f"ur die neuen DirEntries ermitteln
                    pParent = pDir->GetFlag() == FSYS_FLAG_NORMAL ||
                              pDir->GetFlag() == FSYS_FLAG_ABSROOT
                                    ? pDir
                                    : pDir->GetParent();

                }

                ~DirReader_Impl()
                { if( pDosDir ) closedir( pDosDir ); }

                // die folgenden sind systemabh"angig implementiert
    USHORT      Init(); // initialisiert, liest ggf. devices
    USHORT      Read(); // liest 1 Eintrag, F2ugt ein falls ok
};

//--------------------------------------------------------------------

struct FileCopier_Impl
{
    FSysAction      nActions;       // was zu tun ist (Copy/Move/recur)
    Link            aErrorLink;     // bei Fehlern zu rufen
    ErrCode         eErr;           // aktueller Fehlercode im Error-Handler
    const DirEntry* pErrSource;     // fuer Error-Handler falls Source-Fehler
    const DirEntry* pErrTarget;     // fuer Error-Handler falls Target-Fehler

                    FileCopier_Impl()
                    :   nActions( 0 ), eErr( 0 ),
                        pErrSource( 0 ), pErrTarget( 0 )
                    {}
                    FileCopier_Impl( const FileCopier_Impl &rOrig )
                    :   nActions( rOrig.nActions ), eErr( 0 ),
                        pErrSource( 0 ), pErrTarget( 0 )
                    {}

    FileCopier_Impl& operator=( const FileCopier_Impl &rOrig )
                    {
                        nActions = rOrig.nActions;
                        eErr = 0; pErrSource = 0; pErrTarget = 0;
                        return *this;
                    }
};

//--------------------------------------------------------------------

#if defined WNT || defined OS2
BOOL IsRedirectable_Impl( const ByteString &rPath );
#else
#define IsRedirectable_Impl( rPath )    TRUE
#endif

//--------------------------------------------------------------------

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.5.58); FILE MERGED 2008/03/28 15:41:17 rt 1.5.58.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: comdep.hxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _COMDEP_HXX
#define _COMDEP_HXX

#include <tools/fsys.hxx>

#define ACCESSDELIM(e)  ( (e == FSYS_STYLE_MAC) ? ":" : \
                        ( ( e == FSYS_STYLE_VFAT || e == FSYS_STYLE_HPFS || \
                            e == FSYS_STYLE_FAT ) || e == FSYS_STYLE_NTFS ) \
                          ? "\\" : "/" )
#define ACCESSDELIM_C(e)(char)\
                        ( (e == FSYS_STYLE_MAC) ? ':' : \
                        ( ( e == FSYS_STYLE_VFAT || e == FSYS_STYLE_HPFS || \
                            e == FSYS_STYLE_FAT ) || e == FSYS_STYLE_NTFS ) \
                          ? '\\' : '/' )
#define SEARCHDELIM(e)  ( (e == FSYS_STYLE_SYSV || e == FSYS_STYLE_BSD) ? ":" \
                        : ";" )
#define SEARCHDELIM_C(e)(char)\
                        ( (e == FSYS_STYLE_SYSV || e == FSYS_STYLE_BSD) ? ':' \
                        : ';' )
#define ACTPARENT(e)    ( (e == FSYS_STYLE_MAC) ? ":" : ".." )
#define ACTCURRENT(e)   ( (e == FSYS_STYLE_MAC) ? "" : "." )

#if defined UNX
#include "unx.hxx"
#elif defined WNT
#include "wntmsc.hxx"
#elif defined OS2
#include "os2.hxx"
#endif

//--------------------------------------------------------------------

#ifndef LINUX
DIR *opendir( const char* pPfad );
dirent *readdir( DIR *pDir );
int closedir( DIR *pDir );
char *volumeid( const char* pPfad );
#endif

//--------------------------------------------------------------------

struct DirReader_Impl
{
    Dir*        pDir;
    DIR*        pDosDir;
    dirent*     pDosEntry;
    DirEntry*   pParent;
    String      aPath;
    ByteString  aBypass;
    BOOL        bReady;
    BOOL        bInUse;

                DirReader_Impl( Dir &rDir )
                :   pDir( &rDir ),
                    pDosEntry( 0 ),
                    pParent( 0 ),
                    aPath( GUI2FSYS(rDir.GetFull()) ),
                    bReady ( FALSE ),
                    bInUse( FALSE )
                {
#ifndef BOOTSTRAP
                    // Redirection
                    FSysRedirector::DoRedirect( aPath );
#endif

                    // nur den String der Memer-Var nehmen!

#if defined(UNX) || defined(OS2) //for further exlpanation see DirReader_Impl::Read() in unx.cxx
                    pDosDir = NULL;
#else
                    aBypass = ByteString(aPath, osl_getThreadTextEncoding());
                    pDosDir = opendir( (char*) aBypass.GetBuffer() );
#endif

                    // Parent f"ur die neuen DirEntries ermitteln
                    pParent = pDir->GetFlag() == FSYS_FLAG_NORMAL ||
                              pDir->GetFlag() == FSYS_FLAG_ABSROOT
                                    ? pDir
                                    : pDir->GetParent();

                }

                ~DirReader_Impl()
                { if( pDosDir ) closedir( pDosDir ); }

                // die folgenden sind systemabh"angig implementiert
    USHORT      Init(); // initialisiert, liest ggf. devices
    USHORT      Read(); // liest 1 Eintrag, F2ugt ein falls ok
};

//--------------------------------------------------------------------

struct FileCopier_Impl
{
    FSysAction      nActions;       // was zu tun ist (Copy/Move/recur)
    Link            aErrorLink;     // bei Fehlern zu rufen
    ErrCode         eErr;           // aktueller Fehlercode im Error-Handler
    const DirEntry* pErrSource;     // fuer Error-Handler falls Source-Fehler
    const DirEntry* pErrTarget;     // fuer Error-Handler falls Target-Fehler

                    FileCopier_Impl()
                    :   nActions( 0 ), eErr( 0 ),
                        pErrSource( 0 ), pErrTarget( 0 )
                    {}
                    FileCopier_Impl( const FileCopier_Impl &rOrig )
                    :   nActions( rOrig.nActions ), eErr( 0 ),
                        pErrSource( 0 ), pErrTarget( 0 )
                    {}

    FileCopier_Impl& operator=( const FileCopier_Impl &rOrig )
                    {
                        nActions = rOrig.nActions;
                        eErr = 0; pErrSource = 0; pErrTarget = 0;
                        return *this;
                    }
};

//--------------------------------------------------------------------

#if defined WNT || defined OS2
BOOL IsRedirectable_Impl( const ByteString &rPath );
#else
#define IsRedirectable_Impl( rPath )    TRUE
#endif

//--------------------------------------------------------------------

#endif
<|endoftext|>