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

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "PropertyViewTestWidget.h"

#include <QmitkBasePropertyView.h>
#include <QmitkBoolPropertyView.h>
#include <QmitkBoolPropertyEditor.h>
#include <QmitkStringPropertyView.h>
#include <QmitkStringPropertyEditor.h>
#include <QmitkColorPropertyView.h>
#include <QmitkColorPropertyEditor.h>
#include <QmitkNumberPropertyView.h>
#include <QmitkNumberPropertyEditor.h>

#include <QmitkDataTreeListView.h>
#include <QmitkDataTreeComboBox.h>

#include <mitkImage.h>

#include <assert.h>
#include <qlayout.h>
#include <qapplication.h>

#include <qlistview.h>

PropertyViewTest::PropertyViewTest(bool stay, QWidget* parent, const char* name)
:QWidget(parent,name),
 m_Stay(stay)
{
/**/
  QHBoxLayout* hl = new QHBoxLayout(this, QBoxLayout::LeftToRight);
  QVBoxLayout* vl = new QVBoxLayout(hl, QBoxLayout::TopToBottom);

  // string property
  propstring = new mitk::StringProperty("Juhu");

  // base property view for the string
  baseview = new QmitkBasePropertyView( propstring, this );
  vl->addWidget(baseview);

  // string property view for the string
  stringview = new QmitkStringPropertyView( propstring, this );
  vl->addWidget(stringview);

  // string property editor for the string
  stringeditor = new QmitkStringPropertyEditor( propstring, this );
  vl->addWidget(stringeditor);

  // color property
  propcolor = new mitk::ColorProperty(0.5, 1.0, 0.25);

  // color prop editor
  coloreditor = new QmitkColorPropertyEditor( propcolor, this );
  vl->addWidget(coloreditor);

  // bool property
  propbool = new mitk::BoolProperty(true);

  // bool prop view
  boolview = new QmitkBoolPropertyView( propbool, this );
  vl->addWidget(boolview);

  // bool prop editor
  booleditor = new QmitkBoolPropertyEditor( propbool, this );
  vl->addWidget(booleditor);

  //propshort = new mitk::GenericProperty<short>(3);  // see comment below
  propint = new mitk::IntProperty(4);
  propfloat = new mitk::FloatProperty(4.5);
  propdouble = new mitk::DoubleProperty(4.75);

  // not possible because lack of: bool mitk::XMLReader::GetAttribute(std::basic_str, short int&)
  // this is nedded in DataStructures/mitkProperties/mitkGenericProperty.h, l. 86
  //numberview = new QmitkNumberPropertyView( propshort, this );
  //vl->addWidget(numberview);

  numberview1 = new QmitkNumberPropertyView( propint, this );
  numberview1->setDecimalPlaces(4);
  vl->addWidget(numberview1);
  numbereditor1 = new QmitkNumberPropertyEditor( propint, this );
  numbereditor1->setDecimalPlaces(4);
  vl->addWidget(numbereditor1);

  numberview2 = new QmitkNumberPropertyView( propfloat, this );
  numberview2->setDecimalPlaces(3);
  vl->addWidget(numberview2);
  numbereditor2 = new QmitkNumberPropertyEditor( propfloat, this );
  numbereditor2->setDecimalPlaces(3);
  vl->addWidget(numbereditor2);
  numbereditor3 = new QmitkNumberPropertyEditor( propfloat, this );
  numbereditor3->setDecimalPlaces(2);
  vl->addWidget(numbereditor3);
  numbereditor4 = new QmitkNumberPropertyEditor( propfloat, this );
  vl->addWidget(numbereditor4);
  numberview3 = new QmitkNumberPropertyView( propfloat, this );
  numberview3->setDecimalPlaces(2);
  vl->addWidget(numberview3);

  numberview4 = new QmitkNumberPropertyView( propdouble, this );
  vl->addWidget(numberview4);
  numbereditor5 = new QmitkNumberPropertyEditor( propdouble, this );
  numbereditor5->setDecimalPlaces(4);
  vl->addWidget(numbereditor5);
  numbereditor6 = new QmitkNumberPropertyEditor( propdouble, this );
  vl->addWidget(numbereditor6);

  // percents
  propfloat2 = new mitk::FloatProperty(0.43);
  numberview5 = new QmitkNumberPropertyView( propfloat2, this );
  vl->addWidget(numberview5);

  numbereditor7 = new QmitkNumberPropertyEditor( propfloat2, this );
  numbereditor7->setShowPercent(true);
  vl->addWidget(numbereditor7);
  numbereditor8 = new QmitkNumberPropertyEditor( propfloat2, this );
  numbereditor8->setShowPercent(true);
  numbereditor8->setDecimalPlaces(1);
  vl->addWidget(numbereditor8);
/**/
  prepare_tree();

//QVBoxLayout* vlright = new QVBoxLayout(this, QBoxLayout::TopToBottom);

  treelistview = new QmitkDataTreeListView(tree_filter, this);
  // alternative constructor, will create default filter
  //treelistview = new QmitkDataTreeListView(data_tree, this);
  treelistview->setStretchedColumn(2);

//vlright->addWidget(treelistview);

/**/
  QVBoxLayout* vlright = new QVBoxLayout(hl, QBoxLayout::TopToBottom);
  //hl->addWidget( vlright );

  vlright->addWidget( treelistview );

  // color prop view
  colorview = new QmitkColorPropertyView( propcolor, this );
  //vlright->addWidget(colorview, 10);
  vlright->addWidget(colorview);

  treecombobox = new QmitkDataTreeComboBox(tree_filter, this);
  vlright->addWidget( treecombobox );

  // finally, a timer that starts some testing
  timer = new QTimer(this);
  connect ( timer, SIGNAL(timeout()), this, SLOT(run()) );
  timer->start(0, TRUE);
/**/
}

void PropertyViewTest::prepare_tree()
{
  data_tree = mitk::DataTree::New();
  // create some test data
  mitk::Image::Pointer image;
  mitk::PixelType pt(typeid(int));
  unsigned int dim[]={10,10,20}; // image dimensions

  image = mitk::Image::New();
  image->Initialize(mitk::PixelType(typeid(int)), 3, dim);
  int *p = (int*)image->GetData(); // pointer to pixel data
  int size = dim[0]*dim[1]*dim[2];
  for(int i=0; i<size; ++i, ++p) *p=i; // fill image

  {
    mitk::DataTreeNode::Pointer node = mitk::DataTreeNode::New();
    node->SetData(image);
  }

  mitk::DataTreePreOrderIterator it(data_tree);
/**/
  {
    mitk::DataTreeNode::Pointer node = mitk::DataTreeNode::New(); node->SetData(image);
    node->SetProperty("name", new mitk::StringProperty("Opa"));
//    node->SetProperty("opacity", new mitk::FloatProperty(0.8));
    it.Set(node);
  }
/**/
  {
    mitk::DataTreeNode::Pointer node = mitk::DataTreeNode::New(); node->SetData(image);
    node->SetProperty("name", new mitk::StringProperty("Bruder"));
    node->SetProperty("visible", new mitk::BoolProperty(false));
    node->SetProperty("opacity", new mitk::FloatProperty(0.8));
    it.Add(node);
  }
  {
    mitk::DataTreeNode::Pointer node = mitk::DataTreeNode::New(); node->SetData(image);
    node->SetProperty("name", new mitk::StringProperty("Ich"));
    node->SetProperty("opacity", new mitk::FloatProperty(0.8));
    it.Add(node);
  }
  {
    mitk::DataTreeNode::Pointer node = mitk::DataTreeNode::New(); node->SetData(image);
    node->SetProperty("name", new mitk::StringProperty("Schwester"));
    node->SetProperty("opacity", new mitk::FloatProperty(0.8));
    it.Add(node);
  }

  it.GoToChild(1);

  {
    mitk::DataTreeNode::Pointer node = mitk::DataTreeNode::New(); node->SetData(image);
    node->SetProperty("name", new mitk::StringProperty("Sohn"));
//    node->SetProperty("opacity", new mitk::FloatProperty(0.8));
    it.Add(node);
  }
  {
    mitk::DataTreeNode::Pointer node = mitk::DataTreeNode::New(); node->SetData(image);
    node->SetProperty("name", new mitk::StringProperty("Tochter"));
    node->SetProperty("visible", new mitk::BoolProperty(false));
    node->SetProperty("opacity", new mitk::FloatProperty(0.8));
    it.Add(node);
  }

  mitk::DataTreeFilter::PropertyList visible_props;
  visible_props.push_back("visible");
  visible_props.push_back("name");
  visible_props.push_back("opacity");
  mitk::DataTreeFilter::PropertyList editable_props;
  editable_props.push_back("visible");
//  editable_props.push_back("name");
  editable_props.push_back("opacity");

  tree_filter = mitk::DataTreeFilter::New(data_tree);
  tree_filter->SetSelectionMode(mitk::DataTreeFilter::SINGLE_SELECT);
  tree_filter->SetFilter(&mitk::IsGoodDataTreeNode);
  tree_filter->SetVisibleProperties(visible_props);
  tree_filter->SetEditableProperties(editable_props);

}

PropertyViewTest::~PropertyViewTest()
{
  delete timer;

  delete colorview;
  delete coloreditor;
  delete stringeditor;
  delete stringview;
  delete booleditor;
  delete boolview;
  delete baseview;

  delete numberview1;
  delete numberview2;
  delete numberview3;
  delete numberview4;
  delete numberview5;
  delete numbereditor1;
  delete numbereditor2;
  delete numbereditor3;
  delete numbereditor4;
  delete numbereditor5;
  delete numbereditor6;
  delete numbereditor7;
  delete numbereditor8;

  delete propstring;
  delete propcolor;
  delete propbool;
  delete propfloat;
  delete propfloat2;

  delete treelistview;
  delete treecombobox;

  tree_filter = 0;
  data_tree = 0;
}

void PropertyViewTest::run()
{
    assert( baseview->text() == "Juhu" );
    assert( stringview->text() == "Juhu" );
    assert( stringeditor->text() == "Juhu" );

    propstring->SetValue("Huhu Welt");
    assert( baseview->text() == "Huhu Welt" );
    assert( stringview->text() == "Huhu Welt" );
    assert( stringeditor->text() == "Huhu Welt" );

    assert( boolview->isOn() );
    assert( booleditor->isOn() );

    propbool->SetValue(false);
    assert( !boolview->isOn() );
    assert( !booleditor->isOn() );

  if (!m_Stay)
    qApp->quit();
}

<commit_msg>different test case, nice to see sync betw. combobox and listview with single selection<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "PropertyViewTestWidget.h"

#include <QmitkBasePropertyView.h>
#include <QmitkBoolPropertyView.h>
#include <QmitkBoolPropertyEditor.h>
#include <QmitkStringPropertyView.h>
#include <QmitkStringPropertyEditor.h>
#include <QmitkColorPropertyView.h>
#include <QmitkColorPropertyEditor.h>
#include <QmitkNumberPropertyView.h>
#include <QmitkNumberPropertyEditor.h>

#include <QmitkDataTreeListView.h>
#include <QmitkDataTreeComboBox.h>

#include <mitkImage.h>

#include <assert.h>
#include <qlayout.h>
#include <qapplication.h>

#include <qlistview.h>

PropertyViewTest::PropertyViewTest(bool stay, QWidget* parent, const char* name)
:QWidget(parent,name),
 m_Stay(stay)
{
/**/
  QHBoxLayout* hl = new QHBoxLayout(this, QBoxLayout::LeftToRight);
  QVBoxLayout* vl = new QVBoxLayout(hl, QBoxLayout::TopToBottom);

  // string property
  propstring = new mitk::StringProperty("Juhu");

  // base property view for the string
  baseview = new QmitkBasePropertyView( propstring, this );
  vl->addWidget(baseview);

  // string property view for the string
  stringview = new QmitkStringPropertyView( propstring, this );
  vl->addWidget(stringview);

  // string property editor for the string
  stringeditor = new QmitkStringPropertyEditor( propstring, this );
  vl->addWidget(stringeditor);

  // color property
  propcolor = new mitk::ColorProperty(0.5, 1.0, 0.25);

  // color prop editor
  coloreditor = new QmitkColorPropertyEditor( propcolor, this );
  vl->addWidget(coloreditor);

  // bool property
  propbool = new mitk::BoolProperty(true);

  // bool prop view
  boolview = new QmitkBoolPropertyView( propbool, this );
  vl->addWidget(boolview);

  // bool prop editor
  booleditor = new QmitkBoolPropertyEditor( propbool, this );
  vl->addWidget(booleditor);

  //propshort = new mitk::GenericProperty<short>(3);  // see comment below
  propint = new mitk::IntProperty(4);
  propfloat = new mitk::FloatProperty(4.5);
  propdouble = new mitk::DoubleProperty(4.75);

  // not possible because lack of: bool mitk::XMLReader::GetAttribute(std::basic_str, short int&)
  // this is nedded in DataStructures/mitkProperties/mitkGenericProperty.h, l. 86
  //numberview = new QmitkNumberPropertyView( propshort, this );
  //vl->addWidget(numberview);

  numberview1 = new QmitkNumberPropertyView( propint, this );
  numberview1->setDecimalPlaces(4);
  vl->addWidget(numberview1);
  numbereditor1 = new QmitkNumberPropertyEditor( propint, this );
  numbereditor1->setDecimalPlaces(4);
  vl->addWidget(numbereditor1);

  numberview2 = new QmitkNumberPropertyView( propfloat, this );
  numberview2->setDecimalPlaces(3);
  vl->addWidget(numberview2);
  numbereditor2 = new QmitkNumberPropertyEditor( propfloat, this );
  numbereditor2->setDecimalPlaces(3);
  vl->addWidget(numbereditor2);
  numbereditor3 = new QmitkNumberPropertyEditor( propfloat, this );
  numbereditor3->setDecimalPlaces(2);
  vl->addWidget(numbereditor3);
  numbereditor4 = new QmitkNumberPropertyEditor( propfloat, this );
  vl->addWidget(numbereditor4);
  numberview3 = new QmitkNumberPropertyView( propfloat, this );
  numberview3->setDecimalPlaces(2);
  vl->addWidget(numberview3);

  numberview4 = new QmitkNumberPropertyView( propdouble, this );
  vl->addWidget(numberview4);
  numbereditor5 = new QmitkNumberPropertyEditor( propdouble, this );
  numbereditor5->setDecimalPlaces(4);
  vl->addWidget(numbereditor5);
  numbereditor6 = new QmitkNumberPropertyEditor( propdouble, this );
  vl->addWidget(numbereditor6);

  // percents
  propfloat2 = new mitk::FloatProperty(0.43);
  numberview5 = new QmitkNumberPropertyView( propfloat2, this );
  vl->addWidget(numberview5);

  numbereditor7 = new QmitkNumberPropertyEditor( propfloat2, this );
  numbereditor7->setShowPercent(true);
  vl->addWidget(numbereditor7);
  numbereditor8 = new QmitkNumberPropertyEditor( propfloat2, this );
  numbereditor8->setShowPercent(true);
  numbereditor8->setDecimalPlaces(1);
  vl->addWidget(numbereditor8);
/**/
  prepare_tree();

//QVBoxLayout* vlright = new QVBoxLayout(this, QBoxLayout::TopToBottom);

  //treelistview = new QmitkDataTreeListView(tree_filter, this);
  treelistview = new QmitkDataTreeListView(this);
  treelistview->SetFilter(tree_filter);
  // alternative constructor, will create default filter
  //treelistview = new QmitkDataTreeListView(data_tree, this);
  treelistview->setStretchedColumn(2);

//vlright->addWidget(treelistview);

/**/
  QVBoxLayout* vlright = new QVBoxLayout(hl, QBoxLayout::TopToBottom);
  //hl->addWidget( vlright );

  vlright->addWidget( treelistview );

  // color prop view
  colorview = new QmitkColorPropertyView( propcolor, this );
  //vlright->addWidget(colorview, 10);
  vlright->addWidget(colorview);

  treecombobox = new QmitkDataTreeComboBox(tree_filter, this);
  vlright->addWidget( treecombobox );

  // finally, a timer that starts some testing
  timer = new QTimer(this);
  connect ( timer, SIGNAL(timeout()), this, SLOT(run()) );
  timer->start(0, TRUE);
/**/
}

void PropertyViewTest::prepare_tree()
{
  data_tree = mitk::DataTree::New();
  // create some test data
  mitk::Image::Pointer image;
  mitk::PixelType pt(typeid(int));
  unsigned int dim[]={10,10,20}; // image dimensions

  image = mitk::Image::New();
  image->Initialize(mitk::PixelType(typeid(int)), 3, dim);
  int *p = (int*)image->GetData(); // pointer to pixel data
  int size = dim[0]*dim[1]*dim[2];
  for(int i=0; i<size; ++i, ++p) *p=i; // fill image

  {
    mitk::DataTreeNode::Pointer node = mitk::DataTreeNode::New();
    node->SetData(image);
  }

  mitk::DataTreePreOrderIterator it(data_tree);
/**/
  {
    mitk::DataTreeNode::Pointer node = mitk::DataTreeNode::New(); node->SetData(image);
    node->SetProperty("name", new mitk::StringProperty("Opa"));
//    node->SetProperty("opacity", new mitk::FloatProperty(0.8));
    it.Set(node);
  }
/**/
  {
    mitk::DataTreeNode::Pointer node = mitk::DataTreeNode::New(); node->SetData(image);
    node->SetProperty("name", new mitk::StringProperty("Bruder"));
    node->SetProperty("visible", new mitk::BoolProperty(false));
    node->SetProperty("opacity", new mitk::FloatProperty(0.8));
    it.Add(node);
  }
  {
    mitk::DataTreeNode::Pointer node = mitk::DataTreeNode::New(); node->SetData(image);
    node->SetProperty("name", new mitk::StringProperty("Ich"));
    node->SetProperty("opacity", new mitk::FloatProperty(0.8));
    it.Add(node);
  }
  {
    mitk::DataTreeNode::Pointer node = mitk::DataTreeNode::New(); node->SetData(image);
    node->SetProperty("name", new mitk::StringProperty("Schwester"));
    node->SetProperty("opacity", new mitk::FloatProperty(0.8));
    it.Add(node);
  }

  it.GoToChild(1);

  {
    mitk::DataTreeNode::Pointer node = mitk::DataTreeNode::New(); node->SetData(image);
    node->SetProperty("name", new mitk::StringProperty("Sohn"));
//    node->SetProperty("opacity", new mitk::FloatProperty(0.8));
    it.Add(node);
  }
  {
    mitk::DataTreeNode::Pointer node = mitk::DataTreeNode::New(); node->SetData(image);
    node->SetProperty("name", new mitk::StringProperty("Tochter"));
    node->SetProperty("visible", new mitk::BoolProperty(false));
    node->SetProperty("opacity", new mitk::FloatProperty(0.8));
    it.Add(node);
  }

  mitk::DataTreeFilter::PropertyList visible_props;
//  visible_props.push_back("visible");
  visible_props.push_back("name");
//  visible_props.push_back("opacity");
  mitk::DataTreeFilter::PropertyList editable_props;
//  editable_props.push_back("visible");
//  editable_props.push_back("name");
//  editable_props.push_back("opacity");

  tree_filter = mitk::DataTreeFilter::New(data_tree);
  tree_filter->SetSelectionMode(mitk::DataTreeFilter::SINGLE_SELECT);
  tree_filter->SetHierarchyHandling(mitk::DataTreeFilter::FLATTEN_HIERARCHY);
  tree_filter->SetFilter(&mitk::IsGoodDataTreeNode);
  tree_filter->SetVisibleProperties(visible_props);
  tree_filter->SetEditableProperties(editable_props);

}

PropertyViewTest::~PropertyViewTest()
{
  delete timer;

  delete colorview;
  delete coloreditor;
  delete stringeditor;
  delete stringview;
  delete booleditor;
  delete boolview;
  delete baseview;

  delete numberview1;
  delete numberview2;
  delete numberview3;
  delete numberview4;
  delete numberview5;
  delete numbereditor1;
  delete numbereditor2;
  delete numbereditor3;
  delete numbereditor4;
  delete numbereditor5;
  delete numbereditor6;
  delete numbereditor7;
  delete numbereditor8;

  delete propstring;
  delete propcolor;
  delete propbool;
  delete propfloat;
  delete propfloat2;

  delete treelistview;
  delete treecombobox;

  tree_filter = 0;
  data_tree = 0;
}

void PropertyViewTest::run()
{
    assert( baseview->text() == "Juhu" );
    assert( stringview->text() == "Juhu" );
    assert( stringeditor->text() == "Juhu" );

    propstring->SetValue("Huhu Welt");
    assert( baseview->text() == "Huhu Welt" );
    assert( stringview->text() == "Huhu Welt" );
    assert( stringeditor->text() == "Huhu Welt" );

    assert( boolview->isOn() );
    assert( booleditor->isOn() );

    //propbool->SetValue(false);
    //assert( !boolview->isOn() );
    //assert( !booleditor->isOn() );

  if (!m_Stay)
    qApp->quit();
}

<|endoftext|>


<commit_before>/*
 * MRustC - Rust Compiler
 * - By John Hodge (Mutabah/thePowersGang)
 *
 * mir/mir.cpp
 * - MIR (Middle Intermediate Representation) definitions
 */
#include <mir/mir.hpp>

namespace MIR {
    ::std::ostream& operator<<(::std::ostream& os, const Constant& v) {
        TU_MATCHA( (v), (e),
        (Int,
            os << (e < 0 ? "-" : "+");
            os << (e < 0 ? -e : e);
            ),
        (Uint,
            os << e;
            ),
        (Float,
            os << e;
            ),
        (Bool,
            os << (e ? "true" : "false");
            ),
        (Bytes,
            os << "[";
            os << ::std::hex;
            for(auto v : e)
                os << static_cast<unsigned int>(v) << " ";
            os << ::std::dec;
            os << "]";
            ),
        (StaticString,
            os << "\"" << e << "\"";
            ),
        (Const,
            os << e.p;
            ),
        (ItemAddr,
            os << "&" << e;
            )
        )
        return os;
    }

    ::std::ostream& operator<<(::std::ostream& os, const LValue& x)
    {
        TU_MATCHA( (x), (e),
        (Variable,
            os << "Variable(" << e << ")";
            ),
        (Temporary,
            os << "Temporary(" << e.idx << ")";
            ),
        (Argument,
            os << "Argument(" << e.idx << ")";
            ),
        (Static,
            os << "Static(" << e << ")";
            ),
        (Return,
            os << "Return";
            ),
        (Field,
            os << "Field(" << e.field_index << ", " << *e.val << ")";
            ),
        (Deref,
            os << "Deref(" << *e.val << ")";
            ),
        (Index,
            os << "Deref(" << *e.val << ", " << *e.idx << ")";
            ),
        (Downcast,
            os << "Downcast(" << e.variant_index << ", " << *e.val << ")";
            )
        )
        return os;
    }

    ::std::ostream& operator<<(::std::ostream& os, const RValue& x)
    {
        TU_MATCHA( (x), (e),
        (Use,
            os << "Use(" << e << ")";
            ),
        (Constant,
            os << "Constant(" << e << ")";
            ),
        (SizedArray,
            os << "SizedArray(" << e.val << "; " << e.count << ")";
            ),
        (Borrow,
            os << "Borrow(" << e.region << ", " << e.type << ", " << e.val << ")";
            ),
        (Cast,
            os << "Cast(" << e.val << " as " << e.type << ")";
            ),
        (BinOp,
            os << "BinOp(" << e.val_l << " " << static_cast<int>(e.op) << " " << e.val_r << ")";
            ),
        (UniOp,
            os << "UniOp(" << e.val << " " << static_cast<int>(e.op) << ")";
            ),
        (DstMeta,
            os << "DstMeta(" << e.val << ")";
            ),
        (DstPtr,
            os << "DstPtr(" << e.val << ")";
            ),
        (MakeDst,
            os << "MakeDst(" << e.ptr_val << ", " << e.meta_val << ")";
            ),
        (Tuple,
            os << "Tuple(" << e.vals << ")";
            ),
        (Array,
            os << "Array(" << e.vals << ")";
            ),
        (Variant,
            os << "Variant(" << e.path << " #" << e.index << ", " << e.val << ")";
            ),
        (Struct,
            os << "Struct(" << e.path << ", {" << e.vals << "})";
            )
        )
        return os;
    }

    ::std::ostream& operator<<(::std::ostream& os, const Terminator& x)
    {
        TU_MATCHA( (x), (e),
        (Incomplete,
            os << "Invalid";
            ),
        (Return,
            os << "Return";
            ),
        (Diverge,
            os << "Diverge";
            ),
        (Goto,
            os << "Goto(" << e << ")";
            ),
        (Panic,
            os << "Panic(" << e.dst << ";)";
            ),
        (If,
            os << "If( " << e.cond << " : " << e.bb0 << ", " << e.bb1 << ")";
            ),
        (Switch,
            os << "Switch( " << e.val << " : ";
            for(unsigned int j = 0; j < e.targets.size(); j ++)
                os << j << " => bb" << e.targets[j] << ", ";
            os << ")";
            ),
        (CallValue,
            os << "Call( " << e.ret_val << " = " << e.fcn_val << "( ";
            for(const auto& arg : e.args)
                os << arg << ", ";
            os << "), bb" << e.ret_block << ", bb" << e.panic_block << ")";
            ),
        (CallPath,
            os << "Call( " << e.ret_val << " = " << e.fcn_path << "( ";
            for(const auto& arg : e.args)
                os << arg << ", ";
            os << "), bb" << e.ret_block << ", bb" << e.panic_block << ")";
            )
        )

        return os;
    }
}

::MIR::LValue MIR::LValue::clone() const
{
    TU_MATCHA( (*this), (e),
    (Variable, return LValue(e); ),
    (Temporary, return LValue(e); ),
    (Argument, return LValue(e); ),
    (Static, return LValue(e.clone()); ),
    (Return, return LValue(e); ),
    (Field, return LValue::make_Field({
        box$( e.val->clone() ),
        e.field_index
        }); ),
    (Deref, return LValue::make_Deref({
        box$( e.val->clone() )
        }); ),
    (Index, return LValue::make_Index({
        box$( e.val->clone() ),
        box$( e.idx->clone() )
        }); ),
    (Downcast, return LValue::make_Downcast({
        box$( e.val->clone() ),
        e.variant_index
        }); )
    )
    throw "";
}

<commit_msg>MIR - Escape special characters in debug print<commit_after>/*
 * MRustC - Rust Compiler
 * - By John Hodge (Mutabah/thePowersGang)
 *
 * mir/mir.cpp
 * - MIR (Middle Intermediate Representation) definitions
 */
#include <mir/mir.hpp>

namespace MIR {
    ::std::ostream& operator<<(::std::ostream& os, const Constant& v) {
        TU_MATCHA( (v), (e),
        (Int,
            os << (e < 0 ? "-" : "+");
            os << (e < 0 ? -e : e);
            ),
        (Uint,
            os << e;
            ),
        (Float,
            os << e;
            ),
        (Bool,
            os << (e ? "true" : "false");
            ),
        (Bytes,
            os << "[";
            os << ::std::hex;
            for(auto v : e)
                os << static_cast<unsigned int>(v) << " ";
            os << ::std::dec;
            os << "]";
            ),
        (StaticString,
            os << "\"";
            for(auto v : e) {
                if( ' ' <= v && v < 0x7F && v != '"' && v != '\\' )
                    os << v;
                else
                    os << "\\u{" << FMT(::std::hex << (unsigned int)v) << "}";
            }
            os << "\"";
            ),
        (Const,
            os << e.p;
            ),
        (ItemAddr,
            os << "&" << e;
            )
        )
        return os;
    }

    ::std::ostream& operator<<(::std::ostream& os, const LValue& x)
    {
        TU_MATCHA( (x), (e),
        (Variable,
            os << "Variable(" << e << ")";
            ),
        (Temporary,
            os << "Temporary(" << e.idx << ")";
            ),
        (Argument,
            os << "Argument(" << e.idx << ")";
            ),
        (Static,
            os << "Static(" << e << ")";
            ),
        (Return,
            os << "Return";
            ),
        (Field,
            os << "Field(" << e.field_index << ", " << *e.val << ")";
            ),
        (Deref,
            os << "Deref(" << *e.val << ")";
            ),
        (Index,
            os << "Deref(" << *e.val << ", " << *e.idx << ")";
            ),
        (Downcast,
            os << "Downcast(" << e.variant_index << ", " << *e.val << ")";
            )
        )
        return os;
    }

    ::std::ostream& operator<<(::std::ostream& os, const RValue& x)
    {
        TU_MATCHA( (x), (e),
        (Use,
            os << "Use(" << e << ")";
            ),
        (Constant,
            os << "Constant(" << e << ")";
            ),
        (SizedArray,
            os << "SizedArray(" << e.val << "; " << e.count << ")";
            ),
        (Borrow,
            os << "Borrow(" << e.region << ", " << e.type << ", " << e.val << ")";
            ),
        (Cast,
            os << "Cast(" << e.val << " as " << e.type << ")";
            ),
        (BinOp,
            os << "BinOp(" << e.val_l << " " << static_cast<int>(e.op) << " " << e.val_r << ")";
            ),
        (UniOp,
            os << "UniOp(" << e.val << " " << static_cast<int>(e.op) << ")";
            ),
        (DstMeta,
            os << "DstMeta(" << e.val << ")";
            ),
        (DstPtr,
            os << "DstPtr(" << e.val << ")";
            ),
        (MakeDst,
            os << "MakeDst(" << e.ptr_val << ", " << e.meta_val << ")";
            ),
        (Tuple,
            os << "Tuple(" << e.vals << ")";
            ),
        (Array,
            os << "Array(" << e.vals << ")";
            ),
        (Variant,
            os << "Variant(" << e.path << " #" << e.index << ", " << e.val << ")";
            ),
        (Struct,
            os << "Struct(" << e.path << ", {" << e.vals << "})";
            )
        )
        return os;
    }

    ::std::ostream& operator<<(::std::ostream& os, const Terminator& x)
    {
        TU_MATCHA( (x), (e),
        (Incomplete,
            os << "Invalid";
            ),
        (Return,
            os << "Return";
            ),
        (Diverge,
            os << "Diverge";
            ),
        (Goto,
            os << "Goto(" << e << ")";
            ),
        (Panic,
            os << "Panic(" << e.dst << ";)";
            ),
        (If,
            os << "If( " << e.cond << " : " << e.bb0 << ", " << e.bb1 << ")";
            ),
        (Switch,
            os << "Switch( " << e.val << " : ";
            for(unsigned int j = 0; j < e.targets.size(); j ++)
                os << j << " => bb" << e.targets[j] << ", ";
            os << ")";
            ),
        (CallValue,
            os << "Call( " << e.ret_val << " = " << e.fcn_val << "( ";
            for(const auto& arg : e.args)
                os << arg << ", ";
            os << "), bb" << e.ret_block << ", bb" << e.panic_block << ")";
            ),
        (CallPath,
            os << "Call( " << e.ret_val << " = " << e.fcn_path << "( ";
            for(const auto& arg : e.args)
                os << arg << ", ";
            os << "), bb" << e.ret_block << ", bb" << e.panic_block << ")";
            )
        )

        return os;
    }
}

::MIR::LValue MIR::LValue::clone() const
{
    TU_MATCHA( (*this), (e),
    (Variable, return LValue(e); ),
    (Temporary, return LValue(e); ),
    (Argument, return LValue(e); ),
    (Static, return LValue(e.clone()); ),
    (Return, return LValue(e); ),
    (Field, return LValue::make_Field({
        box$( e.val->clone() ),
        e.field_index
        }); ),
    (Deref, return LValue::make_Deref({
        box$( e.val->clone() )
        }); ),
    (Index, return LValue::make_Index({
        box$( e.val->clone() ),
        box$( e.idx->clone() )
        }); ),
    (Downcast, return LValue::make_Downcast({
        box$( e.val->clone() ),
        e.variant_index
        }); )
    )
    throw "";
}

<|endoftext|>


<commit_before>#ifndef ABSTRACT_DELEGATE__HPP
#define ABSTRACT_DELEGATE__HPP

#include "../FastDelegate/src/FastDelegate.h"

//! Value type that represents arbitary delegate in a common form.
class AbstractDelegate
{
public:
	AbstractDelegate() : d_() {}
	AbstractDelegate(fastdelegate::DelegateMemento const & d) : d_(d) {}

	template<class T, class Y> AbstractDelegate(T obj, Y pmf)
		: d_(fastdelegate::MakeDelegate(obj, pmf))
	{}

	bool isNull() const { return d_.empty(); }
	void clear() { d_.clear(); }

	bool operator<(AbstractDelegate const & r) const { return d_.IsLess(r.d_); }
	bool operator>(AbstractDelegate const & r) const { return r.d_.IsLess(d_); }
	bool operator==(AbstractDelegate const & r) const { return d_.IsEqual(r.d_); }
	bool operator!=(AbstractDelegate const & r) const { return !d_.IsEqual(r.d_); }
	bool operator>=(AbstractDelegate const & r) const { return !d_.IsLess(r.d_); }
	bool operator<=(AbstractDelegate const & r) const { return !r.d_.IsLess(d_); }
private:
	fastdelegate::DelegateMemento d_;
};

#endif //ABSTRACT_DELEGATE__HPP<commit_msg>-: Fixed: error in AbstractDelegate template constructor<commit_after>#ifndef ABSTRACT_DELEGATE__HPP
#define ABSTRACT_DELEGATE__HPP

#include "../FastDelegate/src/FastDelegate.h"

//! Value type that represents arbitary delegate in a common form.
class AbstractDelegate
{
public:
	AbstractDelegate() : d_() {}
	AbstractDelegate(fastdelegate::DelegateMemento const & d) : d_(d) {}

	template<class T, class Y> AbstractDelegate(T obj, Y pmf)
		: d_(fastdelegate::MakeDelegate(obj, pmf).GetMemento())
	{}

	bool isNull() const { return d_.empty(); }
	void clear() { d_.clear(); }

	bool operator<(AbstractDelegate const & r) const { return d_.IsLess(r.d_); }
	bool operator>(AbstractDelegate const & r) const { return r.d_.IsLess(d_); }
	bool operator==(AbstractDelegate const & r) const { return d_.IsEqual(r.d_); }
	bool operator!=(AbstractDelegate const & r) const { return !d_.IsEqual(r.d_); }
	bool operator>=(AbstractDelegate const & r) const { return !d_.IsLess(r.d_); }
	bool operator<=(AbstractDelegate const & r) const { return !r.d_.IsLess(d_); }
private:
	fastdelegate::DelegateMemento d_;
};

#endif //ABSTRACT_DELEGATE__HPP<|endoftext|>


<commit_before>// v8-shell.m.cpp                                                     -*-C++-*-

#include <v8.h>

#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>

namespace {

static const char *toCString(v8::Handle<v8::Value> value)
{
    return *v8::String::Utf8Value(value);
}

static std::ostream& format(std::ostream&           stream,
                            v8::Handle<v8::Message> message)
{
    stream << toCString(message->Get()) << '\n';
    auto stack = message->GetStackTrace();
    if (!stack.IsEmpty()) {
        for (int i = 0; i < stack->GetFrameCount(); ++i) {
            auto frame = stack->GetFrame(i);
            stream << "   at ";
            if (frame->GetFunctionName()->Length()) {
                stream << toCString(frame->GetFunctionName()) << " ";
            }
            stream << "(" << toCString(frame->GetScriptName()) << ":"
                << frame->GetLineNumber()      << ":"
                << frame->GetColumn()
                << ")"
                << std::endl;
        }
    }
    return stream;
}

static std::ostream& format(std::ostream&         stream,
                            v8::Handle<v8::Value> value)
{
    return stream << toCString(value) << std::endl;
}

static int read(std::string *result, std::istream& in, std::ostream& out)
{
    result->clear();

    out << ">>> ";
    bool escape = false;
    bool append = true;
    while (true) {
        auto character = in.get();
        switch (character) {
            case -1: {
                out << "\n";
            } return -1;

            case '\n': {
                if (escape) {
                    out << "... ";
                    escape = false;
                }
                else {
                    return 0;
                }
            } break;

            case '\\': {
                escape = true;
                append = false;
            } break;
        }
        if (append) {
            result->push_back(std::istream::traits_type::to_char_type(
                                                                   character));
        }
        append = true;
    }
}

static int evaluate(v8::Isolate             *isolate,
                    v8::Handle<v8::Value>   *result,
                    v8::Handle<v8::Message> *errorMessage,
                    const std::string&       input,
                    const std::string&       inputName)
{
    // This will catch errors within this scope
    v8::TryCatch tryCatch;

    // Load the input string
    auto source = v8::String::NewFromUtf8(isolate,
                                          input.data(),
                                          v8::String::kNormalString,
                                          input.length());
    if (tryCatch.HasCaught()) {
        *errorMessage = tryCatch.Message();
        return -1;
    }

    // Compile it
    auto script = v8::Script::Compile(
                             source,
                             v8::String::NewFromUtf8(isolate,
                                                     inputName.data(),
                                                     v8::String::kNormalString,
                                                     inputName.size()));
    if (tryCatch.HasCaught()) {
        *errorMessage = tryCatch.Message();
        return -1;
    }

    // Evaluate it
    *result = script->Run();
    if (tryCatch.HasCaught()) {
        *errorMessage = tryCatch.Message();
        return -1;
    }

    return 0;
}

static void evaluateAndPrint(v8::Isolate        *isolate,
                             std::ostream&       outStream,
                             std::ostream&       errorStream,
                             const std::string&  input,
                             const std::string&  inputName)
{
    v8::Handle<v8::Value>   result;
    v8::Handle<v8::Message> errorMessage;
    if (evaluate(isolate, &result, &errorMessage, input, inputName)) {
        format(errorStream, errorMessage);
    }
    else {
        outStream << "-> ";
        format(outStream, result);
    }
}

static int readFile(std::string        *contents,
                    const std::string&  fileName)
{
    std::filebuf fileBuffer;
    fileBuffer.open(fileName, std::ios_base::in);
    if (!fileBuffer.is_open()) {
        return -1;
    }

    std::copy(std::istreambuf_iterator<char>(&fileBuffer),
              std::istreambuf_iterator<char>(),
              std::back_inserter(*contents));
    fileBuffer.close();
    return 0;
}

static int evaluateFile(v8::Isolate        *isolate,
                        std::ostream&       outStream,
                        std::ostream&       errorStream,
                        const std::string&  programName,
                        const std::string&  fileName)
{
    std::string input;
    if (readFile(&input, fileName)) {
        errorStream << "Usage: " << programName << " [<filename> | -]*\n"
                    << "Failed to open: " << fileName << std::endl;
        return -1;
    }

    evaluateAndPrint(isolate, outStream, errorStream, input, fileName);
    return 0;
}

static void beginReplLoop(v8::Isolate   *isolate,
                          std::istream&  inStream,
                          std::ostream&  outStream,
                          std::ostream&  errorStream)
{
    std::string input;
    int         command = 0;
    while (read(&input, inStream, outStream) == 0) {
        std::ostringstream oss;
        oss << "<stdin:" << ++command << ">";
        evaluateAndPrint(isolate, outStream, errorStream, input, oss.str());
    }
}

}  // close unnamed namespace

int main(int argc, char *argv[])
{
    // Initialize global v8 variables
    auto *isolate = v8::Isolate::GetCurrent();
    v8::V8::SetCaptureStackTraceForUncaughtExceptions(
                                                    true,
                                                    0x100,
                                                    v8::StackTrace::kDetailed);

    // Stack-local storage
    v8::HandleScope handles(isolate);

    // Create and enter a context
    auto               context = v8::Context::New(isolate);
    v8::Context::Scope scope(context);

    if (argc == 1) {
        beginReplLoop(isolate, std::cin, std::cout, std::cerr);
    }
    else {
        for (int i = 1; i < argc; ++i) {
            if (argv[i][0] == '-') {
                switch (argv[i][1]) {
                    case '\0':
                        beginReplLoop(isolate, std::cin, std::cout, std::cerr);
                        break;

                    case 'h':
                    default:
                        std::cout
                                << "Usage: " << argv[0] << " [<filename> | -]*"
                                << std::endl;
                        break;
                }
            }
            else {
                evaluateFile(isolate, std::cout, std::cerr, argv[0], argv[i]);
            }
        }
    }

    return 0;
}
<commit_msg>Fix bug returning unowned char *<commit_after>// v8-shell.m.cpp                                                     -*-C++-*-

#include <v8.h>

#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>

namespace {

static std::string toCString(v8::Handle<v8::Value> value)
{
    return *v8::String::Utf8Value(value);
}

static std::ostream& format(std::ostream&           stream,
                            v8::Handle<v8::Message> message)
{
    stream << toCString(message->Get()) << '\n';
    auto stack = message->GetStackTrace();
    if (!stack.IsEmpty()) {
        for (int i = 0; i < stack->GetFrameCount(); ++i) {
            auto frame = stack->GetFrame(i);
            stream << "   at ";
            if (frame->GetFunctionName()->Length()) {
                stream << toCString(frame->GetFunctionName()) << " ";
            }
            stream << "(" << toCString(frame->GetScriptName()) << ":"
                << frame->GetLineNumber()      << ":"
                << frame->GetColumn()
                << ")"
                << std::endl;
        }
    }
    return stream;
}

static std::ostream& format(std::ostream&         stream,
                            v8::Handle<v8::Value> value)
{
    return stream << toCString(value) << std::endl;
}

static int read(std::string *result, std::istream& in, std::ostream& out)
{
    result->clear();

    out << ">>> ";
    bool escape = false;
    bool append = true;
    while (true) {
        auto character = in.get();
        switch (character) {
            case -1: {
                out << "\n";
            } return -1;

            case '\n': {
                if (escape) {
                    out << "... ";
                    escape = false;
                }
                else {
                    return 0;
                }
            } break;

            case '\\': {
                escape = true;
                append = false;
            } break;
        }
        if (append) {
            result->push_back(std::istream::traits_type::to_char_type(
                                                                   character));
        }
        append = true;
    }
}

static int evaluate(v8::Isolate             *isolate,
                    v8::Handle<v8::Value>   *result,
                    v8::Handle<v8::Message> *errorMessage,
                    const std::string&       input,
                    const std::string&       inputName)
{
    // This will catch errors within this scope
    v8::TryCatch tryCatch;

    // Load the input string
    auto source = v8::String::NewFromUtf8(isolate,
                                          input.data(),
                                          v8::String::kNormalString,
                                          input.length());
    if (tryCatch.HasCaught()) {
        *errorMessage = tryCatch.Message();
        return -1;
    }

    // Compile it
    auto script = v8::Script::Compile(
                             source,
                             v8::String::NewFromUtf8(isolate,
                                                     inputName.data(),
                                                     v8::String::kNormalString,
                                                     inputName.size()));
    if (tryCatch.HasCaught()) {
        *errorMessage = tryCatch.Message();
        return -1;
    }

    // Evaluate it
    *result = script->Run();
    if (tryCatch.HasCaught()) {
        *errorMessage = tryCatch.Message();
        return -1;
    }

    return 0;
}

static void evaluateAndPrint(v8::Isolate        *isolate,
                             std::ostream&       outStream,
                             std::ostream&       errorStream,
                             const std::string&  input,
                             const std::string&  inputName)
{
    v8::Handle<v8::Value>   result;
    v8::Handle<v8::Message> errorMessage;
    if (evaluate(isolate, &result, &errorMessage, input, inputName)) {
        format(errorStream, errorMessage);
    }
    else {
        outStream << "-> ";
        format(outStream, result);
    }
}

static int readFile(std::string        *contents,
                    const std::string&  fileName)
{
    std::filebuf fileBuffer;
    fileBuffer.open(fileName, std::ios_base::in);
    if (!fileBuffer.is_open()) {
        return -1;
    }

    std::copy(std::istreambuf_iterator<char>(&fileBuffer),
              std::istreambuf_iterator<char>(),
              std::back_inserter(*contents));
    fileBuffer.close();
    return 0;
}

static int evaluateFile(v8::Isolate        *isolate,
                        std::ostream&       outStream,
                        std::ostream&       errorStream,
                        const std::string&  programName,
                        const std::string&  fileName)
{
    std::string input;
    if (readFile(&input, fileName)) {
        errorStream << "Usage: " << programName << " [<filename> | -]*\n"
                    << "Failed to open: " << fileName << std::endl;
        return -1;
    }

    evaluateAndPrint(isolate, outStream, errorStream, input, fileName);
    return 0;
}

static void beginReplLoop(v8::Isolate   *isolate,
                          std::istream&  inStream,
                          std::ostream&  outStream,
                          std::ostream&  errorStream)
{
    std::string input;
    int         command = 0;
    while (read(&input, inStream, outStream) == 0) {
        std::ostringstream oss;
        oss << "<stdin:" << ++command << ">";
        evaluateAndPrint(isolate, outStream, errorStream, input, oss.str());
    }
}

}  // close unnamed namespace

int main(int argc, char *argv[])
{
    // Initialize global v8 variables
    auto *isolate = v8::Isolate::GetCurrent();
    v8::V8::SetCaptureStackTraceForUncaughtExceptions(
                                                    true,
                                                    0x100,
                                                    v8::StackTrace::kDetailed);

    // Stack-local storage
    v8::HandleScope handles(isolate);

    // Create and enter a context
    auto               context = v8::Context::New(isolate);
    v8::Context::Scope scope(context);

    if (argc == 1) {
        beginReplLoop(isolate, std::cin, std::cout, std::cerr);
    }
    else {
        for (int i = 1; i < argc; ++i) {
            if (argv[i][0] == '-') {
                switch (argv[i][1]) {
                    case '\0':
                        beginReplLoop(isolate, std::cin, std::cout, std::cerr);
                        break;

                    case 'h':
                    default:
                        std::cout
                                << "Usage: " << argv[0] << " [<filename> | -]*"
                                << std::endl;
                        break;
                }
            }
            else {
                evaluateFile(isolate, std::cout, std::cerr, argv[0], argv[i]);
            }
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>//MIT License
//
//Copyright(c) 2016 Matthias Moeller
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files(the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions :
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.

#ifndef __TYTI_STEAM_VDF_PARSER_H__
#define __TYTI_STEAM_VDF_PARSER_H__

#include <vector>
#include <unordered_map>
#include <utility>
#include <fstream>

#include <memory>

#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/config.hpp>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_object.hpp>

namespace tyti
{
    namespace vdf
    {
        template<typename CharT>
        struct basic_object;

        template<typename iStreamT, typename charT>
        basic_object<charT> read(iStreamT& inStream, bool *ok);

        namespace detail
        {
            ///////////////////////////////////////////////////////////////////////////
            //  Grammar data structure
            ///////////////////////////////////////////////////////////////////////////
            template<typename T>
            struct parser_ast;

            template<typename charT>
            struct variant
            {
                typedef boost::variant <
                    boost::recursive_wrapper< parser_ast<charT> > //cildren
                    , std::pair<std::basic_string<charT>, std::basic_string<charT> > //attribute
                    , std::basic_string<charT> //includes
                > parser_node;
            };

            template<typename charT>
            struct parser_ast
            {
                std::basic_string<charT> name;                           // tag name
                std::vector< typename variant<charT>::parser_node > children;        // children
            };

            ///////////////////////////////////////////////////////////////////////////
            //  Helper functions selecting the right encoding (char/wchar_T)
            ///////////////////////////////////////////////////////////////////////////

            template<typename T>
            struct literal_macro_help
            {
                static const char* result(const char* c, const wchar_t* wc)
                {
                    return c;
                }
                static const char result(char c, wchar_t wc)
                {
                    return c;
                }
            };

            template<>
            struct literal_macro_help<wchar_t>
            {
                static const wchar_t* result(const char* c, const wchar_t* wc)
                {
                    return wc;
                }
                static const wchar_t result(char c, wchar_t wc)
                {
                    return wc;
                }
            };
#define TYTI_L(type, text) vdf::detail::literal_macro_help<type>::result(text, L##text)

            template<typename T>
            struct encoding_selector
            {
                typedef boost::spirit::standard::char_type char_type;
                typedef boost::spirit::standard::space_type space_type;
                static const char_type char_;
                static const space_type space;
            };

            template<>
            struct encoding_selector<wchar_t>
            {
                typedef boost::spirit::standard_wide::char_type char_type;
                typedef boost::spirit::standard_wide::space_type space_type;
                static const char_type char_;
                static const space_type space;
            };
            template<typename T>
            const typename encoding_selector<T>::char_type encoding_selector<T>::char_ = boost::spirit::standard::char_;
            template<typename T>
            const typename encoding_selector<T>::space_type encoding_selector<T>::space = boost::spirit::standard::space;
            const typename encoding_selector<wchar_t>::char_type encoding_selector<wchar_t>::char_ = boost::spirit::standard_wide::char_;
            const typename encoding_selector<wchar_t>::space_type encoding_selector<wchar_t>::space = boost::spirit::standard_wide::space;

            ///////////////////////////////////////////////////////////////////////////
            //  Grammar
            ///////////////////////////////////////////////////////////////////////////
            template<typename CharT, typename Iterator>
            struct vdf_skipper : public boost::spirit::qi::grammar<Iterator> {

            private:
                typedef encoding_selector<typename Iterator::value_type> es;
            public:

                vdf_skipper() : vdf_skipper::base_type(skip, "comment_skipper") {
                    //skip whitespace or C++ comment until next line
                    comment = (TYTI_L(CharT, "//") >> *(es::char_ - TYTI_L(CharT, '\n')));
                    skip = es::space | comment;
                }
                boost::spirit::qi::rule<Iterator> skip;
                boost::spirit::qi::rule<Iterator> comment;
            };

            template <typename CharT, typename Iterator>
            struct vdf_grammar
                : boost::spirit::qi::grammar<Iterator, parser_ast<CharT>(), boost::spirit::qi::locals< std::basic_string<CharT> >, vdf_skipper<CharT, Iterator> >
            {
                typedef CharT char_type;
                typedef std::basic_string<char_type> gr_string;
                typedef encoding_selector<char_type> es;
                typedef typename variant<char_type>::parser_node parser_node;
                vdf_grammar()
                    : vdf_grammar::base_type(vdf, "vdf")
                {
                    namespace spirit = boost::spirit;
                    namespace phoenix = boost::phoenix;
                    using spirit::qi::lit;
                    using spirit::qi::lexeme;
                    using spirit::qi::on_error;
                    using spirit::qi::fail;
                    using namespace spirit::qi::labels;

                    using phoenix::construct;
                    using phoenix::val;

                    quoted_string %= lexeme[TYTI_L(char_type, '"') >>
                        (es::char_ - TYTI_L(char_type, '"') - TYTI_L(char_type, '#')) >>
                        *(es::char_ - TYTI_L(char_type, '"')) >> TYTI_L(char_type, '"')];

                    include %= (lit(TYTI_L(char_type,"\"#base\"")) | lit(TYTI_L(char_type,"\"#include\""))) > quoted_string;
                    text %= quoted_string > quoted_string;
                    node %= vdf | text | include;

                    vdf %=
                        quoted_string >> TYTI_L(char_type, "{")
                        >> *node >> TYTI_L(char_type, "}");

                    vdf.name("vdf");
                    node.name("node");
                    text.name("text");
                    quoted_string.name("string");

                    //on_error<fail>
                    //    (
                    //        vdf
                    //        , std::cout
                    //        << val("Error! Expecting ")
                    //        << spirit::_4                               // what failed?
                    //        << val(" here: \"")
                    //        << construct<std::string>(spirit::_3, spirit::_2)   // iterators to error-pos, end
                    //        << val("\"")
                    //        << std::endl
                    //        );
                }

                typedef vdf_skipper<CharT, Iterator> skipper;
                //typedef typename es::space_type skipper;

                boost::spirit::qi::rule<Iterator, parser_ast<CharT>(), boost::spirit::qi::locals<gr_string>, skipper> vdf;
                boost::spirit::qi::rule<Iterator, parser_node(), skipper> node;
                boost::spirit::qi::rule<Iterator, std::pair<gr_string, gr_string>(), skipper> text;
                boost::spirit::qi::rule<Iterator, gr_string(), skipper> quoted_string;
                boost::spirit::qi::rule<Iterator, gr_string(), skipper> include;
            };

            ///////////////////////////////////////////////////////////////////////////
            //  Visitor
            ///////////////////////////////////////////////////////////////////////////

            // trasformation from parser_ast to output tree via objects
            template<typename charT>
            struct vdf_praser_ast_visitor : public boost::static_visitor<>
            {
                typedef basic_object<charT> vis_object;
                typedef std::pair<std::basic_string<charT>, std::basic_string<charT> > vis_key_value;
                vis_object& m_currentObj;
            public:
                vdf_praser_ast_visitor(vis_object& t) : m_currentObj(t) {}
                void operator()(std::pair<std::basic_string<charT>, std::basic_string<charT> > in) const
                {
                    m_currentObj.attribs.insert(std::move(in));
                }
                void operator()(std::basic_string<charT> in) const
                {
                    std::basic_ifstream<charT> file(in);
                    if (!file.is_open())
                    {
                        std::cerr << "Could not open file: " << std::string(in.begin(), in.end()) << std::endl;
                        return;
                    }
                    auto obj = tyti::vdf::read(file);
                    m_currentObj.childs.emplace(obj.name, std::make_shared<vis_object>(obj));
                }
                void operator()(const parser_ast<charT>& x) const
                {
                    vis_object t;
                    t.name = x.name;
                    for (auto& i : x.children)
                        boost::apply_visitor(vdf_praser_ast_visitor<charT>(t), i);
                    m_currentObj.childs.emplace(t.name, std::make_shared<vis_object>(t));
                }

            };

            ///////////////////////////////////////////////////////////////////////////
            //  Writer helper functions
            ///////////////////////////////////////////////////////////////////////////

            struct tabs
            {
                size_t t;
                tabs(size_t i) :t(i) {}
            };

            template<typename oStreamT>
            oStreamT& operator<<(oStreamT& s, tabs t)
            {
                for (; t.t > 0; --t.t)
                    s << "\t";
                return s;
            }
        } // end namespace detail

        ///////////////////////////////////////////////////////////////////////////
        //  Interface
        ///////////////////////////////////////////////////////////////////////////

        /// basic object node. Every object has a name and can contains attributes saved as key_value pairs or childrens
        template<typename CharT>
        struct basic_object
        {
            typedef CharT char_type;
            std::basic_string<char_type> name;
            std::unordered_map<std::basic_string<char_type>, std::basic_string<char_type> > attribs;
            std::unordered_map<std::basic_string<char_type>, std::shared_ptr< basic_object<char_type> > > childs;
        };

        typedef basic_object<char> object;
        typedef basic_object<wchar_t> wobject;

        /** \brief writes given object tree in vdf format to given stream.
        Uses tabs instead of whitespaces.
        */
        template<typename oStreamT, typename charT = typename oStreamT::char_type>
        void write(oStreamT& s, const basic_object<charT>& r, size_t t = 0)
        {
            using namespace detail;
            s << tabs(t) << TYTI_L(charT, '"') << r.name << TYTI_L(charT, "\"\n") << tabs(t) << TYTI_L(charT, "{\n");
            for (auto& i : r.attribs)
                s << tabs(t + 1) << TYTI_L(charT, '"') << i.first << TYTI_L(charT, "\"\t\t\"") << i.second << TYTI_L(charT, "\"\n");
            for (auto& i : r.childs)
                write(s, i, t + 1);
            s << tabs(t) << TYTI_L(charT, "}\n");
        }

        /** \brief Read VDF formatted sequences defined by the range [first, last).
        If the file is mailformatted, parser will try to read it until it can.
        @param first begin iterator
        @param end end iterator
        @param ok output bool. true, if parser successed, false, if parser failed
        */
        template<typename IterT, typename charT = typename IterT::value_type>
        basic_object<charT> read(IterT first, IterT last, bool* ok = 0)
        {
            using namespace detail;
            parser_ast<charT> ast;
            vdf_grammar<charT, IterT> parser;
            vdf_skipper<charT, IterT> skipper;
            bool r = boost::spirit::qi::phrase_parse(first, last, parser, skipper, ast);
            if (ok)
                *ok = r;

            basic_object<charT> root;
                for(auto& i : ast.children)
                boost::apply_visitor(vdf_praser_ast_visitor<charT>(root), i);
            root.name = ast.name;
            return root;
        }

        /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf formatted data.
        */
        template<typename iStreamT, typename charT = typename iStreamT::char_type>
        basic_object<charT> read(iStreamT& inStream, bool *ok = 0)
        {
            // cache the file
            std::basic_string<charT> str;
            inStream.seekg(0, std::ios::end);
            str.resize(inStream.tellg());
            if (str.empty())
                return basic_object<charT>();

            inStream.seekg(0, std::ios::beg);
            inStream.read(&str[0], str.size());
            inStream.close();

            // parse it
            return read(str.begin(), str.end(), ok);
        }

    } // end namespace vdf
} // end namespace tyti
#ifndef TYTI_NO_L_UNDEF
#undef TYTI_L
#endif

BOOST_FUSION_ADAPT_STRUCT(
    tyti::vdf::detail::parser_ast<char>,
    (std::string, name)
    (std::vector< tyti::vdf::detail::variant<char>::parser_node >, children)
)

BOOST_FUSION_ADAPT_STRUCT(
    tyti::vdf::detail::parser_ast<wchar_t>,
    (std::wstring, name)
    (std::vector< tyti::vdf::detail::variant<wchar_t>::parser_node >, children)
)

#endif //__TYTI_STEAM_VDF_PARSER_H__<commit_msg>moved default arguments to declaration<commit_after>//MIT License
//
//Copyright(c) 2016 Matthias Moeller
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files(the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions :
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.

#ifndef __TYTI_STEAM_VDF_PARSER_H__
#define __TYTI_STEAM_VDF_PARSER_H__

#include <vector>
#include <unordered_map>
#include <utility>
#include <fstream>

#include <memory>

#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/config.hpp>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_object.hpp>

namespace tyti
{
    namespace vdf
    {
        template<typename CharT>
        struct basic_object;

        template<typename iStreamT, typename charT = typename iStreamT::char_type>
        basic_object<charT> read(iStreamT& inStream, bool *ok = 0);

        namespace detail
        {
            ///////////////////////////////////////////////////////////////////////////
            //  Grammar data structure
            ///////////////////////////////////////////////////////////////////////////
            template<typename T>
            struct parser_ast;

            template<typename charT>
            struct variant
            {
                typedef boost::variant <
                    boost::recursive_wrapper< parser_ast<charT> > //cildren
                    , std::pair<std::basic_string<charT>, std::basic_string<charT> > //attribute
                    , std::basic_string<charT> //includes
                > parser_node;
            };

            template<typename charT>
            struct parser_ast
            {
                std::basic_string<charT> name;                           // tag name
                std::vector< typename variant<charT>::parser_node > children;        // children
            };

            ///////////////////////////////////////////////////////////////////////////
            //  Helper functions selecting the right encoding (char/wchar_T)
            ///////////////////////////////////////////////////////////////////////////

            template<typename T>
            struct literal_macro_help
            {
                static const char* result(const char* c, const wchar_t* wc)
                {
                    return c;
                }
                static const char result(char c, wchar_t wc)
                {
                    return c;
                }
            };

            template<>
            struct literal_macro_help<wchar_t>
            {
                static const wchar_t* result(const char* c, const wchar_t* wc)
                {
                    return wc;
                }
                static const wchar_t result(char c, wchar_t wc)
                {
                    return wc;
                }
            };
#define TYTI_L(type, text) vdf::detail::literal_macro_help<type>::result(text, L##text)

            template<typename T>
            struct encoding_selector
            {
                typedef boost::spirit::standard::char_type char_type;
                typedef boost::spirit::standard::space_type space_type;
                static const char_type char_;
                static const space_type space;
            };

            template<>
            struct encoding_selector<wchar_t>
            {
                typedef boost::spirit::standard_wide::char_type char_type;
                typedef boost::spirit::standard_wide::space_type space_type;
                static const char_type char_;
                static const space_type space;
            };
            template<typename T>
            const typename encoding_selector<T>::char_type encoding_selector<T>::char_ = boost::spirit::standard::char_;
            template<typename T>
            const typename encoding_selector<T>::space_type encoding_selector<T>::space = boost::spirit::standard::space;
            const typename encoding_selector<wchar_t>::char_type encoding_selector<wchar_t>::char_ = boost::spirit::standard_wide::char_;
            const typename encoding_selector<wchar_t>::space_type encoding_selector<wchar_t>::space = boost::spirit::standard_wide::space;

            ///////////////////////////////////////////////////////////////////////////
            //  Grammar
            ///////////////////////////////////////////////////////////////////////////
            template<typename CharT, typename Iterator>
            struct vdf_skipper : public boost::spirit::qi::grammar<Iterator> {

            private:
                typedef encoding_selector<typename Iterator::value_type> es;
            public:

                vdf_skipper() : vdf_skipper::base_type(skip, "comment_skipper") {
                    //skip whitespace or C++ comment until next line
                    comment = (TYTI_L(CharT, "//") >> *(es::char_ - TYTI_L(CharT, '\n')));
                    skip = es::space | comment;
                }
                boost::spirit::qi::rule<Iterator> skip;
                boost::spirit::qi::rule<Iterator> comment;
            };

            template <typename CharT, typename Iterator>
            struct vdf_grammar
                : boost::spirit::qi::grammar<Iterator, parser_ast<CharT>(), boost::spirit::qi::locals< std::basic_string<CharT> >, vdf_skipper<CharT, Iterator> >
            {
                typedef CharT char_type;
                typedef std::basic_string<char_type> gr_string;
                typedef encoding_selector<char_type> es;
                typedef typename variant<char_type>::parser_node parser_node;
                vdf_grammar()
                    : vdf_grammar::base_type(vdf, "vdf")
                {
                    namespace spirit = boost::spirit;
                    namespace phoenix = boost::phoenix;
                    using spirit::qi::lit;
                    using spirit::qi::lexeme;
                    using spirit::qi::on_error;
                    using spirit::qi::fail;
                    using namespace spirit::qi::labels;

                    using phoenix::construct;
                    using phoenix::val;

                    quoted_string %= lexeme[TYTI_L(char_type, '"') >>
                        (es::char_ - TYTI_L(char_type, '"') - TYTI_L(char_type, '#')) >>
                        *(es::char_ - TYTI_L(char_type, '"')) >> TYTI_L(char_type, '"')];

                    include %= (lit(TYTI_L(char_type,"\"#base\"")) | lit(TYTI_L(char_type,"\"#include\""))) > quoted_string;
                    text %= quoted_string > quoted_string;
                    node %= vdf | text | include;

                    vdf %=
                        quoted_string >> TYTI_L(char_type, "{")
                        >> *node >> TYTI_L(char_type, "}");

                    vdf.name("vdf");
                    node.name("node");
                    text.name("text");
                    quoted_string.name("string");

                    //on_error<fail>
                    //    (
                    //        vdf
                    //        , std::cout
                    //        << val("Error! Expecting ")
                    //        << spirit::_4                               // what failed?
                    //        << val(" here: \"")
                    //        << construct<std::string>(spirit::_3, spirit::_2)   // iterators to error-pos, end
                    //        << val("\"")
                    //        << std::endl
                    //        );
                }

                typedef vdf_skipper<CharT, Iterator> skipper;
                //typedef typename es::space_type skipper;

                boost::spirit::qi::rule<Iterator, parser_ast<CharT>(), boost::spirit::qi::locals<gr_string>, skipper> vdf;
                boost::spirit::qi::rule<Iterator, parser_node(), skipper> node;
                boost::spirit::qi::rule<Iterator, std::pair<gr_string, gr_string>(), skipper> text;
                boost::spirit::qi::rule<Iterator, gr_string(), skipper> quoted_string;
                boost::spirit::qi::rule<Iterator, gr_string(), skipper> include;
            };

            ///////////////////////////////////////////////////////////////////////////
            //  Visitor
            ///////////////////////////////////////////////////////////////////////////

            // trasformation from parser_ast to output tree via objects
            template<typename charT>
            struct vdf_praser_ast_visitor : public boost::static_visitor<>
            {
                typedef basic_object<charT> vis_object;
                typedef std::pair<std::basic_string<charT>, std::basic_string<charT> > vis_key_value;
                vis_object& m_currentObj;
            public:
                vdf_praser_ast_visitor(vis_object& t) : m_currentObj(t) {}
                void operator()(std::pair<std::basic_string<charT>, std::basic_string<charT> > in) const
                {
                    m_currentObj.attribs.insert(std::move(in));
                }
                void operator()(std::basic_string<charT> in) const
                {
                    std::basic_ifstream<charT> file(in);
                    if (!file.is_open())
                    {
                        std::cerr << "Could not open file: " << std::string(in.begin(), in.end()) << std::endl;
                        return;
                    }
                    auto obj = tyti::vdf::read(file);
                    m_currentObj.childs.emplace(obj.name, std::make_shared<vis_object>(obj));
                }
                void operator()(const parser_ast<charT>& x) const
                {
                    vis_object t;
                    t.name = x.name;
                    for (auto& i : x.children)
                        boost::apply_visitor(vdf_praser_ast_visitor<charT>(t), i);
                    m_currentObj.childs.emplace(t.name, std::make_shared<vis_object>(t));
                }

            };

            ///////////////////////////////////////////////////////////////////////////
            //  Writer helper functions
            ///////////////////////////////////////////////////////////////////////////

            struct tabs
            {
                size_t t;
                tabs(size_t i) :t(i) {}
            };

            template<typename oStreamT>
            oStreamT& operator<<(oStreamT& s, tabs t)
            {
                for (; t.t > 0; --t.t)
                    s << "\t";
                return s;
            }
        } // end namespace detail

        ///////////////////////////////////////////////////////////////////////////
        //  Interface
        ///////////////////////////////////////////////////////////////////////////

        /// basic object node. Every object has a name and can contains attributes saved as key_value pairs or childrens
        template<typename CharT>
        struct basic_object
        {
            typedef CharT char_type;
            std::basic_string<char_type> name;
            std::unordered_map<std::basic_string<char_type>, std::basic_string<char_type> > attribs;
            std::unordered_map<std::basic_string<char_type>, std::shared_ptr< basic_object<char_type> > > childs;
        };

        typedef basic_object<char> object;
        typedef basic_object<wchar_t> wobject;

        /** \brief writes given object tree in vdf format to given stream.
        Uses tabs instead of whitespaces.
        */
        template<typename oStreamT, typename charT = typename oStreamT::char_type>
        void write(oStreamT& s, const basic_object<charT>& r, size_t t = 0)
        {
            using namespace detail;
            s << tabs(t) << TYTI_L(charT, '"') << r.name << TYTI_L(charT, "\"\n") << tabs(t) << TYTI_L(charT, "{\n");
            for (auto& i : r.attribs)
                s << tabs(t + 1) << TYTI_L(charT, '"') << i.first << TYTI_L(charT, "\"\t\t\"") << i.second << TYTI_L(charT, "\"\n");
            for (auto& i : r.childs)
                write(s, i, t + 1);
            s << tabs(t) << TYTI_L(charT, "}\n");
        }

        /** \brief Read VDF formatted sequences defined by the range [first, last).
        If the file is mailformatted, parser will try to read it until it can.
        @param first begin iterator
        @param end end iterator
        @param ok output bool. true, if parser successed, false, if parser failed
        */
        template<typename IterT, typename charT = typename IterT::value_type>
        basic_object<charT> read(IterT first, IterT last, bool* ok = 0)
        {
            using namespace detail;
            parser_ast<charT> ast;
            vdf_grammar<charT, IterT> parser;
            vdf_skipper<charT, IterT> skipper;
            bool r = boost::spirit::qi::phrase_parse(first, last, parser, skipper, ast);
            if (ok)
                *ok = r;

            basic_object<charT> root;
                for(auto& i : ast.children)
                boost::apply_visitor(vdf_praser_ast_visitor<charT>(root), i);
            root.name = ast.name;
            return root;
        }

        /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf formatted data.
        */
        template<typename iStreamT, typename charT>
        basic_object<charT> read(iStreamT& inStream, bool *ok)
        {
            // cache the file
            std::basic_string<charT> str;
            inStream.seekg(0, std::ios::end);
            str.resize(inStream.tellg());
            if (str.empty())
                return basic_object<charT>();

            inStream.seekg(0, std::ios::beg);
            inStream.read(&str[0], str.size());
            inStream.close();

            // parse it
            return read(str.begin(), str.end(), ok);
        }

    } // end namespace vdf
} // end namespace tyti
#ifndef TYTI_NO_L_UNDEF
#undef TYTI_L
#endif

BOOST_FUSION_ADAPT_STRUCT(
    tyti::vdf::detail::parser_ast<char>,
    (std::string, name)
    (std::vector< tyti::vdf::detail::variant<char>::parser_node >, children)
)

BOOST_FUSION_ADAPT_STRUCT(
    tyti::vdf::detail::parser_ast<wchar_t>,
    (std::wstring, name)
    (std::vector< tyti::vdf::detail::variant<wchar_t>::parser_node >, children)
)

#endif //__TYTI_STEAM_VDF_PARSER_H__<|endoftext|>


<commit_before>// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/searchlib/tensor/tensor_buffer_operations.h>
#include <vespa/eval/eval/simple_value.h>
#include <vespa/eval/eval/tensor_spec.h>
#include <vespa/eval/eval/value.h>
#include <vespa/eval/eval/value_codec.h>
#include <vespa/eval/streamed/streamed_value_builder_factory.h>
#include <vespa/vespalib/gtest/gtest.h>

using search::tensor::TensorBufferOperations;
using vespalib::eval::SimpleValue;
using vespalib::eval::StreamedValueBuilderFactory;
using vespalib::eval::TensorSpec;
using vespalib::eval::Value;
using vespalib::eval::ValueType;
using vespalib::eval::TypedCells;

const vespalib::string tensor_type_spec("tensor(x{})");
const vespalib::string tensor_type_2d_spec("tensor(x{},y{})");
const vespalib::string tensor_type_2d_mixed_spec("tensor(x{},y[2])");
const vespalib::string float_tensor_type_spec("tensor<float>(y{})");

struct TestParam
{
    vespalib::string    _name;
    std::vector<size_t> _array_sizes;
    TensorSpec          _tensor_spec;
    TestParam(vespalib::string name, std::vector<size_t> array_sizes, TensorSpec tensor_spec)
        : _name(std::move(name)),
          _array_sizes(std::move(array_sizes)),
          _tensor_spec(std::move(tensor_spec))
    {
    }
    ~TestParam();
};

TestParam::~TestParam() = default;

std::ostream& operator<<(std::ostream& os, const TestParam& param)
{
    os << param._name;
    return os;
}

class TensorBufferOperationsTest : public testing::TestWithParam<TestParam>
{
protected:
    ValueType _tensor_type;
    TensorBufferOperations _ops;
    TensorBufferOperationsTest();
    ~TensorBufferOperationsTest() override;
    std::vector<size_t> get_array_sizes(uint32_t max_subspaces);
    std::vector<char> store_tensor(const Value& tensor);
    std::vector<char> store_tensor(const TensorSpec& spec);
    std::unique_ptr<Value> load_tensor(vespalib::ConstArrayRef<char> buf);
    TensorSpec load_tensor_spec(vespalib::ConstArrayRef<char> buf);
    vespalib::nbostream encode_stored_tensor(vespalib::ConstArrayRef<char> buf);
    void assert_store_load(const TensorSpec& tensor_spec);
    void assert_store_copy_load(const TensorSpec& tensor_spec);
    void assert_store_encode_decode(const TensorSpec& tensor_spec);
};

TensorBufferOperationsTest::TensorBufferOperationsTest()
    : testing::TestWithParam<TestParam>(),
      _tensor_type(ValueType::from_spec(GetParam()._tensor_spec.type())),
      _ops(_tensor_type)
{
}

TensorBufferOperationsTest::~TensorBufferOperationsTest() = default;

std::vector<size_t>
TensorBufferOperationsTest::get_array_sizes(uint32_t max_subspaces)
{
    std::vector<size_t> array_sizes;
    for (uint32_t num_subspaces = 0; num_subspaces < max_subspaces; ++num_subspaces) {
        array_sizes.emplace_back(_ops.get_array_size(num_subspaces));
    }
    return array_sizes;
}

std::vector<char>
TensorBufferOperationsTest::store_tensor(const Value& tensor)
{
    EXPECT_EQ(_tensor_type, tensor.type());
    uint32_t num_subspaces = tensor.index().size();
    auto array_size = _ops.get_array_size(num_subspaces);
    std::vector<char> buf;
    buf.resize(array_size);
    _ops.store_tensor(buf, tensor);
    return buf;
}

std::vector<char>
TensorBufferOperationsTest::store_tensor(const TensorSpec& spec)
{
    auto tensor = SimpleValue::from_spec(spec);
    return store_tensor(*tensor);
}

std::unique_ptr<Value>
TensorBufferOperationsTest::load_tensor(vespalib::ConstArrayRef<char> buf)
{
    return _ops.make_fast_view(buf, _tensor_type);
}

vespalib::nbostream
TensorBufferOperationsTest::encode_stored_tensor(vespalib::ConstArrayRef<char> buf)
{
    vespalib::nbostream out;
    _ops.encode_stored_tensor(buf, _tensor_type, out);
    return out;
}

TensorSpec
TensorBufferOperationsTest::load_tensor_spec(vespalib::ConstArrayRef<char> buf)
{
    auto loaded = load_tensor(buf);
    return TensorSpec::from_value(*loaded);
}

void
TensorBufferOperationsTest::assert_store_load(const TensorSpec& tensor_spec)
{
    auto buf = store_tensor(tensor_spec);
    auto loaded_spec = load_tensor_spec(buf);
    _ops.reclaim_labels(buf);
    EXPECT_EQ(tensor_spec, loaded_spec);
}

void
TensorBufferOperationsTest::assert_store_copy_load(const TensorSpec& tensor_spec)
{
    auto buf = store_tensor(tensor_spec);
    auto buf2 = buf;
    _ops.copied_labels(buf2);
    EXPECT_EQ(buf, buf2);
    _ops.reclaim_labels(buf);
    EXPECT_NE(buf, buf2);
    buf.clear();
    auto loaded_spec = load_tensor_spec(buf2);
    _ops.reclaim_labels(buf2);
    EXPECT_EQ(tensor_spec, loaded_spec);
}

void
TensorBufferOperationsTest::assert_store_encode_decode(const TensorSpec& tensor_spec)
{
    auto buf = store_tensor(tensor_spec);
    auto encoded = encode_stored_tensor(buf);
    _ops.reclaim_labels(buf);
    const auto& factory = StreamedValueBuilderFactory::get();
    auto decoded = vespalib::eval::decode_value(encoded, factory);
    auto decoded_spec = TensorSpec::from_value(*decoded);
    EXPECT_EQ(tensor_spec, decoded_spec);
}

VESPA_GTEST_INSTANTIATE_TEST_SUITE_P(TensorBufferOperationsMultiTest,
                                     TensorBufferOperationsTest,
                                     testing::Values(TestParam("1d", {8, 16, 32, 40, 64}, TensorSpec(tensor_type_spec).add({{"x", "a"}}, 4.5)),
                                                     TestParam("1dmulti", {8, 16, 32, 40, 64}, TensorSpec(tensor_type_spec).add({{"x", "a"}}, 4.5).add({{"x", "c"}}, 4.25)),
                                                     TestParam("1dfloat", {4, 12, 20, 28, 36}, TensorSpec(float_tensor_type_spec).add({{"y", "aa"}}, 4.25)),
                                                     TestParam("2d", {8, 24, 40, 56, 80}, TensorSpec(tensor_type_2d_spec).add({{"x", "a"},{"y", "aa"}}, 4.75)),
                                                     TestParam("2dmixed", {8, 24, 48, 64, 96}, TensorSpec(tensor_type_2d_mixed_spec).add({{"x", "a"},{"y", 0}}, 4.5).add({{"x", "a"},{"y", 1}}, 4.25))),
                                     testing::PrintToStringParamName());

TEST_P(TensorBufferOperationsTest, array_sizes_are_calculated)
{
    EXPECT_EQ(GetParam()._array_sizes, get_array_sizes(5));
}

TEST_P(TensorBufferOperationsTest, tensor_can_be_stored_and_loaded)
{
    assert_store_load(GetParam()._tensor_spec);
}

TEST_P(TensorBufferOperationsTest, tensor_buffer_can_be_copied)
{
    assert_store_copy_load(GetParam()._tensor_spec);
}

TEST_P(TensorBufferOperationsTest, tensor_buffer_can_be_encoded)
{
    assert_store_encode_decode(GetParam()._tensor_spec);
}

GTEST_MAIN_RUN_ALL_TESTS()
<commit_msg>Deinline TestParam copy constructor.<commit_after>// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/searchlib/tensor/tensor_buffer_operations.h>
#include <vespa/eval/eval/simple_value.h>
#include <vespa/eval/eval/tensor_spec.h>
#include <vespa/eval/eval/value.h>
#include <vespa/eval/eval/value_codec.h>
#include <vespa/eval/streamed/streamed_value_builder_factory.h>
#include <vespa/vespalib/gtest/gtest.h>

using search::tensor::TensorBufferOperations;
using vespalib::eval::SimpleValue;
using vespalib::eval::StreamedValueBuilderFactory;
using vespalib::eval::TensorSpec;
using vespalib::eval::Value;
using vespalib::eval::ValueType;
using vespalib::eval::TypedCells;

const vespalib::string tensor_type_spec("tensor(x{})");
const vespalib::string tensor_type_2d_spec("tensor(x{},y{})");
const vespalib::string tensor_type_2d_mixed_spec("tensor(x{},y[2])");
const vespalib::string float_tensor_type_spec("tensor<float>(y{})");

struct TestParam
{
    vespalib::string    _name;
    std::vector<size_t> _array_sizes;
    TensorSpec          _tensor_spec;
    TestParam(vespalib::string name, std::vector<size_t> array_sizes, TensorSpec tensor_spec)
        : _name(std::move(name)),
          _array_sizes(std::move(array_sizes)),
          _tensor_spec(std::move(tensor_spec))
    {
    }
    TestParam(const TestParam&);
    ~TestParam();
};

TestParam::TestParam(const TestParam&) = default;

TestParam::~TestParam() = default;

std::ostream& operator<<(std::ostream& os, const TestParam& param)
{
    os << param._name;
    return os;
}

class TensorBufferOperationsTest : public testing::TestWithParam<TestParam>
{
protected:
    ValueType _tensor_type;
    TensorBufferOperations _ops;
    TensorBufferOperationsTest();
    ~TensorBufferOperationsTest() override;
    std::vector<size_t> get_array_sizes(uint32_t max_subspaces);
    std::vector<char> store_tensor(const Value& tensor);
    std::vector<char> store_tensor(const TensorSpec& spec);
    std::unique_ptr<Value> load_tensor(vespalib::ConstArrayRef<char> buf);
    TensorSpec load_tensor_spec(vespalib::ConstArrayRef<char> buf);
    vespalib::nbostream encode_stored_tensor(vespalib::ConstArrayRef<char> buf);
    void assert_store_load(const TensorSpec& tensor_spec);
    void assert_store_copy_load(const TensorSpec& tensor_spec);
    void assert_store_encode_decode(const TensorSpec& tensor_spec);
};

TensorBufferOperationsTest::TensorBufferOperationsTest()
    : testing::TestWithParam<TestParam>(),
      _tensor_type(ValueType::from_spec(GetParam()._tensor_spec.type())),
      _ops(_tensor_type)
{
}

TensorBufferOperationsTest::~TensorBufferOperationsTest() = default;

std::vector<size_t>
TensorBufferOperationsTest::get_array_sizes(uint32_t max_subspaces)
{
    std::vector<size_t> array_sizes;
    for (uint32_t num_subspaces = 0; num_subspaces < max_subspaces; ++num_subspaces) {
        array_sizes.emplace_back(_ops.get_array_size(num_subspaces));
    }
    return array_sizes;
}

std::vector<char>
TensorBufferOperationsTest::store_tensor(const Value& tensor)
{
    EXPECT_EQ(_tensor_type, tensor.type());
    uint32_t num_subspaces = tensor.index().size();
    auto array_size = _ops.get_array_size(num_subspaces);
    std::vector<char> buf;
    buf.resize(array_size);
    _ops.store_tensor(buf, tensor);
    return buf;
}

std::vector<char>
TensorBufferOperationsTest::store_tensor(const TensorSpec& spec)
{
    auto tensor = SimpleValue::from_spec(spec);
    return store_tensor(*tensor);
}

std::unique_ptr<Value>
TensorBufferOperationsTest::load_tensor(vespalib::ConstArrayRef<char> buf)
{
    return _ops.make_fast_view(buf, _tensor_type);
}

vespalib::nbostream
TensorBufferOperationsTest::encode_stored_tensor(vespalib::ConstArrayRef<char> buf)
{
    vespalib::nbostream out;
    _ops.encode_stored_tensor(buf, _tensor_type, out);
    return out;
}

TensorSpec
TensorBufferOperationsTest::load_tensor_spec(vespalib::ConstArrayRef<char> buf)
{
    auto loaded = load_tensor(buf);
    return TensorSpec::from_value(*loaded);
}

void
TensorBufferOperationsTest::assert_store_load(const TensorSpec& tensor_spec)
{
    auto buf = store_tensor(tensor_spec);
    auto loaded_spec = load_tensor_spec(buf);
    _ops.reclaim_labels(buf);
    EXPECT_EQ(tensor_spec, loaded_spec);
}

void
TensorBufferOperationsTest::assert_store_copy_load(const TensorSpec& tensor_spec)
{
    auto buf = store_tensor(tensor_spec);
    auto buf2 = buf;
    _ops.copied_labels(buf2);
    EXPECT_EQ(buf, buf2);
    _ops.reclaim_labels(buf);
    EXPECT_NE(buf, buf2);
    buf.clear();
    auto loaded_spec = load_tensor_spec(buf2);
    _ops.reclaim_labels(buf2);
    EXPECT_EQ(tensor_spec, loaded_spec);
}

void
TensorBufferOperationsTest::assert_store_encode_decode(const TensorSpec& tensor_spec)
{
    auto buf = store_tensor(tensor_spec);
    auto encoded = encode_stored_tensor(buf);
    _ops.reclaim_labels(buf);
    const auto& factory = StreamedValueBuilderFactory::get();
    auto decoded = vespalib::eval::decode_value(encoded, factory);
    auto decoded_spec = TensorSpec::from_value(*decoded);
    EXPECT_EQ(tensor_spec, decoded_spec);
}

VESPA_GTEST_INSTANTIATE_TEST_SUITE_P(TensorBufferOperationsMultiTest,
                                     TensorBufferOperationsTest,
                                     testing::Values(TestParam("1d", {8, 16, 32, 40, 64}, TensorSpec(tensor_type_spec).add({{"x", "a"}}, 4.5)),
                                                     TestParam("1dmulti", {8, 16, 32, 40, 64}, TensorSpec(tensor_type_spec).add({{"x", "a"}}, 4.5).add({{"x", "c"}}, 4.25)),
                                                     TestParam("1dfloat", {4, 12, 20, 28, 36}, TensorSpec(float_tensor_type_spec).add({{"y", "aa"}}, 4.25)),
                                                     TestParam("2d", {8, 24, 40, 56, 80}, TensorSpec(tensor_type_2d_spec).add({{"x", "a"},{"y", "aa"}}, 4.75)),
                                                     TestParam("2dmixed", {8, 24, 48, 64, 96}, TensorSpec(tensor_type_2d_mixed_spec).add({{"x", "a"},{"y", 0}}, 4.5).add({{"x", "a"},{"y", 1}}, 4.25))),
                                     testing::PrintToStringParamName());

TEST_P(TensorBufferOperationsTest, array_sizes_are_calculated)
{
    EXPECT_EQ(GetParam()._array_sizes, get_array_sizes(5));
}

TEST_P(TensorBufferOperationsTest, tensor_can_be_stored_and_loaded)
{
    assert_store_load(GetParam()._tensor_spec);
}

TEST_P(TensorBufferOperationsTest, tensor_buffer_can_be_copied)
{
    assert_store_copy_load(GetParam()._tensor_spec);
}

TEST_P(TensorBufferOperationsTest, tensor_buffer_can_be_encoded)
{
    assert_store_encode_decode(GetParam()._tensor_spec);
}

GTEST_MAIN_RUN_ALL_TESTS()
<|endoftext|>