<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 "ViewMenuManager.h"

#include "pqCoreUtilities.h"
#include "pqView.h"
#include "vtkCommand.h"
#include "vtkGridAxes3DActor.h"
#include "vtkSMPropertyHelper.h"
#include "vtkSMSessionProxyManager.h"
#include "vtkSMViewProxy.h"
#include "vtkTextProperty.h"

#include <QAction>
#include <QActionGroup>
#include <QDialog>
#include <QHBoxLayout>
#include <QMainWindow>
#include <QMenu>

#include "ActiveObjects.h"
#include "Utilities.h"
#include "ViewPropertiesPanel.h"

namespace tomviz {

ViewMenuManager::ViewMenuManager(QMainWindow* mainWindow, QMenu* menu)
  : pqViewMenuManager(mainWindow, menu), perspectiveProjectionAction(nullptr),
    orthographicProjectionAction(nullptr), showAxisGridAction(nullptr)
{
  this->viewPropertiesDialog = new QDialog(mainWindow);
  this->viewPropertiesDialog->setWindowTitle("View Properties");
  ViewPropertiesPanel* panel =
    new ViewPropertiesPanel(this->viewPropertiesDialog);
  QHBoxLayout* layout = new QHBoxLayout;
  layout->addWidget(panel);
  this->viewPropertiesDialog->setLayout(layout);
  this->connect(this->viewPropertiesDialog, SIGNAL(finished(int)),
                SLOT(viewPropertiesDialogHidden()));

  this->showViewPropertiesAction = new QAction("View Properties", this->Menu);
  this->showViewPropertiesAction->setCheckable(true);
  this->connect(this->showViewPropertiesAction, SIGNAL(triggered(bool)),
                SLOT(showViewPropertiesDialog(bool)));
  this->View = ActiveObjects::instance().activeView();
  if (this->View) {
    this->ViewObserverId =
      pqCoreUtilities::connect(this->View, vtkCommand::PropertyModifiedEvent,
                               this, SLOT(onViewPropertyChanged()));
  }
  this->connect(&ActiveObjects::instance(),
                SIGNAL(viewChanged(vtkSMViewProxy*)), SLOT(onViewChanged()));
}

void ViewMenuManager::buildMenu()
{
  bool showViewPropertiesChecked = this->showViewPropertiesAction->isChecked();
  bool perspectiveProjectionChecked = true;
  if (this->perspectiveProjectionAction) {
    perspectiveProjectionChecked =
      this->perspectiveProjectionAction->isChecked();
  }
  bool axisGridIsShowing = false;
  if (this->showAxisGridAction) {
    axisGridIsShowing = this->showAxisGridAction->isChecked();
  }
  this->showViewPropertiesAction = nullptr; // The object is about to be deleted
  this->perspectiveProjectionAction = nullptr;
  this->orthographicProjectionAction = nullptr;
  pqViewMenuManager::buildMenu(); // deletes all prior menu items and
                                  // repopulates menu

  this->Menu->addSeparator();
  // Projection modes
  QActionGroup* projectionGroup = new QActionGroup(this);

  this->perspectiveProjectionAction =
    this->Menu->addAction("Perspective Projection");
  this->perspectiveProjectionAction->setCheckable(true);
  this->perspectiveProjectionAction->setActionGroup(projectionGroup);
  this->perspectiveProjectionAction->setChecked(perspectiveProjectionChecked);
  this->connect(this->perspectiveProjectionAction, SIGNAL(triggered()),
                SLOT(setProjectionModeToPerspective()));
  this->orthographicProjectionAction =
    this->Menu->addAction("Orthographic Projection");
  this->orthographicProjectionAction->setCheckable(true);
  this->orthographicProjectionAction->setActionGroup(projectionGroup);
  this->orthographicProjectionAction->setChecked(!perspectiveProjectionChecked);
  this->connect(this->orthographicProjectionAction, SIGNAL(triggered()),
                SLOT(setProjectionModeToOrthographic()));

  this->Menu->addSeparator();

  this->showAxisGridAction = this->Menu->addAction("Show Axis Grid");
  this->showAxisGridAction->setCheckable(true);
  this->showAxisGridAction->setChecked(axisGridIsShowing);
  this->showAxisGridAction->setEnabled(this->View &&
                                       this->View->GetProperty("AxesGrid"));
  this->connect(this->showAxisGridAction, SIGNAL(triggered(bool)),
                SLOT(setShowAxisGrid(bool)));

  // Show view properties
  this->showViewPropertiesAction = this->Menu->addAction("View Properties");
  this->showViewPropertiesAction->setCheckable(true);
  this->showViewPropertiesAction->setChecked(showViewPropertiesChecked);
  this->connect(this->showViewPropertiesAction, SIGNAL(triggered(bool)),
                SLOT(showViewPropertiesDialog(bool)));
}

void ViewMenuManager::showViewPropertiesDialog(bool show)
{
  if (show) {
    this->viewPropertiesDialog->show();
  } else {
    this->viewPropertiesDialog->accept();
  }
}

void ViewMenuManager::viewPropertiesDialogHidden()
{
  this->showViewPropertiesAction->setChecked(false);
}

void ViewMenuManager::setProjectionModeToPerspective()
{
  if (!this->View->GetProperty("CameraParallelProjection")) {
    return;
  }
  int parallel =
    vtkSMPropertyHelper(this->View, "CameraParallelProjection").GetAsInt();
  if (parallel) {
    vtkSMPropertyHelper(this->View, "CameraParallelProjection").Set(0);
    this->View->UpdateVTKObjects();
    pqView* view = tomviz::convert<pqView*>(this->View);
    if (view) {
      view->render();
    }
  }
}

void ViewMenuManager::setProjectionModeToOrthographic()
{
  if (!this->View->GetProperty("CameraParallelProjection")) {
    return;
  }
  int parallel =
    vtkSMPropertyHelper(this->View, "CameraParallelProjection").GetAsInt();
  if (!parallel) {
    vtkSMPropertyHelper(this->View, "CameraParallelProjection").Set(1);
    this->View->UpdateVTKObjects();
    pqView* view = tomviz::convert<pqView*>(this->View);
    if (view) {
      view->render();
    }
  }
}

void ViewMenuManager::onViewPropertyChanged()
{
  if (!this->perspectiveProjectionAction ||
      !this->orthographicProjectionAction) {
    return;
  }
  if (!this->View->GetProperty("CameraParallelProjection")) {
    return;
  }
  int parallel =
    vtkSMPropertyHelper(this->View, "CameraParallelProjection").GetAsInt();
  if (parallel && this->perspectiveProjectionAction->isChecked()) {
    this->orthographicProjectionAction->setChecked(true);
  } else if (!parallel && this->orthographicProjectionAction->isChecked()) {
    this->perspectiveProjectionAction->setChecked(true);
  }
}

void ViewMenuManager::onViewChanged()
{
  if (this->View) {
    if (this->View->GetProperty("AxesGrid")) {
      vtkSMProxy* grid =
        vtkSMPropertyHelper(this->View, "AxesGrid").GetAsProxy();
      if (grid) {
        grid->RemoveObserver(this->AxesGridObserverId);
      }
      this->View->RemoveObserver(this->ViewObserverId);
    }
  }
  this->View = ActiveObjects::instance().activeView();
  if (this->View) {
    this->ViewObserverId =
      pqCoreUtilities::connect(this->View, vtkCommand::PropertyModifiedEvent,
                               this, SLOT(onViewPropertyChanged()));
    if (this->View->GetProperty("AxesGrid")) {
      vtkSMPropertyHelper axesGridProp(this->View, "AxesGrid");
      vtkSMProxy* proxy = axesGridProp.GetAsProxy();
      if (!proxy) {
        vtkSMSessionProxyManager* pxm = this->View->GetSessionProxyManager();
        proxy = pxm->NewProxy("annotations", "GridAxes3DActor");
        axesGridProp.Set(proxy);
        this->View->UpdateVTKObjects();
        proxy->Delete();
      }
      this->AxesGridObserverId =
        pqCoreUtilities::connect(proxy, vtkCommand::PropertyModifiedEvent, this,
                                 SLOT(onAxesGridChanged()));
    }
  }
  bool enableAxesGrid = (this->View && this->View->GetProperty("AxesGrid"));
  // We have to check since this can be called before buildMenu
  if (this->showAxisGridAction) {
    this->showAxisGridAction->setEnabled(enableAxesGrid);
  }
  bool enableProjectionModes =
    (this->View && this->View->GetProperty("CameraParallelProjection"));
  // We have to check since this can be called before buildMenu
  if (this->orthographicProjectionAction && this->perspectiveProjectionAction) {
    this->orthographicProjectionAction->setEnabled(enableProjectionModes);
    this->perspectiveProjectionAction->setEnabled(enableProjectionModes);
  }
}

void ViewMenuManager::setShowAxisGrid(bool show)
{
  if (!this->View->GetProperty("AxesGrid")) {
    return;
  }
  vtkSMProxy* axesGrid =
    vtkSMPropertyHelper(this->View, "AxesGrid").GetAsProxy();
  int showing = vtkSMPropertyHelper(axesGrid, "Visibility").GetAsInt();
  if (showing && !show) {
    vtkSMPropertyHelper(axesGrid, "Visibility").Set(0);
  } else if (!showing && show) {
    vtkSMPropertyHelper(axesGrid, "Visibility").Set(1);

    auto actor =
      vtkGridAxes3DActor::SafeDownCast(axesGrid->GetClientSideObject());

    for (int i : { 0, 1, 2 }) {
      actor->GetTitleTextProperty(i)->SetColor(offWhite);
      actor->GetLabelTextProperty(i)->SetColor(offWhite);
    }
  }
  axesGrid->UpdateVTKObjects();
  pqView* view = tomviz::convert<pqView*>(this->View);
  if (view) {
    view->render();
  }
}

void ViewMenuManager::onAxesGridChanged()
{
  if (!this->showAxisGridAction) {
    return;
  }
  vtkSMProxy* axesGrid =
    vtkSMPropertyHelper(this->View, "AxesGrid").GetAsProxy();
  int showing = vtkSMPropertyHelper(axesGrid, "Visibility").GetAsInt();
  if (showing && !this->showAxisGridAction->isChecked()) {
    this->showAxisGridAction->setChecked(true);
  } else if (!showing && this->showAxisGridAction->isChecked()) {
    this->showAxisGridAction->setChecked(false);
  }
}
}
<commit_msg>Set axes grid to off white<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 "ViewMenuManager.h"

#include "pqCoreUtilities.h"
#include "pqView.h"
#include "vtkCommand.h"
#include "vtkGridAxes3DActor.h"
#include "vtkSMPropertyHelper.h"
#include "vtkSMSessionProxyManager.h"
#include "vtkSMViewProxy.h"
#include "vtkTextProperty.h"
#include "vtkProperty.h"

#include <QAction>
#include <QActionGroup>
#include <QDialog>
#include <QHBoxLayout>
#include <QMainWindow>
#include <QMenu>

#include "ActiveObjects.h"
#include "Utilities.h"
#include "ViewPropertiesPanel.h"

namespace tomviz {

ViewMenuManager::ViewMenuManager(QMainWindow* mainWindow, QMenu* menu)
  : pqViewMenuManager(mainWindow, menu), perspectiveProjectionAction(nullptr),
    orthographicProjectionAction(nullptr), showAxisGridAction(nullptr)
{
  this->viewPropertiesDialog = new QDialog(mainWindow);
  this->viewPropertiesDialog->setWindowTitle("View Properties");
  ViewPropertiesPanel* panel =
    new ViewPropertiesPanel(this->viewPropertiesDialog);
  QHBoxLayout* layout = new QHBoxLayout;
  layout->addWidget(panel);
  this->viewPropertiesDialog->setLayout(layout);
  this->connect(this->viewPropertiesDialog, SIGNAL(finished(int)),
                SLOT(viewPropertiesDialogHidden()));

  this->showViewPropertiesAction = new QAction("View Properties", this->Menu);
  this->showViewPropertiesAction->setCheckable(true);
  this->connect(this->showViewPropertiesAction, SIGNAL(triggered(bool)),
                SLOT(showViewPropertiesDialog(bool)));
  this->View = ActiveObjects::instance().activeView();
  if (this->View) {
    this->ViewObserverId =
      pqCoreUtilities::connect(this->View, vtkCommand::PropertyModifiedEvent,
                               this, SLOT(onViewPropertyChanged()));
  }
  this->connect(&ActiveObjects::instance(),
                SIGNAL(viewChanged(vtkSMViewProxy*)), SLOT(onViewChanged()));
}

void ViewMenuManager::buildMenu()
{
  bool showViewPropertiesChecked = this->showViewPropertiesAction->isChecked();
  bool perspectiveProjectionChecked = true;
  if (this->perspectiveProjectionAction) {
    perspectiveProjectionChecked =
      this->perspectiveProjectionAction->isChecked();
  }
  bool axisGridIsShowing = false;
  if (this->showAxisGridAction) {
    axisGridIsShowing = this->showAxisGridAction->isChecked();
  }
  this->showViewPropertiesAction = nullptr; // The object is about to be deleted
  this->perspectiveProjectionAction = nullptr;
  this->orthographicProjectionAction = nullptr;
  pqViewMenuManager::buildMenu(); // deletes all prior menu items and
                                  // repopulates menu

  this->Menu->addSeparator();
  // Projection modes
  QActionGroup* projectionGroup = new QActionGroup(this);

  this->perspectiveProjectionAction =
    this->Menu->addAction("Perspective Projection");
  this->perspectiveProjectionAction->setCheckable(true);
  this->perspectiveProjectionAction->setActionGroup(projectionGroup);
  this->perspectiveProjectionAction->setChecked(perspectiveProjectionChecked);
  this->connect(this->perspectiveProjectionAction, SIGNAL(triggered()),
                SLOT(setProjectionModeToPerspective()));
  this->orthographicProjectionAction =
    this->Menu->addAction("Orthographic Projection");
  this->orthographicProjectionAction->setCheckable(true);
  this->orthographicProjectionAction->setActionGroup(projectionGroup);
  this->orthographicProjectionAction->setChecked(!perspectiveProjectionChecked);
  this->connect(this->orthographicProjectionAction, SIGNAL(triggered()),
                SLOT(setProjectionModeToOrthographic()));

  this->Menu->addSeparator();

  this->showAxisGridAction = this->Menu->addAction("Show Axis Grid");
  this->showAxisGridAction->setCheckable(true);
  this->showAxisGridAction->setChecked(axisGridIsShowing);
  this->showAxisGridAction->setEnabled(this->View &&
                                       this->View->GetProperty("AxesGrid"));
  this->connect(this->showAxisGridAction, SIGNAL(triggered(bool)),
                SLOT(setShowAxisGrid(bool)));

  // Show view properties
  this->showViewPropertiesAction = this->Menu->addAction("View Properties");
  this->showViewPropertiesAction->setCheckable(true);
  this->showViewPropertiesAction->setChecked(showViewPropertiesChecked);
  this->connect(this->showViewPropertiesAction, SIGNAL(triggered(bool)),
                SLOT(showViewPropertiesDialog(bool)));
}

void ViewMenuManager::showViewPropertiesDialog(bool show)
{
  if (show) {
    this->viewPropertiesDialog->show();
  } else {
    this->viewPropertiesDialog->accept();
  }
}

void ViewMenuManager::viewPropertiesDialogHidden()
{
  this->showViewPropertiesAction->setChecked(false);
}

void ViewMenuManager::setProjectionModeToPerspective()
{
  if (!this->View->GetProperty("CameraParallelProjection")) {
    return;
  }
  int parallel =
    vtkSMPropertyHelper(this->View, "CameraParallelProjection").GetAsInt();
  if (parallel) {
    vtkSMPropertyHelper(this->View, "CameraParallelProjection").Set(0);
    this->View->UpdateVTKObjects();
    pqView* view = tomviz::convert<pqView*>(this->View);
    if (view) {
      view->render();
    }
  }
}

void ViewMenuManager::setProjectionModeToOrthographic()
{
  if (!this->View->GetProperty("CameraParallelProjection")) {
    return;
  }
  int parallel =
    vtkSMPropertyHelper(this->View, "CameraParallelProjection").GetAsInt();
  if (!parallel) {
    vtkSMPropertyHelper(this->View, "CameraParallelProjection").Set(1);
    this->View->UpdateVTKObjects();
    pqView* view = tomviz::convert<pqView*>(this->View);
    if (view) {
      view->render();
    }
  }
}

void ViewMenuManager::onViewPropertyChanged()
{
  if (!this->perspectiveProjectionAction ||
      !this->orthographicProjectionAction) {
    return;
  }
  if (!this->View->GetProperty("CameraParallelProjection")) {
    return;
  }
  int parallel =
    vtkSMPropertyHelper(this->View, "CameraParallelProjection").GetAsInt();
  if (parallel && this->perspectiveProjectionAction->isChecked()) {
    this->orthographicProjectionAction->setChecked(true);
  } else if (!parallel && this->orthographicProjectionAction->isChecked()) {
    this->perspectiveProjectionAction->setChecked(true);
  }
}

void ViewMenuManager::onViewChanged()
{
  if (this->View) {
    if (this->View->GetProperty("AxesGrid")) {
      vtkSMProxy* grid =
        vtkSMPropertyHelper(this->View, "AxesGrid").GetAsProxy();
      if (grid) {
        grid->RemoveObserver(this->AxesGridObserverId);
      }
      this->View->RemoveObserver(this->ViewObserverId);
    }
  }
  this->View = ActiveObjects::instance().activeView();
  if (this->View) {
    this->ViewObserverId =
      pqCoreUtilities::connect(this->View, vtkCommand::PropertyModifiedEvent,
                               this, SLOT(onViewPropertyChanged()));
    if (this->View->GetProperty("AxesGrid")) {
      vtkSMPropertyHelper axesGridProp(this->View, "AxesGrid");
      vtkSMProxy* proxy = axesGridProp.GetAsProxy();
      if (!proxy) {
        vtkSMSessionProxyManager* pxm = this->View->GetSessionProxyManager();
        proxy = pxm->NewProxy("annotations", "GridAxes3DActor");
        axesGridProp.Set(proxy);
        this->View->UpdateVTKObjects();
        proxy->Delete();
      }
      this->AxesGridObserverId =
        pqCoreUtilities::connect(proxy, vtkCommand::PropertyModifiedEvent, this,
                                 SLOT(onAxesGridChanged()));
    }
  }
  bool enableAxesGrid = (this->View && this->View->GetProperty("AxesGrid"));
  // We have to check since this can be called before buildMenu
  if (this->showAxisGridAction) {
    this->showAxisGridAction->setEnabled(enableAxesGrid);
  }
  bool enableProjectionModes =
    (this->View && this->View->GetProperty("CameraParallelProjection"));
  // We have to check since this can be called before buildMenu
  if (this->orthographicProjectionAction && this->perspectiveProjectionAction) {
    this->orthographicProjectionAction->setEnabled(enableProjectionModes);
    this->perspectiveProjectionAction->setEnabled(enableProjectionModes);
  }
}

void ViewMenuManager::setShowAxisGrid(bool show)
{
  if (!this->View->GetProperty("AxesGrid")) {
    return;
  }
  vtkSMProxy* axesGrid =
    vtkSMPropertyHelper(this->View, "AxesGrid").GetAsProxy();
  int showing = vtkSMPropertyHelper(axesGrid, "Visibility").GetAsInt();
  if (showing && !show) {
    vtkSMPropertyHelper(axesGrid, "Visibility").Set(0);
  } else if (!showing && show) {
    vtkSMPropertyHelper(axesGrid, "Visibility").Set(1);

    auto actor =
      vtkGridAxes3DActor::SafeDownCast(axesGrid->GetClientSideObject());

    for (int i : { 0, 1, 2 }) {
      actor->GetTitleTextProperty(i)->SetColor(offWhite);
      actor->GetLabelTextProperty(i)->SetColor(offWhite);
      actor->GetProperty()->SetColor(offWhite);
    }
  }
  axesGrid->UpdateVTKObjects();
  pqView* view = tomviz::convert<pqView*>(this->View);
  if (view) {
    view->render();
  }
}

void ViewMenuManager::onAxesGridChanged()
{
  if (!this->showAxisGridAction) {
    return;
  }
  vtkSMProxy* axesGrid =
    vtkSMPropertyHelper(this->View, "AxesGrid").GetAsProxy();
  int showing = vtkSMPropertyHelper(axesGrid, "Visibility").GetAsInt();
  if (showing && !this->showAxisGridAction->isChecked()) {
    this->showAxisGridAction->setChecked(true);
  } else if (!showing && this->showAxisGridAction->isChecked()) {
    this->showAxisGridAction->setChecked(false);
  }
}
}
<|endoftext|>


<commit_before>// Copyright 2013-2015 Stanford University
//
// 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 <iostream>
#include <sys/time.h>

#include "src/ext/cpputil/include/command_line/command_line.h"
#include "src/ext/cpputil/include/io/column.h"
#include "src/ext/cpputil/include/io/filterstream.h"
#include "src/ext/cpputil/include/signal/debug_handler.h"

#include "src/cfg/cfg_transforms.h"
#include "src/tunit/tunit.h"
#include "src/search/progress_callback.h"
#include "src/search/statistics_callback.h"
#include "src/search/timeout.h"
#include "src/search/postprocessing.h"

#include "tools/args/search.inc"
#include "tools/args/target.inc"
#include "tools/gadgets/cost_function.h"
#include "tools/gadgets/functions.h"
#include "tools/gadgets/sandbox.h"
#include "tools/gadgets/search.h"
#include "tools/gadgets/search_state.h"
#include "tools/gadgets/seed.h"
#include "tools/gadgets/solver.h"
#include "tools/gadgets/target.h"
#include "tools/gadgets/testcases.h"
#include "tools/gadgets/transforms.h"
#include "tools/gadgets/validator.h"
#include "tools/gadgets/verifier.h"
#include "tools/io/postprocessing.h"
#include "tools/io/timeout.h"
#include "tools/ui/console.h"

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

auto& io = Heading::create("Output Options:");
auto& out = ValueArg<string>::create("out")
            .alternate("o")
            .usage("<path/to/file.s>")
            .description("File to write successful results to")
            .default_val("result.s");

auto& stats = Heading::create("Statistics Options:");
auto& stat_int =
  ValueArg<size_t>::create("statistics_interval")
  .usage("<int>")
  .description("Number of iterations between statistics updates")
  .default_val(1000000);

auto& automation_heading = Heading::create("Automation Options:");
auto& timeout_action_arg =
  ValueArg<Timeout, TimeoutReader, TimeoutWriter>::create("timeout_action")
  .usage("(quit|restart|testcase)")
  .description("Action to take when search times out")
  .default_val(Timeout::RESTART);
auto& timeout_cycles_arg =
  ValueArg<size_t>::create("timeout_cycles")
  .usage("<int>")
  .description("Number of timeout cycles to attempt before giving up")
  .default_val(16);

ValueArg<double>& exp_scaling_arg =
  ValueArg<double>::create("exp_scaling")
  .usage("<double>")
  .description("Exponential scaling factor of timeout iterations per cycle (requires timeout_action==restart)")
  .default_val(1.0);

auto& postprocessing_arg =
  ValueArg<Postprocessing, PostprocessingReader, PostprocessingWriter>::create("postprocessing")
  .usage("(none|simple|full)")
  .description("Postprocessing of the program found by STOKE (simple removes nops and unreachable blocks, and full additionally removes redundant statements without side-effects)")
  .default_val(Postprocessing::FULL);

void sep(ostream& os, string c = "*") {
  for (size_t i = 0; i < 80; ++i) {
    os << c;
  }
  os << endl << endl;
}

static Cost lowest_cost = 0;
static Cost lowest_correct = 0;
static Cost starting_cost = 0;

void show_state(const SearchState& state, ostream& os) {
  CfgTransforms tforms;

  ofilterstream<Column> ofs(os);
  ofs.filter().padding(5);

  auto best_yet = state.best_yet;
  tforms.remove_unreachable(best_yet);
  tforms.remove_nop(best_yet);

  lowest_cost = state.best_yet_cost;
  ofs << "Lowest Cost Discovered (" << state.best_yet_cost << ")" << endl;
  ofs << endl;
  ofs << best_yet.get_code();
  ofs.filter().next();

  auto best_correct = state.best_correct;
  tforms.remove_unreachable(best_correct);
  tforms.remove_nop(best_correct);

  lowest_correct = state.best_correct_cost;
  ofs << "Lowest Known Correct Cost (" << state.best_correct_cost << ")" << endl;
  ofs << endl;
  ofs << best_correct.get_code();
  ofs.filter().done();
}

void pcb(const ProgressCallbackData& data, void* arg) {
  ostream& os = *((ostream*)arg);

  os << "Progress Update: " << endl;
  os << endl;

  show_state(data.state, os);

  os << endl << endl;
  sep(os);
}

struct ScbArg {
  ostream* os;
  uint32_t** cost_stats;
};

void show_statistics(const StatisticsCallbackData& data, ostream& os) {
  os << "Iterations:                    " << data.iterations << endl;
  os << "Elapsed Time:                  " << data.elapsed.count() << "s" << endl;
  os << "Iterations/s:                  " << (data.iterations / data.elapsed.count()) << endl;
  os << endl;
  os << "Starting cost:                 " << starting_cost << endl;
  os << "Lowest cost:                   " << lowest_cost << endl;
  os << "Lowest correct cost:           " << lowest_correct << endl;
  os << endl;

  ofilterstream<Column> ofs(os);
  ofs.filter().padding(5);

  Statistics total;
  for (size_t i = 0; i < 6; ++i) {
    total += data.move_statistics[i];
  }

  ofs << "Move Type" << endl;
  ofs << endl;
  ofs << "Instruction" << endl;
  ofs << "Opcode" << endl;
  ofs << "Operand" << endl;
  ofs << "Resize" << endl;
  ofs << "Local Swap" << endl;
  ofs << "Global Swap" << endl;
  ofs << "Extension" << endl;
  ofs << endl;
  ofs << "Total";
  ofs.filter().next();

  ofs << "Proposed" << endl;
  ofs << endl;
  for (size_t i = 0; i < (size_t) Move::NUM_MOVES; ++i) {
    ofs << 100 * (double)data.move_statistics[i].num_proposed / data.iterations << "%" << endl;
  }
  ofs << endl;
  ofs << 100 * (double)total.num_proposed / data.iterations << "%";
  ofs.filter().next();

  ofs << "Succeeded" << endl;
  ofs << endl;
  for (size_t i = 0; i < (size_t) Move::NUM_MOVES; ++i) {
    ofs << 100 * (double)data.move_statistics[i].num_succeeded / data.iterations << "%" << endl;
  }
  ofs << endl;
  ofs << 100 * (double)total.num_succeeded / data.iterations << "%";
  ofs.filter().next();

  ofs << "Accepted" << endl;
  ofs << endl;
  for (size_t i = 0; i < (size_t) Move::NUM_MOVES; ++i) {
    ofs << 100 * (double)data.move_statistics[i].num_accepted / data.iterations << "%" << endl;
  }
  ofs << endl;
  ofs << 100 * (double)total.num_accepted / data.iterations << "%";
  ofs.filter().done();
}

void scb(const StatisticsCallbackData& data, void* arg) {
  ScbArg sa = *((ScbArg*)arg);
  ostream& os = *(sa.os);
  uint32_t** cost_stats = sa.cost_stats;

  os << "Statistics Update: " << endl;
  os << endl;
  show_statistics(data, os);

  os << endl << endl;
  sep(os);
}

void show_final_update(const StatisticsCallbackData& stats, SearchState& state,
                       size_t total_restarts,
                       size_t total_iterations, time_point<steady_clock> start,
                       duration<double> search_elapsed) {
  auto total_elapsed = duration_cast<duration<double>>(steady_clock::now() - start);
  sep(Console::msg(), "#");
  Console::msg() << "Final update:" << endl << endl;
  Console::msg() << "Total search iterations:       " << total_iterations << endl;
  Console::msg() << "Number of attempted searches:  " << total_restarts << endl;
  Console::msg() << "Total search time:             " << search_elapsed.count() << "s" << endl;
  Console::msg() << "Total time:                    " << total_elapsed.count() << "s" << endl;
  Console::msg() << endl << "Statistics of last search" << endl << endl;
  // get the state first (because it updates some static variables)
  ostringstream stream;
  show_state(state, stream);
  show_statistics(stats, Console::msg());
  Console::msg() << endl << endl;
  Console::msg() << stream.str();
  Console::msg() << endl << endl;
  sep(Console::msg(), "#");
}

int main(int argc, char** argv) {
  const auto start = steady_clock::now();
  duration<double> search_elapsed;

  CommandLineConfig::strict_with_convenience(argc, argv);
  DebugHandler::install_sigsegv();
  DebugHandler::install_sigill();

  SeedGadget seed;
  FunctionsGadget aux_fxns;
  TargetGadget target(aux_fxns);

  TrainingSetGadget training_set(seed);
  SandboxGadget training_sb(training_set, aux_fxns);

  TransformsGadget transforms(target.get_code(), aux_fxns, seed);
  SearchGadget search(&transforms, seed);

  TestSetGadget test_set(seed);
  SandboxGadget test_sb(test_set, aux_fxns);
  CostFunctionGadget holdout_fxn(target, &test_sb);
  SolverGadget smt;
  ValidatorGadget validator(smt);
  VerifierGadget verifier(holdout_fxn, validator);

  if (!target.is_sound()) {
    Console::error(1) << "Target reads undefined variables, or leaves live_out undefined: " << target.which_undef_read() << endl;
  }

  ScbArg scb_arg {&Console::msg(), nullptr};
  search.set_progress_callback(pcb, &Console::msg())
  .set_statistics_callback(scb, &scb_arg)
  .set_statistics_interval(stat_int);

  size_t total_iterations = 0;
  size_t total_restarts = 0;

  string final_msg;
  SearchStateGadget state(target, aux_fxns);
  for (size_t i = 0; ; ++i) {
    CostFunctionGadget fxn(target, &training_sb);

    Console::msg() << "Running search:" << endl << endl;
    state = SearchStateGadget(target, aux_fxns);

    // Run the initial cost function
    // Used by statistics output and a sanity check
    auto initial_cost = fxn(state.current);
    if(!initial_cost.first && init_arg == Init::TARGET) {
      Console::warn() << "Initial state has non-zero correctness cost with --init target.";
    }
    starting_cost = initial_cost.second;
    lowest_cost = initial_cost.second;
    if(initial_cost.first) {
      lowest_correct = initial_cost.second;
    } else {
      lowest_correct = 0;
    }

    search.set_timeout_itr(timeout_itr_arg);
    const auto start_search = steady_clock::now();
    search.run(target, fxn, init_arg, state, aux_fxns);
    search_elapsed += duration_cast<duration<double>>(steady_clock::now() - start_search);

    total_iterations += search.get_statistics().iterations;
    total_restarts++;

    if (state.interrupted) {
      Console::msg() << endl;
      show_final_update(search.get_statistics(), state, total_restarts, total_iterations, start, search_elapsed);
      Console::msg() << "Search interrupted!" << endl;
      exit(1);
    }

    const auto verified = verifier.verify(target, state.best_correct);

    if(verifier.has_error()) {
      Console::msg() << "The verifier encountered an error:" << endl;
      Console::msg() << verifier.error() << endl;
    }

    if (!state.success) {
      Console::msg() << "Unable to discover a new correct rewrite before timing out... " << endl << endl;
    } else if (!verified) {
      Console::msg() << "Unable to verify new rewrite..." << endl << endl;
    } else {
      if (strategy_arg.value() == Strategy::NONE) {
        final_msg = "Search terminated successfully (but no verification was performed)!";
      } else {
        final_msg = "Search terminated successfully with a verified rewrite!";
      }
      break;
    }

    sep(Console::msg());

    if ((timeout_action_arg == Timeout::RESTART) && (i < timeout_cycles_arg.value())) {
      if (exp_scaling_arg.value() != 1.0) {
        timeout_itr_arg.value() = (size_t)ceil(timeout_itr_arg.value() * exp_scaling_arg.value());
        Console::msg() << "Increasing timeout iterations to " << timeout_itr_arg.value() << endl;
      }
      Console::msg() << "Restarting search:" << endl << endl;
    } else if ((timeout_action_arg == Timeout::TESTCASE) && (i < timeout_cycles_arg.value())
               && verifier.counter_example_available()) {
      Console::msg() << "Restarting search using new testcase:" << endl << endl;
      Console::msg() << verifier.get_counter_example() << endl << endl;
      training_sb.insert_input(verifier.get_counter_example());
    } else {
      show_final_update(search.get_statistics(), state, total_restarts, total_iterations, start, search_elapsed);
      Console::error(1) << "Search terminated unsuccessfully; unable to discover a new rewrite!" << endl;
    }
  }

  CfgTransforms tforms;
  if (postprocessing_arg == Postprocessing::FULL) {
    tforms.remove_redundant(state.best_correct);
    tforms.remove_unreachable(state.best_correct);
    tforms.remove_nop(state.best_correct);
  } else if (postprocessing_arg == Postprocessing::SIMPLE) {
    tforms.remove_unreachable(state.best_correct);
    tforms.remove_nop(state.best_correct);
  } else {
		// Do nothing.
	}

  auto final_stats = search.get_statistics();

  TUnit rewrite;
  rewrite.name = target_arg.value().name;
  rewrite.code = state.best_correct.get_code();

  show_final_update(final_stats, state, total_restarts, total_iterations, start, search_elapsed);
  Console::msg() << final_msg << endl;

  ofstream ofs(out.value());
  ofs << rewrite;

  return 0;
}
<commit_msg>style<commit_after>// Copyright 2013-2015 Stanford University
//
// 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 <iostream>
#include <sys/time.h>

#include "src/ext/cpputil/include/command_line/command_line.h"
#include "src/ext/cpputil/include/io/column.h"
#include "src/ext/cpputil/include/io/filterstream.h"
#include "src/ext/cpputil/include/signal/debug_handler.h"

#include "src/cfg/cfg_transforms.h"
#include "src/tunit/tunit.h"
#include "src/search/progress_callback.h"
#include "src/search/statistics_callback.h"
#include "src/search/timeout.h"
#include "src/search/postprocessing.h"

#include "tools/args/search.inc"
#include "tools/args/target.inc"
#include "tools/gadgets/cost_function.h"
#include "tools/gadgets/functions.h"
#include "tools/gadgets/sandbox.h"
#include "tools/gadgets/search.h"
#include "tools/gadgets/search_state.h"
#include "tools/gadgets/seed.h"
#include "tools/gadgets/solver.h"
#include "tools/gadgets/target.h"
#include "tools/gadgets/testcases.h"
#include "tools/gadgets/transforms.h"
#include "tools/gadgets/validator.h"
#include "tools/gadgets/verifier.h"
#include "tools/io/postprocessing.h"
#include "tools/io/timeout.h"
#include "tools/ui/console.h"

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

auto& io = Heading::create("Output Options:");
auto& out = ValueArg<string>::create("out")
            .alternate("o")
            .usage("<path/to/file.s>")
            .description("File to write successful results to")
            .default_val("result.s");

auto& stats = Heading::create("Statistics Options:");
auto& stat_int =
  ValueArg<size_t>::create("statistics_interval")
  .usage("<int>")
  .description("Number of iterations between statistics updates")
  .default_val(1000000);

auto& automation_heading = Heading::create("Automation Options:");
auto& timeout_action_arg =
  ValueArg<Timeout, TimeoutReader, TimeoutWriter>::create("timeout_action")
  .usage("(quit|restart|testcase)")
  .description("Action to take when search times out")
  .default_val(Timeout::RESTART);
auto& timeout_cycles_arg =
  ValueArg<size_t>::create("timeout_cycles")
  .usage("<int>")
  .description("Number of timeout cycles to attempt before giving up")
  .default_val(16);

ValueArg<double>& exp_scaling_arg =
  ValueArg<double>::create("exp_scaling")
  .usage("<double>")
  .description("Exponential scaling factor of timeout iterations per cycle (requires timeout_action==restart)")
  .default_val(1.0);

auto& postprocessing_arg =
  ValueArg<Postprocessing, PostprocessingReader, PostprocessingWriter>::create("postprocessing")
  .usage("(none|simple|full)")
  .description("Postprocessing of the program found by STOKE (simple removes nops and unreachable blocks, and full additionally removes redundant statements without side-effects)")
  .default_val(Postprocessing::FULL);

void sep(ostream& os, string c = "*") {
  for (size_t i = 0; i < 80; ++i) {
    os << c;
  }
  os << endl << endl;
}

static Cost lowest_cost = 0;
static Cost lowest_correct = 0;
static Cost starting_cost = 0;

void show_state(const SearchState& state, ostream& os) {
  CfgTransforms tforms;

  ofilterstream<Column> ofs(os);
  ofs.filter().padding(5);

  auto best_yet = state.best_yet;
  tforms.remove_unreachable(best_yet);
  tforms.remove_nop(best_yet);

  lowest_cost = state.best_yet_cost;
  ofs << "Lowest Cost Discovered (" << state.best_yet_cost << ")" << endl;
  ofs << endl;
  ofs << best_yet.get_code();
  ofs.filter().next();

  auto best_correct = state.best_correct;
  tforms.remove_unreachable(best_correct);
  tforms.remove_nop(best_correct);

  lowest_correct = state.best_correct_cost;
  ofs << "Lowest Known Correct Cost (" << state.best_correct_cost << ")" << endl;
  ofs << endl;
  ofs << best_correct.get_code();
  ofs.filter().done();
}

void pcb(const ProgressCallbackData& data, void* arg) {
  ostream& os = *((ostream*)arg);

  os << "Progress Update: " << endl;
  os << endl;

  show_state(data.state, os);

  os << endl << endl;
  sep(os);
}

struct ScbArg {
  ostream* os;
  uint32_t** cost_stats;
};

void show_statistics(const StatisticsCallbackData& data, ostream& os) {
  os << "Iterations:                    " << data.iterations << endl;
  os << "Elapsed Time:                  " << data.elapsed.count() << "s" << endl;
  os << "Iterations/s:                  " << (data.iterations / data.elapsed.count()) << endl;
  os << endl;
  os << "Starting cost:                 " << starting_cost << endl;
  os << "Lowest cost:                   " << lowest_cost << endl;
  os << "Lowest correct cost:           " << lowest_correct << endl;
  os << endl;

  ofilterstream<Column> ofs(os);
  ofs.filter().padding(5);

  Statistics total;
  for (size_t i = 0; i < 6; ++i) {
    total += data.move_statistics[i];
  }

  ofs << "Move Type" << endl;
  ofs << endl;
  ofs << "Instruction" << endl;
  ofs << "Opcode" << endl;
  ofs << "Operand" << endl;
  ofs << "Resize" << endl;
  ofs << "Local Swap" << endl;
  ofs << "Global Swap" << endl;
  ofs << "Extension" << endl;
  ofs << endl;
  ofs << "Total";
  ofs.filter().next();

  ofs << "Proposed" << endl;
  ofs << endl;
  for (size_t i = 0; i < (size_t) Move::NUM_MOVES; ++i) {
    ofs << 100 * (double)data.move_statistics[i].num_proposed / data.iterations << "%" << endl;
  }
  ofs << endl;
  ofs << 100 * (double)total.num_proposed / data.iterations << "%";
  ofs.filter().next();

  ofs << "Succeeded" << endl;
  ofs << endl;
  for (size_t i = 0; i < (size_t) Move::NUM_MOVES; ++i) {
    ofs << 100 * (double)data.move_statistics[i].num_succeeded / data.iterations << "%" << endl;
  }
  ofs << endl;
  ofs << 100 * (double)total.num_succeeded / data.iterations << "%";
  ofs.filter().next();

  ofs << "Accepted" << endl;
  ofs << endl;
  for (size_t i = 0; i < (size_t) Move::NUM_MOVES; ++i) {
    ofs << 100 * (double)data.move_statistics[i].num_accepted / data.iterations << "%" << endl;
  }
  ofs << endl;
  ofs << 100 * (double)total.num_accepted / data.iterations << "%";
  ofs.filter().done();
}

void scb(const StatisticsCallbackData& data, void* arg) {
  ScbArg sa = *((ScbArg*)arg);
  ostream& os = *(sa.os);
  uint32_t** cost_stats = sa.cost_stats;

  os << "Statistics Update: " << endl;
  os << endl;
  show_statistics(data, os);

  os << endl << endl;
  sep(os);
}

void show_final_update(const StatisticsCallbackData& stats, SearchState& state,
                       size_t total_restarts,
                       size_t total_iterations, time_point<steady_clock> start,
                       duration<double> search_elapsed) {
  auto total_elapsed = duration_cast<duration<double>>(steady_clock::now() - start);
  sep(Console::msg(), "#");
  Console::msg() << "Final update:" << endl << endl;
  Console::msg() << "Total search iterations:       " << total_iterations << endl;
  Console::msg() << "Number of attempted searches:  " << total_restarts << endl;
  Console::msg() << "Total search time:             " << search_elapsed.count() << "s" << endl;
  Console::msg() << "Total time:                    " << total_elapsed.count() << "s" << endl;
  Console::msg() << endl << "Statistics of last search" << endl << endl;
  // get the state first (because it updates some static variables)
  ostringstream stream;
  show_state(state, stream);
  show_statistics(stats, Console::msg());
  Console::msg() << endl << endl;
  Console::msg() << stream.str();
  Console::msg() << endl << endl;
  sep(Console::msg(), "#");
}

int main(int argc, char** argv) {
  const auto start = steady_clock::now();
  duration<double> search_elapsed;

  CommandLineConfig::strict_with_convenience(argc, argv);
  DebugHandler::install_sigsegv();
  DebugHandler::install_sigill();

  SeedGadget seed;
  FunctionsGadget aux_fxns;
  TargetGadget target(aux_fxns);

  TrainingSetGadget training_set(seed);
  SandboxGadget training_sb(training_set, aux_fxns);

  TransformsGadget transforms(target.get_code(), aux_fxns, seed);
  SearchGadget search(&transforms, seed);

  TestSetGadget test_set(seed);
  SandboxGadget test_sb(test_set, aux_fxns);
  CostFunctionGadget holdout_fxn(target, &test_sb);
  SolverGadget smt;
  ValidatorGadget validator(smt);
  VerifierGadget verifier(holdout_fxn, validator);

  if (!target.is_sound()) {
    Console::error(1) << "Target reads undefined variables, or leaves live_out undefined: " << target.which_undef_read() << endl;
  }

  ScbArg scb_arg {&Console::msg(), nullptr};
  search.set_progress_callback(pcb, &Console::msg())
  .set_statistics_callback(scb, &scb_arg)
  .set_statistics_interval(stat_int);

  size_t total_iterations = 0;
  size_t total_restarts = 0;

  string final_msg;
  SearchStateGadget state(target, aux_fxns);
  for (size_t i = 0; ; ++i) {
    CostFunctionGadget fxn(target, &training_sb);

    Console::msg() << "Running search:" << endl << endl;
    state = SearchStateGadget(target, aux_fxns);

    // Run the initial cost function
    // Used by statistics output and a sanity check
    auto initial_cost = fxn(state.current);
    if(!initial_cost.first && init_arg == Init::TARGET) {
      Console::warn() << "Initial state has non-zero correctness cost with --init target.";
    }
    starting_cost = initial_cost.second;
    lowest_cost = initial_cost.second;
    if(initial_cost.first) {
      lowest_correct = initial_cost.second;
    } else {
      lowest_correct = 0;
    }

    search.set_timeout_itr(timeout_itr_arg);
    const auto start_search = steady_clock::now();
    search.run(target, fxn, init_arg, state, aux_fxns);
    search_elapsed += duration_cast<duration<double>>(steady_clock::now() - start_search);

    total_iterations += search.get_statistics().iterations;
    total_restarts++;

    if (state.interrupted) {
      Console::msg() << endl;
      show_final_update(search.get_statistics(), state, total_restarts, total_iterations, start, search_elapsed);
      Console::msg() << "Search interrupted!" << endl;
      exit(1);
    }

    const auto verified = verifier.verify(target, state.best_correct);

    if(verifier.has_error()) {
      Console::msg() << "The verifier encountered an error:" << endl;
      Console::msg() << verifier.error() << endl;
    }

    if (!state.success) {
      Console::msg() << "Unable to discover a new correct rewrite before timing out... " << endl << endl;
    } else if (!verified) {
      Console::msg() << "Unable to verify new rewrite..." << endl << endl;
    } else {
      if (strategy_arg.value() == Strategy::NONE) {
        final_msg = "Search terminated successfully (but no verification was performed)!";
      } else {
        final_msg = "Search terminated successfully with a verified rewrite!";
      }
      break;
    }

    sep(Console::msg());

    if ((timeout_action_arg == Timeout::RESTART) && (i < timeout_cycles_arg.value())) {
      if (exp_scaling_arg.value() != 1.0) {
        timeout_itr_arg.value() = (size_t)ceil(timeout_itr_arg.value() * exp_scaling_arg.value());
        Console::msg() << "Increasing timeout iterations to " << timeout_itr_arg.value() << endl;
      }
      Console::msg() << "Restarting search:" << endl << endl;
    } else if ((timeout_action_arg == Timeout::TESTCASE) && (i < timeout_cycles_arg.value())
               && verifier.counter_example_available()) {
      Console::msg() << "Restarting search using new testcase:" << endl << endl;
      Console::msg() << verifier.get_counter_example() << endl << endl;
      training_sb.insert_input(verifier.get_counter_example());
    } else {
      show_final_update(search.get_statistics(), state, total_restarts, total_iterations, start, search_elapsed);
      Console::error(1) << "Search terminated unsuccessfully; unable to discover a new rewrite!" << endl;
    }
  }

  CfgTransforms tforms;
  if (postprocessing_arg == Postprocessing::FULL) {
    tforms.remove_redundant(state.best_correct);
    tforms.remove_unreachable(state.best_correct);
    tforms.remove_nop(state.best_correct);
  } else if (postprocessing_arg == Postprocessing::SIMPLE) {
    tforms.remove_unreachable(state.best_correct);
    tforms.remove_nop(state.best_correct);
  } else {
    // Do nothing.
  }

  auto final_stats = search.get_statistics();

  TUnit rewrite;
  rewrite.name = target_arg.value().name;
  rewrite.code = state.best_correct.get_code();

  show_final_update(final_stats, state, total_restarts, total_iterations, start, search_elapsed);
  Console::msg() << final_msg << endl;

  ofstream ofs(out.value());
  ofs << rewrite;

  return 0;
}
<|endoftext|>


<commit_before>#include "dreal/api/api.h"

#include <cmath>
#include <gtest/gtest.h>

#include "dreal/solver/formula_evaluator.h"

namespace dreal {
namespace {

class ApiTest : public ::testing::Test {
 protected:
  const Variable x_{"x", Variable::Type::CONTINUOUS};
  const Variable y_{"y", Variable::Type::CONTINUOUS};
  const Variable z_{"z", Variable::Type::CONTINUOUS};

  const Variable binary1_{"binary1", Variable::Type::BINARY};
  const Variable binary2_{"binary2", Variable::Type::BINARY};

  const Variable b1_{"b1", Variable::Type::BOOLEAN};
  const Variable b2_{"b2", Variable::Type::BOOLEAN};
};

::testing::AssertionResult CheckSolution(const Formula& f,
                                         const Box& solution) {
  FormulaEvaluator formula_evaluator{make_relational_formula_evaluator(f)};
  const FormulaEvaluationResult formula_evaluation_result{
      formula_evaluator(solution)};
  if (formula_evaluation_result.type() ==
      FormulaEvaluationResult::Type::UNSAT) {
    return ::testing::AssertionFailure() << "UNSAT detected!";
  }
  if (!formula_evaluation_result.evaluation().contains(0.0)) {
    return ::testing::AssertionFailure() << "The interval evaluation indicates "
                                            "that the solution does not "
                                            "satisfy the constraint.";
  }
  return ::testing::AssertionSuccess();
}

// Tests CheckSatisfiability (δ-SAT case).
TEST_F(ApiTest, CheckSatisfiabilityMixedBooleanAndContinuous) {
  const auto result = CheckSatisfiability(
      !b1_ && b2_ && (sin(x_) == 1) && x_ > 0 && x_ < 2 * 3.141592, 0.001);
  ASSERT_TRUE(result);
  EXPECT_EQ((*result)[b1_], 0.0);
  EXPECT_EQ((*result)[b2_], 1.0);
  EXPECT_NEAR(std::sin((*result)[x_].mid()), 1.0, 0.001);
}

TEST_F(ApiTest, CheckSatisfiabilityBinaryVariables1) {
  const Formula f{2 * binary1_ + 4 * binary2_ == 0};
  const auto result = CheckSatisfiability(f, 0.001);
  ASSERT_TRUE(result);
  const Box& solution{*result};
  EXPECT_EQ(solution[binary1_].mid(), 0.0);
  EXPECT_EQ(solution[binary2_].mid(), 0.0);
  EXPECT_EQ(solution[binary1_].diam(), 0.0);
  EXPECT_EQ(solution[binary2_].diam(), 0.0);
}

TEST_F(ApiTest, CheckSatisfiabilityBinaryVariables2) {
  const Formula f{binary1_ + binary2_ > 3};
  const auto result = CheckSatisfiability(f, 0.001);
  EXPECT_FALSE(result);
}

// Tests CheckSatisfiability (δ-SAT case).
TEST_F(ApiTest, CheckSatisfiabilityDeltaSat) {
  // 0 ≤ x ≤ 5
  // 0 ≤ y ≤ 5
  // 0 ≤ z ≤ 5
  // 2x + y = z
  const Formula f1{0 <= x_ && x_ <= 5};
  const Formula f2{0 <= y_ && y_ <= 5};
  const Formula f3{0 <= z_ && z_ <= 5};
  const Formula f4{2 * x_ + y_ == z_};

  // Checks the API returning an optional.
  {
    auto result = CheckSatisfiability(f1 && f2 && f3 && f4, 0.001);
    ASSERT_TRUE(result);
    EXPECT_TRUE(CheckSolution(f4, *result));
  }

  // Checks the API returning a bool.
  {
    Box b;
    const bool result{CheckSatisfiability(f1 && f2 && f3 && f4, 0.001, &b)};
    ASSERT_TRUE(result);
    EXPECT_TRUE(CheckSolution(f4, b));
  }
}

// Tests CheckSatisfiability (UNSAT case).
TEST_F(ApiTest, CheckSatisfiabilityUnsat) {
  // 2x² + 6x + 5 < 0
  // -10 ≤ x ≤ 10
  const Formula f1{2 * x_ * x_ + 6 * x_ + 5 < 0};
  const Formula f2{-10 <= x_ && x_ <= 10};

  // Checks the API returning an optional.
  {
    auto result = CheckSatisfiability(f1 && f2, 0.001);
    EXPECT_FALSE(result);
  }

  // Checks the API returning a bool.
  {
    Box b;
    const bool result{CheckSatisfiability(f1 && f2, 0.001, &b)};
    EXPECT_FALSE(result);
  }
}

TEST_F(ApiTest, Minimize1) {
  // minimize 2x² + 6x + 5 s.t. -4 ≤ x ≤ 0
  const Expression objective{2 * x_ * x_ + 6 * x_ + 5};
  const Formula constraint{-10 <= x_ && x_ <= 10};
  const double delta{0.01};
  const double known_minimum = 0.5;

  // Checks the API returning an optional.
  {
    const auto result = Minimize(objective, constraint, delta);
    ASSERT_TRUE(result);
    const double x = (*result)[x_].mid();
    EXPECT_TRUE(-10 <= x && x <= 10);
    EXPECT_LT(2 * x * x + 6 * x + 5, known_minimum + delta);
  }

  // Checks the API returning a bool.
  {
    Box b;
    const bool result = Minimize(objective, constraint, delta, &b);
    ASSERT_TRUE(result);
    const double x = b[x_].mid();
    EXPECT_TRUE(-10 <= x && x <= 10);
    EXPECT_LT(2 * x * x + 6 * x + 5, known_minimum + delta);
  }
}

TEST_F(ApiTest, Minimize2) {
  // minimize sin(3x) - 2cos(x) s.t. -3 ≤ x ≤ 3
  const Expression objective{sin(3 * x_) - 2 * cos(x_)};
  const Formula constraint{-3 <= x_ && x_ <= 3};
  const double delta{0.001};
  const double known_minimum = -2.77877;

  // Checks the API returning an optional.
  {
    const auto result = Minimize(objective, constraint, delta);
    ASSERT_TRUE(result);
    const double x = (*result)[x_].mid();
    EXPECT_TRUE(-3 <= x && x <= 3);
    EXPECT_LT(sin(3 * x) - 2 * cos(x), known_minimum + delta);
  }

  // Checks the API returning a bool.
  {
    Box b;
    const bool result = Minimize(objective, constraint, delta, &b);
    ASSERT_TRUE(result);
    const double x = b[x_].mid();
    EXPECT_TRUE(-3 <= x && x <= 3);
    EXPECT_LT(sin(3 * x) - 2 * cos(x), known_minimum + delta);
  }
}

TEST_F(ApiTest, CheckSatisfiabilityDisjunction) {
  const double delta{0.001};
  const Variable b1{"b1", Variable::Type::BOOLEAN};
  const Variable b2{"b2", Variable::Type::BOOLEAN};
  const Variable b3{"b3", Variable::Type::BOOLEAN};
  const auto result = CheckSatisfiability(b1 || !b2 || b3, delta);
  const Box& solution{*result};

  EXPECT_EQ(solution[b1].diam(), 0);
  EXPECT_EQ(solution[b2].diam(), 0);
  EXPECT_EQ(solution[b3].diam(), 0);

  const double v1{solution[b1].mid()};
  const double v2{solution[b2].mid()};
  const double v3{solution[b3].mid()};
  EXPECT_TRUE(v1 == 1.0 || v1 == 0.0);
  EXPECT_TRUE(v2 == 1.0 || v2 == 0.0);
  EXPECT_TRUE(v3 == 1.0 || v3 == 0.0);
  EXPECT_TRUE(v1 || !v2 || v3);
}

TEST_F(ApiTest, CheckSatisfiabilityIfThenElse1) {
  const double delta{0.001};
  const Formula f1{if_then_else(x_ > y_, x_, y_) == z_};
  const Formula f2{x_ == 100};
  const Formula f3{y_ == 50};
  const auto result = CheckSatisfiability(f1 && f2 && f3, delta);
  ASSERT_TRUE(result);
  const Box& solution{*result};
  EXPECT_EQ(solution[z_].mid(), 100);
}

TEST_F(ApiTest, CheckSatisfiabilityIfThenElse2) {
  const double delta{0.001};
  const Formula f1{if_then_else(x_ > y_, x_, y_) == z_};
  const Formula f2{x_ == 50};
  const Formula f3{y_ == 100};
  const auto result = CheckSatisfiability(f1 && f2 && f3, delta);
  ASSERT_TRUE(result);
  const Box& solution{*result};
  EXPECT_EQ(solution[z_].mid(), 100);
}

}  // namespace
}  // namespace dreal
<commit_msg>test(api): Add more checks<commit_after>#include "dreal/api/api.h"

#include <cmath>
#include <gtest/gtest.h>

#include "dreal/solver/formula_evaluator.h"

namespace dreal {
namespace {

class ApiTest : public ::testing::Test {
 protected:
  const Variable x_{"x", Variable::Type::CONTINUOUS};
  const Variable y_{"y", Variable::Type::CONTINUOUS};
  const Variable z_{"z", Variable::Type::CONTINUOUS};

  const Variable binary1_{"binary1", Variable::Type::BINARY};
  const Variable binary2_{"binary2", Variable::Type::BINARY};

  const Variable b1_{"b1", Variable::Type::BOOLEAN};
  const Variable b2_{"b2", Variable::Type::BOOLEAN};
};

::testing::AssertionResult CheckSolution(const Formula& f,
                                         const Box& solution) {
  FormulaEvaluator formula_evaluator{make_relational_formula_evaluator(f)};
  const FormulaEvaluationResult formula_evaluation_result{
      formula_evaluator(solution)};
  if (formula_evaluation_result.type() ==
      FormulaEvaluationResult::Type::UNSAT) {
    return ::testing::AssertionFailure() << "UNSAT detected!";
  }
  if (!formula_evaluation_result.evaluation().contains(0.0)) {
    return ::testing::AssertionFailure() << "The interval evaluation indicates "
                                            "that the solution does not "
                                            "satisfy the constraint.";
  }
  return ::testing::AssertionSuccess();
}

// Tests CheckSatisfiability (δ-SAT case).
TEST_F(ApiTest, CheckSatisfiabilityMixedBooleanAndContinuous) {
  const auto result = CheckSatisfiability(
      !b1_ && b2_ && (sin(x_) == 1) && x_ > 0 && x_ < 2 * 3.141592, 0.001);
  ASSERT_TRUE(result);
  EXPECT_EQ((*result)[b1_], 0.0);
  EXPECT_EQ((*result)[b2_], 1.0);
  EXPECT_NEAR(std::sin((*result)[x_].mid()), 1.0, 0.001);
}

TEST_F(ApiTest, CheckSatisfiabilityBinaryVariables1) {
  const Formula f{2 * binary1_ + 4 * binary2_ == 0};
  const auto result = CheckSatisfiability(f, 0.001);
  ASSERT_TRUE(result);
  const Box& solution{*result};
  EXPECT_EQ(solution[binary1_].mid(), 0.0);
  EXPECT_EQ(solution[binary2_].mid(), 0.0);
  EXPECT_EQ(solution[binary1_].diam(), 0.0);
  EXPECT_EQ(solution[binary2_].diam(), 0.0);
}

TEST_F(ApiTest, CheckSatisfiabilityBinaryVariables2) {
  const Formula f{binary1_ + binary2_ > 3};
  const auto result = CheckSatisfiability(f, 0.001);
  EXPECT_FALSE(result);
}

// Tests CheckSatisfiability (δ-SAT case).
TEST_F(ApiTest, CheckSatisfiabilityDeltaSat) {
  // 0 ≤ x ≤ 5
  // 0 ≤ y ≤ 5
  // 0 ≤ z ≤ 5
  // 2x + y = z
  const Formula f1{0 <= x_ && x_ <= 5};
  const Formula f2{0 <= y_ && y_ <= 5};
  const Formula f3{0 <= z_ && z_ <= 5};
  const Formula f4{2 * x_ + y_ == z_};

  // Checks the API returning an optional.
  {
    auto result = CheckSatisfiability(f1 && f2 && f3 && f4, 0.001);
    ASSERT_TRUE(result);
    EXPECT_TRUE(CheckSolution(f4, *result));
  }

  // Checks the API returning a bool.
  {
    Box b;
    const bool result{CheckSatisfiability(f1 && f2 && f3 && f4, 0.001, &b)};
    ASSERT_TRUE(result);
    EXPECT_TRUE(CheckSolution(f4, b));
  }
}

// Tests CheckSatisfiability (UNSAT case).
TEST_F(ApiTest, CheckSatisfiabilityUnsat) {
  // 2x² + 6x + 5 < 0
  // -10 ≤ x ≤ 10
  const Formula f1{2 * x_ * x_ + 6 * x_ + 5 < 0};
  const Formula f2{-10 <= x_ && x_ <= 10};

  // Checks the API returning an optional.
  {
    auto result = CheckSatisfiability(f1 && f2, 0.001);
    EXPECT_FALSE(result);
  }

  // Checks the API returning a bool.
  {
    Box b;
    const bool result{CheckSatisfiability(f1 && f2, 0.001, &b)};
    EXPECT_FALSE(result);
  }
}

TEST_F(ApiTest, Minimize1) {
  // minimize 2x² + 6x + 5 s.t. -4 ≤ x ≤ 0
  const Expression objective{2 * x_ * x_ + 6 * x_ + 5};
  const Formula constraint{-10 <= x_ && x_ <= 10};
  const double delta{0.01};
  const double known_minimum = 0.5;

  // Checks the API returning an optional.
  {
    const auto result = Minimize(objective, constraint, delta);
    ASSERT_TRUE(result);
    const double x = (*result)[x_].mid();
    EXPECT_TRUE(-10 <= x && x <= 10);
    EXPECT_LT(2 * x * x + 6 * x + 5, known_minimum + delta);
  }

  // Checks the API returning a bool.
  {
    Box b;
    const bool result = Minimize(objective, constraint, delta, &b);
    ASSERT_TRUE(result);
    const double x = b[x_].mid();
    EXPECT_TRUE(-10 <= x && x <= 10);
    EXPECT_LT(2 * x * x + 6 * x + 5, known_minimum + delta);
  }
}

TEST_F(ApiTest, Minimize2) {
  // minimize sin(3x) - 2cos(x) s.t. -3 ≤ x ≤ 3
  const Expression objective{sin(3 * x_) - 2 * cos(x_)};
  const Formula constraint{-3 <= x_ && x_ <= 3};
  const double delta{0.001};
  const double known_minimum = -2.77877;

  // Checks the API returning an optional.
  {
    const auto result = Minimize(objective, constraint, delta);
    ASSERT_TRUE(result);
    const double x = (*result)[x_].mid();
    EXPECT_TRUE(-3 <= x && x <= 3);
    EXPECT_LT(sin(3 * x) - 2 * cos(x), known_minimum + delta);
  }

  // Checks the API returning a bool.
  {
    Box b;
    const bool result = Minimize(objective, constraint, delta, &b);
    ASSERT_TRUE(result);
    const double x = b[x_].mid();
    EXPECT_TRUE(-3 <= x && x <= 3);
    EXPECT_LT(sin(3 * x) - 2 * cos(x), known_minimum + delta);
  }
}

TEST_F(ApiTest, CheckSatisfiabilityDisjunction) {
  const double delta{0.001};
  const Variable b1{"b1", Variable::Type::BOOLEAN};
  const Variable b2{"b2", Variable::Type::BOOLEAN};
  const Variable b3{"b3", Variable::Type::BOOLEAN};
  const auto result = CheckSatisfiability(b1 || !b2 || b3, delta);
  const Box& solution{*result};

  EXPECT_EQ(solution[b1].diam(), 0);
  EXPECT_EQ(solution[b2].diam(), 0);
  EXPECT_EQ(solution[b3].diam(), 0);

  const double v1{solution[b1].mid()};
  const double v2{solution[b2].mid()};
  const double v3{solution[b3].mid()};
  EXPECT_TRUE(v1 == 1.0 || v1 == 0.0);
  EXPECT_TRUE(v2 == 1.0 || v2 == 0.0);
  EXPECT_TRUE(v3 == 1.0 || v3 == 0.0);
  EXPECT_TRUE(v1 || !v2 || v3);
}

TEST_F(ApiTest, CheckSatisfiabilityIfThenElse1) {
  const double delta{0.001};
  const Formula f1{if_then_else(x_ > y_, x_, y_) == z_};
  const Formula f2{x_ == 100};
  const Formula f3{y_ == 50};
  const auto result = CheckSatisfiability(f1 && f2 && f3, delta);
  ASSERT_TRUE(result);
  const Box& solution{*result};
  EXPECT_EQ(solution[z_].mid(), 100);
  EXPECT_EQ(solution.size(), 3);
}

TEST_F(ApiTest, CheckSatisfiabilityIfThenElse2) {
  const double delta{0.001};
  const Formula f1{if_then_else(x_ > y_, x_, y_) == z_};
  const Formula f2{x_ == 50};
  const Formula f3{y_ == 100};
  const auto result = CheckSatisfiability(f1 && f2 && f3, delta);
  ASSERT_TRUE(result);
  const Box& solution{*result};
  EXPECT_EQ(solution[z_].mid(), 100);
  EXPECT_EQ(solution.size(), 3);
}

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


<commit_before>/**
 * 7.1 定义抽象数据类型
 * @Author Bob
 * @Eamil 0haizhu0@gmail.com
 * @Date 2017/8/15
 */
int main(){
  /**
   * 数据抽象依赖于接口和实现分离的编程技术。
   */
  return 0;
}
<commit_msg>7.1 定义抽象数据类型<commit_after>/**
 * 7.1 定义抽象数据类型
 * @Author Bob
 * @Eamil 0haizhu0@gmail.com
 * @Date 2017/8/15
 */
int main(){
  /**
   * 数据抽象依赖于接口和实现分离的编程技术。
   *
   * 在第一章中的Sales_item类是一个抽象数据类型，我们通过它的接口来使用Sales_item对象。我们不能访问它的数据成员。事实上，
   * 我们甚至不知道这个类有哪些数据成员。
   *
   * 与之相反，Sales_data类不是一个抽象数据类型。它允许类的用户直接访问它的数据成员，并且要求由用户来编写操作。要想把Sales_data
   * 变成抽象数据类型，我们需要定义一些操作以供类的用户使用。一旦Sales_data定义了它自己的操作，我们就可以封装(隐藏)它的数据成员了。
   */
  return 0;
}
<|endoftext|>


<commit_before>/*
  Copyright (c) 2011, The Mineserver Project
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:
  * Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
  * Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
  * Neither the name of the The Mineserver Project nor the
    names of its contributors may be used to endorse or promote products
    derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <string>
#include <cstring>
#include <errno.h>
#include <vector>

#include <mineserver/byteorder.h>
#include <mineserver/network/protocol/notch/packetstream.h>

void Mineserver::Network_Protocol_Notch_PacketStream::bytesFrom(const uint8_t* src, size_t n)
{
	m_buffer->insert(m_buffer->end(), src, src+n);
}

void Mineserver::Network_Protocol_Notch_PacketStream::bytesFrom(const std::vector<uint8_t> src)
{
  m_buffer->insert(m_buffer->end(), src.begin(), src.end());
}

void Mineserver::Network_Protocol_Notch_PacketStream::bytesTo(uint8_t* dst, size_t n)
{
  memcpy(dst, reinterpret_cast<uint8_t*>(&((*m_buffer)[m_pos])), n);
  m_pos += n;
}

void Mineserver::Network_Protocol_Notch_PacketStream::bytesTo(std::vector<uint8_t> dst)
{
  dst.insert(dst.end(), m_buffer->begin()+m_pos, m_buffer->end());
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(bool val)
{
  m_buffer->push_back(val ? 1 : 0);

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(bool& val)
{
  if (haveData(1))
  {
    val = ((*m_buffer)[m_pos++] != 0);
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(int8_t val)
{
  m_buffer->push_back(val);

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(int8_t& val)
{
  if (haveData(1))
  {
    val = (*m_buffer)[m_pos++];
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(uint8_t val)
{
  m_buffer->push_back(val);

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(uint8_t& val)
{
  if (haveData(1))
  {
    val = (*m_buffer)[m_pos++];
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(int16_t val)
{
  int16_t nval = htobe16(val);

  append(reinterpret_cast<const uint8_t*>(&nval), sizeof(nval));

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(int16_t& val)
{
  if (haveData(2))
  {
    val = betoh16(*(reinterpret_cast<int16_t*>(&((*m_buffer)[m_pos]))));
    m_pos += 2;
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(uint16_t val)
{
  uint16_t nval = htobe16(val);

  append(reinterpret_cast<const uint8_t*>(&nval), sizeof(nval));

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(uint16_t& val)
{
  if (haveData(2))
  {
    val = betoh16(*(reinterpret_cast<uint16_t*>(&((*m_buffer)[m_pos]))));
    m_pos += 2;
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(int32_t val)
{
  int32_t nval = htobe32(val);

  append(reinterpret_cast<const uint8_t*>(&nval), sizeof(nval));

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(int32_t& val)
{
  if (haveData(4))
  {
    val = betoh32(*(reinterpret_cast<int32_t*>(&((*m_buffer)[m_pos]))));
    m_pos += 4;
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(uint32_t val)
{
  uint32_t nval = htobe32(val);

  append(reinterpret_cast<const uint8_t*>(&nval), sizeof(nval));

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(uint32_t& val)
{
  if (haveData(4))
  {
    val = betoh32(*(reinterpret_cast<uint32_t*>(&((*m_buffer)[m_pos]))));
    m_pos += 4;
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(int64_t val)
{
  int64_t nval = htobe64(val);

  append(reinterpret_cast<const uint8_t*>(&nval), sizeof(nval));

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(int64_t& val)
{
  if (haveData(8))
  {
    val = betoh64(*(reinterpret_cast<int64_t*>(&((*m_buffer)[m_pos]))));
    m_pos += 8;
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(uint64_t val)
{
  uint64_t nval = htobe64(val);

  append(reinterpret_cast<const uint8_t*>(&nval), sizeof(nval));

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(uint64_t& val)
{
  if (haveData(8))
  {
    val = betoh64(*(reinterpret_cast<uint64_t*>(&((*m_buffer)[m_pos]))));
    m_pos += 8;
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(float val)
{
  uint32_t nval;

  memcpy(&nval, &val, 4);
  nval = htobe32(nval);
  append(reinterpret_cast<const uint8_t*>(&nval), sizeof(nval));

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(float& val)
{
  if (haveData(4))
  {
    uint32_t res;
    uint8_t* p = reinterpret_cast<uint8_t*>(&res);

    for (size_t i = 0; i < sizeof(res); ++i)
    {
      *p++ = (*m_buffer)[m_pos++];
    }

    uint32_t ival = betoh32(res);
    memcpy(&val, &ival, 4);

    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(double val)
{
  uint64_t nval;

  memcpy(&nval, &val, 8);
  nval = betoh64(nval);
  append(reinterpret_cast<const uint8_t*>(&nval), sizeof(nval));

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(double& val)
{
  if (haveData(8))
  {
    uint64_t res;
    uint8_t* p = reinterpret_cast<uint8_t*>(&res);

    for (size_t i = 0; i < sizeof(res); ++i)
    {
      *p++ = (*m_buffer)[m_pos++];
    }

    uint64_t ival = betoh64(res);
    memcpy(&val, &ival, 8);

    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(const std::string& str)
{
  char *dst, *dst_c;
  size_t src_s, src_l, dst_s, dst_l;

  src_s = src_l = str.size();
  dst_s = dst_l = str.size()*2;

  char* src_c = const_cast<char*>(str.c_str());
  dst = dst_c = new char[dst_s];

  memset(dst, 0, dst_s);

  size_t rc = iconv(m_iconvUtfHandler, &src_c, &src_l, &dst_c, &dst_l);

  // Should be handling these errors
  if (rc == -1) {
    switch (errno) {
    case E2BIG:
      break;
    case EILSEQ:
      break;
    case EINVAL:
      break;
    default:
      break;
    }
  }

  size_t result_b = dst_s-dst_l;
  size_t result_c = result_b/2;

  result_c = htobe16(result_c);

  append(reinterpret_cast<const uint8_t*>(&result_c), 2);
  append(reinterpret_cast<const uint8_t*>(dst), result_b);

  delete[] dst;

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(std::string& str)
{
  int16_t len;

  if (haveData(2))
  {
    len = betoh16(*(reinterpret_cast<int16_t*>(&((*m_buffer)[m_pos]))));
    m_pos += 2;
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  if (haveData(len * 2))
  {
    char *dst, *dst_c;
    size_t src_s, src_l, dst_s, dst_l;

    src_s = src_l = len * 2;
    dst_s = dst_l = len;

    char* src_c = reinterpret_cast<char*>(&((*m_buffer)[m_pos]));
    dst = dst_c = new char[dst_s];

    size_t rc = iconv(m_iconvUcsHandler, &src_c, &src_l, &dst_c, &dst_l);

    // Should be handling these errors
    if (rc == -1) {
      switch (errno) {
      case E2BIG:
        break;
      case EILSEQ:
        break;
      case EINVAL:
        break;
      default:
        break;
      }
    }

    str.assign(dst, dst_s);

    delete[] dst;

    m_pos += len * 2;

    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}
<commit_msg>fixed a couple of warnings in Network_Protocol_Notch_PacketStream<commit_after>/*
  Copyright (c) 2011, The Mineserver Project
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:
  * Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
  * Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
  * Neither the name of the The Mineserver Project nor the
    names of its contributors may be used to endorse or promote products
    derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <string>
#include <cstring>
#include <errno.h>
#include <vector>

#include <mineserver/byteorder.h>
#include <mineserver/network/protocol/notch/packetstream.h>

void Mineserver::Network_Protocol_Notch_PacketStream::bytesFrom(const uint8_t* src, size_t n)
{
	m_buffer->insert(m_buffer->end(), src, src+n);
}

void Mineserver::Network_Protocol_Notch_PacketStream::bytesFrom(const std::vector<uint8_t> src)
{
  m_buffer->insert(m_buffer->end(), src.begin(), src.end());
}

void Mineserver::Network_Protocol_Notch_PacketStream::bytesTo(uint8_t* dst, size_t n)
{
  memcpy(dst, reinterpret_cast<uint8_t*>(&((*m_buffer)[m_pos])), n);
  m_pos += n;
}

void Mineserver::Network_Protocol_Notch_PacketStream::bytesTo(std::vector<uint8_t> dst)
{
  dst.insert(dst.end(), m_buffer->begin()+m_pos, m_buffer->end());
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(bool val)
{
  m_buffer->push_back(val ? 1 : 0);

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(bool& val)
{
  if (haveData(1))
  {
    val = ((*m_buffer)[m_pos++] != 0);
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(int8_t val)
{
  m_buffer->push_back(val);

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(int8_t& val)
{
  if (haveData(1))
  {
    val = (*m_buffer)[m_pos++];
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(uint8_t val)
{
  m_buffer->push_back(val);

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(uint8_t& val)
{
  if (haveData(1))
  {
    val = (*m_buffer)[m_pos++];
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(int16_t val)
{
  int16_t nval = htobe16(val);

  append(reinterpret_cast<const uint8_t*>(&nval), sizeof(nval));

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(int16_t& val)
{
  if (haveData(2))
  {
    val = betoh16(*(reinterpret_cast<int16_t*>(&((*m_buffer)[m_pos]))));
    m_pos += 2;
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(uint16_t val)
{
  uint16_t nval = htobe16(val);

  append(reinterpret_cast<const uint8_t*>(&nval), sizeof(nval));

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(uint16_t& val)
{
  if (haveData(2))
  {
    val = betoh16(*(reinterpret_cast<uint16_t*>(&((*m_buffer)[m_pos]))));
    m_pos += 2;
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(int32_t val)
{
  int32_t nval = htobe32(val);

  append(reinterpret_cast<const uint8_t*>(&nval), sizeof(nval));

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(int32_t& val)
{
  if (haveData(4))
  {
    val = betoh32(*(reinterpret_cast<int32_t*>(&((*m_buffer)[m_pos]))));
    m_pos += 4;
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(uint32_t val)
{
  uint32_t nval = htobe32(val);

  append(reinterpret_cast<const uint8_t*>(&nval), sizeof(nval));

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(uint32_t& val)
{
  if (haveData(4))
  {
    val = betoh32(*(reinterpret_cast<uint32_t*>(&((*m_buffer)[m_pos]))));
    m_pos += 4;
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(int64_t val)
{
  int64_t nval = htobe64(val);

  append(reinterpret_cast<const uint8_t*>(&nval), sizeof(nval));

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(int64_t& val)
{
  if (haveData(8))
  {
    val = betoh64(*(reinterpret_cast<int64_t*>(&((*m_buffer)[m_pos]))));
    m_pos += 8;
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(uint64_t val)
{
  uint64_t nval = htobe64(val);

  append(reinterpret_cast<const uint8_t*>(&nval), sizeof(nval));

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(uint64_t& val)
{
  if (haveData(8))
  {
    val = betoh64(*(reinterpret_cast<uint64_t*>(&((*m_buffer)[m_pos]))));
    m_pos += 8;
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(float val)
{
  uint32_t nval;

  memcpy(&nval, &val, 4);
  nval = htobe32(nval);
  append(reinterpret_cast<const uint8_t*>(&nval), sizeof(nval));

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(float& val)
{
  if (haveData(4))
  {
    uint32_t res;
    uint8_t* p = reinterpret_cast<uint8_t*>(&res);

    for (size_t i = 0; i < sizeof(res); ++i)
    {
      *p++ = (*m_buffer)[m_pos++];
    }

    uint32_t ival = betoh32(res);
    memcpy(&val, &ival, 4);

    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(double val)
{
  uint64_t nval;

  memcpy(&nval, &val, 8);
  nval = betoh64(nval);
  append(reinterpret_cast<const uint8_t*>(&nval), sizeof(nval));

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(double& val)
{
  if (haveData(8))
  {
    uint64_t res;
    uint8_t* p = reinterpret_cast<uint8_t*>(&res);

    for (size_t i = 0; i < sizeof(res); ++i)
    {
      *p++ = (*m_buffer)[m_pos++];
    }

    uint64_t ival = betoh64(res);
    memcpy(&val, &ival, 8);

    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator<<(const std::string& str)
{
  char *dst, *dst_c;
  size_t src_s, src_l, dst_s, dst_l;

  src_s = src_l = str.size();
  dst_s = dst_l = str.size()*2;

  char* src_c = const_cast<char*>(str.c_str());
  dst = dst_c = new char[dst_s];

  memset(dst, 0, dst_s);

  size_t rc = iconv(m_iconvUtfHandler, &src_c, &src_l, &dst_c, &dst_l);

  // Should be handling these errors
  if (static_cast<int>(rc) == -1) {
    switch (errno) {
    case E2BIG:
      break;
    case EILSEQ:
      break;
    case EINVAL:
      break;
    default:
      break;
    }
  }

  size_t result_b = dst_s-dst_l;
  size_t result_c = result_b/2;

  result_c = htobe16(result_c);

  append(reinterpret_cast<const uint8_t*>(&result_c), 2);
  append(reinterpret_cast<const uint8_t*>(dst), result_b);

  delete[] dst;

  return *this;
}

Mineserver::Network_Protocol_Notch_PacketStream& Mineserver::Network_Protocol_Notch_PacketStream::operator>>(std::string& str)
{
  int16_t len;

  if (haveData(2))
  {
    len = betoh16(*(reinterpret_cast<int16_t*>(&((*m_buffer)[m_pos]))));
    m_pos += 2;
    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  if (haveData(len * 2))
  {
    char *dst, *dst_c;
    size_t src_s, src_l, dst_s, dst_l;

    src_s = src_l = len * 2;
    dst_s = dst_l = len;

    char* src_c = reinterpret_cast<char*>(&((*m_buffer)[m_pos]));
    dst = dst_c = new char[dst_s];

    size_t rc = iconv(m_iconvUcsHandler, &src_c, &src_l, &dst_c, &dst_l);

    // Should be handling these errors
    if (static_cast<int>(rc) == -1) {
      switch (errno) {
      case E2BIG:
        break;
      case EILSEQ:
        break;
      case EINVAL:
        break;
      default:
        break;
      }
    }

    str.assign(dst, dst_s);

    delete[] dst;

    m_pos += len * 2;

    m_valid = true;
  }
  else
  {
    m_valid = false;
  }

  return *this;
}
<|endoftext|>