<commit_before>// -*- c++ -*- ///////////////////////////////////////////////////////////////
//
// This file is part of Miro (The Middleware for Robots)
// Copyright (C) 1999-2013
// Department of Neural Information Processing, University of Ulm
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//

#define QT_ALTERNATE_QTSMANIP

#include "ConfigDocumentXML.h"
#include "Section.h"

#include "miroWidgets/ConfigFile.h"

#include "params/Generator.h"

#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QMenu>
#include <qstring.h>

#include <algorithm>
#include <cassert>
#include <iostream>

const QString ConfigDocumentXML::XML_DOCTYPE("MiroConfigDocument");
const QString ConfigDocumentXML::XML_TAG("config");

//------------------------------------------------------------------------------
// public methods

ConfigDocumentXML::ConfigDocumentXML(QDomDocument const& _document,
				     QTreeWidget * _treeWidget,
				     QObject * _parent, const char * _name) :
  Super(_document, _treeWidget, _parent, _name),
  menuAddSection_(NULL)
{
}

ConfigDocumentXML::~ConfigDocumentXML()
{}

//----------------------------------------------------------------------------
// inherited public methods

void
ConfigDocumentXML::contextMenu(QMenu& _menu)
{
  // The context menu has one QAction, "Add Section"
  // The "Add Section" menu is a submenu of the menu passed as argument.
  // Its signal is invoked when it is activated, not triggered.
  menuAddSection_ = _menu.addMenu(tr("Add Section"));

  Miro::CFG::QStringVector childSections;
  QTreeWidgetItem * const pTreeWidgetItem = treeWidgetItem();
  assert(pTreeWidgetItem != NULL);
  QTreeWidgetItem * const pParentTreeWidgetItem = pTreeWidgetItem->parent();
  if (pParentTreeWidgetItem != NULL)
  {
    // It is not the root, so it may have siblings
    for (int i = 0; i < pParentTreeWidgetItem->childCount(); ++i)
    {
      const QTreeWidgetItem * const pChildTreeWidgetItem =
	pParentTreeWidgetItem->child(i);
      assert(pChildTreeWidgetItem != NULL);
      const QString text = pChildTreeWidgetItem->text(0);
      childSections.push_back(text);
    }
  }

  // submenu: add all section names
  // not yet available in the document
  Miro::CFG::QStringVector sections =
    ConfigFile::instance()->description().groups();
  Miro::CFG::QStringVector::const_iterator first, last = sections.end();
  for (first = sections.begin(); first != last; ++first) {

    // if this section already exists, don't add it
    Miro::CFG::QStringVector::const_iterator i =
      std::find(childSections.begin(), childSections.end(), *first);
    if (i != childSections.end())
      continue;

    // count the final parameter classes in the section
    int itemCount = 0;
    Miro::CFG::GroupMap::const_iterator f, l;
    ConfigFile::instance()->description().getGroupedTypes(*first, f, l);
    for (; f != l; ++f) {
      if (f->second.isFinal()) {
	++itemCount;
      }
    }

    // if this section is empty, don't add it
    if (itemCount == 0)
      continue;

    // The name of the Action
    const QString name = *first;
    // From "http://qt-project.org/doc/qt4-8/qaction.html":
    // "We recommend that actions are created as children of the window they
    // are used in. In most cases, actions will be children of the application's
    // main window."
    // This class doesn't have a handle to any window.
    QWidget * const pActionParent = NULL;
    QAction * const pAction = new QAction(name, pActionParent);
    connect(pAction, SIGNAL(activated(int)), this, SLOT(onAddSection(int)));
    // Add the Action to the Menu
    menuAddSection_->addAction(pAction);
  }
}

//----------------------------------------------------------------------------
// public slots

void
ConfigDocumentXML::onAddSection(int _n)
{
  QDomElement config = document_.documentElement();
  QDomElement e = document_.createElement(Section::XML_TAG);
  e.setAttribute(Section::XML_ATTRIBUTE_KEY, menuAddSection_->text(_n));

  QDomNode n = config.firstChild();
  QDomNode newChild;

  if (config.firstChild().isNull())
    newChild = config.appendChild(e);
  else
    newChild = config.insertBefore(e, n);

  assert(!newChild.isNull());
  new Section(newChild,
	      treeWidgetItem(), NULL,
	      this, menuAddSection_->text(_n));
  setModified();
}

//------------------------------------------------------------------------------
// protected methods

void
ConfigDocumentXML::parse()
{
  QDomNode n = document_.firstChild();
  if (!n.isNull()) {
    QDomNode n1 = n.firstChild();
    QTreeWidgetItem * pre = NULL;
    while (!n1.isNull()) {
      QDomElement e = n1.toElement();
      if (!e.isNull() &&
	  e.tagName() == Section::XML_TAG) {
	Section * section =
	  new Section(e,
		      treeWidgetItem(), pre,
		      this, e.attribute("name"));
	pre = section->treeWidgetItem();
      }
      n1 = n1.nextSibling();
    }
  }
}
<commit_msg>Context menu wasn't filtering the sections<commit_after>// -*- c++ -*- ///////////////////////////////////////////////////////////////
//
// This file is part of Miro (The Middleware for Robots)
// Copyright (C) 1999-2013
// Department of Neural Information Processing, University of Ulm
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//

#define QT_ALTERNATE_QTSMANIP

#include "ConfigDocumentXML.h"
#include "Section.h"

#include "miroWidgets/ConfigFile.h"

#include "params/Generator.h"

#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QMenu>
#include <qstring.h>

#include <algorithm>
#include <cassert>

const QString ConfigDocumentXML::XML_DOCTYPE("MiroConfigDocument");
const QString ConfigDocumentXML::XML_TAG("config");

//------------------------------------------------------------------------------
// public methods

ConfigDocumentXML::ConfigDocumentXML(QDomDocument const& _document,
				     QTreeWidget * _treeWidget,
				     QObject * _parent, const char * _name) :
  Super(_document, _treeWidget, _parent, _name),
  menuAddSection_(NULL)
{
}

ConfigDocumentXML::~ConfigDocumentXML()
{}

//----------------------------------------------------------------------------
// inherited public methods

void
ConfigDocumentXML::contextMenu(QMenu& _menu)
{
  // The context menu has one QAction, "Add Section"
  // The "Add Section" menu is a submenu of the menu passed as argument.
  // Its signal is invoked when it is activated, not triggered.
  menuAddSection_ = _menu.addMenu(tr("Add Section"));

  // Construct a list of all siblings of the QTreeWidgetItem
  Miro::CFG::QStringVector childSections;
  // Fetch the QTreeWidgetItem
  QTreeWidgetItem * const pTreeWidgetItem = treeWidgetItem();
  assert(pTreeWidgetItem != NULL);
  // For each child of the QTreeWidgetItem
  for (int i = 0; i < pTreeWidgetItem->childCount(); ++i)
  {
      // Fetch the ith sibling
      const QTreeWidgetItem * const pChildTreeWidgetItem =
	pTreeWidgetItem->child(i);
      assert(pChildTreeWidgetItem != NULL);
      // Fetch the sibling's label text
      const QString text = pChildTreeWidgetItem->text(0);
      // Append the label text to the QStringVector
      childSections.push_back(text);
  }
  // The QStringVector should have as many elements as the parent has children
  assert(static_cast<size_t>(pTreeWidgetItem->childCount()) ==
	 static_cast<size_t>(childSections.size()));

  // submenu: add all section names not yet available in the document
  Miro::CFG::QStringVector sections =
    ConfigFile::instance()->description().groups();

  Miro::CFG::QStringVector::const_iterator first, last = sections.end();
  for (first = sections.begin(); first != last; ++first) {

    // if this section already exists, don't add it
    Miro::CFG::QStringVector::const_iterator i =
      std::find(childSections.begin(), childSections.end(), *first);
    if (i != childSections.end())
      continue;

    // count the final parameter classes in the section
    int itemCount = 0;
    Miro::CFG::GroupMap::const_iterator f, l;
    ConfigFile::instance()->description().getGroupedTypes(*first, f, l);
    for (; f != l; ++f) {
      if (f->second.isFinal()) {
	++itemCount;
      }
    }

    // if this section is empty, don't add it
    if (itemCount == 0)
      continue;

    // The name of the Action
    const QString name = *first;
    // From "http://qt-project.org/doc/qt4-8/qaction.html":
    // "We recommend that actions are created as children of the window they
    // are used in. In most cases, actions will be children of the application's
    // main window."
    // This class doesn't have a handle to any window.
    QWidget * const pActionParent = NULL;
    QAction * const pAction = new QAction(name, pActionParent);
    connect(pAction, SIGNAL(activated(int)), this, SLOT(onAddSection(int)));
    // Add the Action to the Menu
    menuAddSection_->addAction(pAction);
  }
}

//----------------------------------------------------------------------------
// public slots

void
ConfigDocumentXML::onAddSection(int _n)
{
  QDomElement config = document_.documentElement();
  QDomElement e = document_.createElement(Section::XML_TAG);
  e.setAttribute(Section::XML_ATTRIBUTE_KEY, menuAddSection_->text(_n));

  QDomNode n = config.firstChild();
  QDomNode newChild;

  if (config.firstChild().isNull())
    newChild = config.appendChild(e);
  else
    newChild = config.insertBefore(e, n);

  assert(!newChild.isNull());
  new Section(newChild,
	      treeWidgetItem(), NULL,
	      this, menuAddSection_->text(_n));
  setModified();
}

//------------------------------------------------------------------------------
// protected methods

void
ConfigDocumentXML::parse()
{
  QDomNode n = document_.firstChild();
  if (!n.isNull()) {
    QDomNode n1 = n.firstChild();
    QTreeWidgetItem * pre = NULL;
    while (!n1.isNull()) {
      QDomElement e = n1.toElement();
      if (!e.isNull() &&
	  e.tagName() == Section::XML_TAG) {
	Section * section =
	  new Section(e,
		      treeWidgetItem(), pre,
		      this, e.attribute("name"));
	pre = section->treeWidgetItem();
      }
      n1 = n1.nextSibling();
    }
  }
}
<|endoftext|>


<commit_before>// C++ General Utility Library (mailto:cgul@zethes.com)
// Copyright (C) 2012-2014, Joshua Brookover and Amber Thrall
// All rights reserved.

/** @file ImageHandler.cpp
 */

#include "ImageHandler.hpp"
#include "../Exceptions/ImageException.hpp"

#ifdef PNG_FOUND
#   include "PNG.hpp"
#endif

#ifdef JPEG_FOUND
#   include "JPEG.hpp"
#endif
#include "BMP.hpp"

_CGUL_EXPORT CGUL::ImageHandler::ImageHandler()
{
    // Add default image loaders
#   ifdef PNG_FOUND
    Register(new ImageLoaders::PNG());
#   endif
#   ifdef JPEG_FOUND
    Register(new ImageLoaders::JPEG());
#   endif
    Register(new ImageLoaders::BMP());
}

_CGUL_EXPORT CGUL::ImageHandler::~ImageHandler()
{
    for (Vector< ImageLoader* >::iterator itr = loaders.begin(), itrEnd = loaders.end(); itr != itrEnd; ++itr)
    {
        delete *itr;
    }
}

_CGUL_EXPORT CGUL::ImageHandler* CGUL::ImageHandler::GetInstance()
{
    static CGUL::ImageHandler instance;
    return &instance;
}

_CGUL_EXPORT void CGUL::ImageHandler::Register(ImageLoader* loader)
{
    loaders.push_back(loader);
}

_CGUL_EXPORT CGUL::ImageLoader* CGUL::ImageHandler::GetLoaderByName(const String& name)
{
    for (UInt32 i = 0; i < loaders.size(); i++)
    {
        if (loaders[i]->GetName() == name)
        {
            return loaders[i];
        }
    }
    return NULL;
}

_CGUL_EXPORT CGUL::ImageLoader* CGUL::ImageHandler::GetLoaderByExtension(const String& ext)
{
    for (UInt32 i = 0; i < loaders.size(); i++)
    {
        if (loaders[i]->GetExtension().GetLower() == ext.GetLower())
        {
            return loaders[i];
        }
    }
    return NULL;
}

_CGUL_EXPORT CGUL::ImageLoader* CGUL::ImageHandler::GetLoaderByFile(const String& file)
{
    for (UInt32 i = 0; i < loaders.size(); i++)
    {
        if (loaders[i]->CanLoad(file))
        {
            return loaders[i];
        }
    }
    return NULL;
}

_CGUL_EXPORT void CGUL::ImageHandler::GetAllLoaders(FixedList< ImageLoader* >* loaders)
{
    loaders->SetSize(this->loaders.size());
    Size count = 0;
    for (Vector< ImageLoader* >::iterator itr = this->loaders.begin(), itrEnd = this->loaders.end(); itr != itrEnd; ++itr)
    {
        loaders->Set(count++, *itr);
    }
}
<commit_msg>Commented out bitmap references. It's not added yet.<commit_after>// C++ General Utility Library (mailto:cgul@zethes.com)
// Copyright (C) 2012-2014, Joshua Brookover and Amber Thrall
// All rights reserved.

/** @file ImageHandler.cpp
 */

#include "ImageHandler.hpp"
#include "../Exceptions/ImageException.hpp"

#ifdef PNG_FOUND
#   include "PNG.hpp"
#endif

#ifdef JPEG_FOUND
#   include "JPEG.hpp"
#endif
//#include "BMP.hpp"

_CGUL_EXPORT CGUL::ImageHandler::ImageHandler()
{
    // Add default image loaders
#   ifdef PNG_FOUND
    Register(new ImageLoaders::PNG());
#   endif
#   ifdef JPEG_FOUND
    Register(new ImageLoaders::JPEG());
#   endif
    //Register(new ImageLoaders::BMP());
}

_CGUL_EXPORT CGUL::ImageHandler::~ImageHandler()
{
    for (Vector< ImageLoader* >::iterator itr = loaders.begin(), itrEnd = loaders.end(); itr != itrEnd; ++itr)
    {
        delete *itr;
    }
}

_CGUL_EXPORT CGUL::ImageHandler* CGUL::ImageHandler::GetInstance()
{
    static CGUL::ImageHandler instance;
    return &instance;
}

_CGUL_EXPORT void CGUL::ImageHandler::Register(ImageLoader* loader)
{
    loaders.push_back(loader);
}

_CGUL_EXPORT CGUL::ImageLoader* CGUL::ImageHandler::GetLoaderByName(const String& name)
{
    for (UInt32 i = 0; i < loaders.size(); i++)
    {
        if (loaders[i]->GetName() == name)
        {
            return loaders[i];
        }
    }
    return NULL;
}

_CGUL_EXPORT CGUL::ImageLoader* CGUL::ImageHandler::GetLoaderByExtension(const String& ext)
{
    for (UInt32 i = 0; i < loaders.size(); i++)
    {
        if (loaders[i]->GetExtension().GetLower() == ext.GetLower())
        {
            return loaders[i];
        }
    }
    return NULL;
}

_CGUL_EXPORT CGUL::ImageLoader* CGUL::ImageHandler::GetLoaderByFile(const String& file)
{
    for (UInt32 i = 0; i < loaders.size(); i++)
    {
        if (loaders[i]->CanLoad(file))
        {
            return loaders[i];
        }
    }
    return NULL;
}

_CGUL_EXPORT void CGUL::ImageHandler::GetAllLoaders(FixedList< ImageLoader* >* loaders)
{
    loaders->SetSize(this->loaders.size());
    Size count = 0;
    for (Vector< ImageLoader* >::iterator itr = this->loaders.begin(), itrEnd = this->loaders.end(); itr != itrEnd; ++itr)
    {
        loaders->Set(count++, *itr);
    }
}
<|endoftext|>


<commit_before>#ifndef EXECUTORS_H
#define EXECUTORS_H

#include "processes.hpp"
#include "objects.hpp"
#include "reader.hpp" // for Bytecode classes
#include "types.hpp"

#include <map>

#include <boost/smart_ptr.hpp>

/*
  hl functions are represented by a Closure structure, which has an
  attached bytecode_t array.

  Calling convention:

  proc.stack[0] *must* be a Closure
  !! for now, at least.  in the future we will change this so that
  !! calls to non-Closure objects will be transformed to calls to
  !! the global <axiom>call*, which *should* be a Closure
  !! -- almkglor

  proc.stack[0] contains the closure.  If it is a "normal"
  function, proc.stack[1] is the "continuation" function
  and proc.stack[2..n] are the parameters.
  proc.stack.size() is the number of parameters including
  the function itself and the continuation.

  If it is a "continuation" function, proc.stack[1] is always
  the return value. proc.stack.size() will be 2.

  Functions never return.
*/

#define PASTE_SYMBOLS(x,y) x##y

/*
  Not necessary when using GCC.
  NOTE!  We retain this and even add references to
  an _e_bytecode_label type so that modders who
  happen to use *only* GCC will remember to update
  the declarations for the benefit of non-GCC
  users.
*/

#define DECLARE_BYTECODES enum _e_bytecode_label {
#define BYTECODE_ENUM(x) PASTE_SYMBOLS(_bytecode_, x)
#define A_BYTECODE(x) BYTECODE_ENUM(x),
#define END_DECLARE_BYTECODES __null_bytecode };
DECLARE_BYTECODES
	A_BYTECODE(apply)
	A_BYTECODE(apply_invert_k)
	A_BYTECODE(apply_list)
	A_BYTECODE(apply_k_release)
        A_BYTECODE(build_closure)
	A_BYTECODE(build_k_closure)
	A_BYTECODE(build_k_closure_recreate)
	A_BYTECODE(build_k_closure_reuse)
	A_BYTECODE(car)
	A_BYTECODE(car_local_push)
	A_BYTECODE(car_clos_push)
	A_BYTECODE(ccc)
	A_BYTECODE(cdr)
	A_BYTECODE(cdr_local_push)
	A_BYTECODE(cdr_clos_push)
	A_BYTECODE(check_vars)
	A_BYTECODE(closure_ref)
	A_BYTECODE(composeo)
	A_BYTECODE(composeo_continuation)
	A_BYTECODE(cons)
        A_BYTECODE(const_ref)
	A_BYTECODE(b_continue)
	A_BYTECODE(continue_local)
	A_BYTECODE(continue_on_clos)
	A_BYTECODE(global)
	A_BYTECODE(global_set)
	A_BYTECODE(halt)
	A_BYTECODE(halt_local_push)
	A_BYTECODE(halt_clos_push)
	A_BYTECODE(jmp_nil)
  //A_BYTECODE(if_local)
	A_BYTECODE(b_int)
	A_BYTECODE(b_float)
	A_BYTECODE(lit_nil)
	A_BYTECODE(lit_t)
	A_BYTECODE(local)
	A_BYTECODE(monomethod)
	A_BYTECODE(reducto)
        A_BYTECODE(reducto_continuation)
	A_BYTECODE(rep)
	A_BYTECODE(rep_local_push)
	A_BYTECODE(rep_clos_push)
	A_BYTECODE(scar)
	A_BYTECODE(scdr)
	A_BYTECODE(sv)
	A_BYTECODE(sv_local_push)
	A_BYTECODE(sv_clos_push)
	A_BYTECODE(sv_ref)
	A_BYTECODE(sv_ref_local_push)
	A_BYTECODE(sv_ref_clos_push)
	A_BYTECODE(sv_set)
	A_BYTECODE(sym)
	A_BYTECODE(symeval)
	A_BYTECODE(table_create)
	A_BYTECODE(table_ref)
	A_BYTECODE(table_sref)
	A_BYTECODE(table_map)
	A_BYTECODE(tag)
	A_BYTECODE(type)
	A_BYTECODE(type_local_push)
	A_BYTECODE(type_clos_push)
	A_BYTECODE(variadic)
	/*maybe organize by alphabetical order of bytecodes ^^*/
	A_BYTECODE(do_executor)
	A_BYTECODE(plus)
	A_BYTECODE(minus)
	A_BYTECODE(mul)
	A_BYTECODE(div)
	A_BYTECODE(mod)
END_DECLARE_BYTECODES

#ifdef __GNUC__

// use indirect goto when using GCC

typedef void* _bytecode_label;
#define DISPATCH_BYTECODES \
        bytecode_t *pc = expect_type<Bytecode>(clos->code())->getCode();\
	goto *(pc->op);
#define NEXT_BYTECODE goto *((++pc)->op)
#define BYTECODE(x) BYTECODE_ENUM(x); PASTE_SYMBOLS(label_b_, x)
#define THE_BYTECODE_LABEL(x) &&PASTE_SYMBOLS(label_b_, x)

#else // __GNUC__

// use an enum when using standard C

typedef enum _e_bytecode_label _bytecode_label;
#define DISPATCH_BYTECODES \
	bytecode_t *pc = expect_type<Bytecode>(clos->code())->getCode();\
	switch(pc->op)
#define NEXT_BYTECODE {pc++; continue;}
#define BYTECODE(x) case BYTECODE_ENUM(x)
#define THE_BYTECODE_LABEL(x) BYTECODE_ENUM(x)

#endif // __GNUC__

class Process;
class ProcessStack;

class Executor;

class ExecutorTable : public std::map<Symbol*, Executor*> {
public:
	~ExecutorTable();
};

/*
 * Generic executor
 * An executor represents a built-in function
 */
class Executor {
private:
  // table of available executors
  static ExecutorTable tbl;
public:
  // register an executor in the system
  // no locks: executors should be registered only during startup
  static void reg(Symbol *s, Executor *e) {
    tbl[s] = e;
  }
  // no locks: tbl stucture is immutable after initialization
  static Executor* findExecutor(Symbol *s) {
    std::map<Symbol*,Executor*>::iterator it = tbl.find(s);
    if (it==tbl.end())
      return NULL;
    else
      return it->second;
  }
  virtual ~Executor() {}
  // return true if a function call must be performed, false otherwise
  virtual bool run(Process & proc, size_t & reductions) = 0;
};

inline ExecutorTable::~ExecutorTable() {
	for(iterator i = begin(); i != end(); ++i) {
		delete i->second;
	}
}

/*
 * The bytecode read by the reader should be assembled before execution
 * an assembled bytecode is an array of bytecode_t
 * The executor can assume that the bytecodes are correct
 * The assembler must have already catched eventual errors
 */
struct bytecode_t {
  _bytecode_label op; // operation code
  intptr_t val; // simple value argument (may be invalid)
};

// a bytecode object contains a table of complex constants such as gensyms
class Bytecode : public GenericDerivedVariadic<Bytecode> {
private:
  // TODO: rearrange to let code be shared between different processes
  // ?? what exactly does the above comment mean? -- almkglor
  boost::shared_array<bytecode_t> code;
  size_t codeSize;
  size_t nextCode; // next free position in code
  size_t nextPos; // next free position in variadic space

public:
  Bytecode(size_t sz)
    : GenericDerivedVariadic<Bytecode>(sz), codeSize(0), nextCode(0),
      nextPos(0) {}
  virtual ~Bytecode() {}

  Object::ref& operator[](size_t i) {
    if (i < size())
      return index(i);
    else
      throw_HlError("internal: trying to access objects in bytecode with an index too large!");
  }

  Object::ref type(void) const {
    return Object::to_ref(symbol_bytecode);
  }

  bytecode_t* getCode() { return code.get(); }

  // close a complex constants
  size_t closeOver(Object::ref obj) {
    if (nextPos >= size())
      throw_HlError("internal: trying to close over, but there is no space left in Bytecode");
    index(nextPos) = obj;
    return nextPos++;
  }

  // add a bytecode at the end of the sequence
  void push(bytecode_t b);
  void push(_bytecode_label op, intptr_t val);
  void push(Symbol *s, intptr_t val);
  void push(const char *s, intptr_t val);

  void traverse_references(GenericTraverser *gt) {
    for(size_t i = 0; i < nextPos; ++i) {
      gt->traverse(index(i));
    }
  }
};

#define INTPARAM(name) intptr_t name = pc->val
#define SYMPARAM(name) Symbol *name = (Symbol*)pc->val
#define FLOATPARAM(name) Float *name = (Float*)pc->val

class AsOp {
public:
  // expect arguments on the stack:
  //  - sequence arg (stack top)
  //  - simple arg
  //  - Bytecode object being assembled
  //  - seq being assembled
  virtual void assemble(Process & proc) = 0;
};

class Assembler {
private:
  typedef std::map<Symbol*, AsOp*> sym_op_tbl;
  sym_op_tbl tbl;

  // extracts a value pointer/immediate object, throwing away the type tag
  static intptr_t simpleVal(Object::ref sa);
public:
  ~Assembler() {
    for (sym_op_tbl::iterator i = tbl.begin(); i!=tbl.end(); i++)
      delete i->second;
  }

  // register a new assembler operation
  template <class T>
  void reg(Symbol* s) { tbl[s] = new T(); }

  // do the assembly, leave a Bytecode on the stack, expect a sequence on
  // the stack
  void go(Process & proc);

  // count number of comples constants in seq (not recursive)
  static size_t countConsts(Object::ref seq);
  // tells if an object is a complex one or not
  static bool isComplexConst(Object::ref obj);
};

extern Assembler assembler;

// Execute a given process
ProcessStatus execute(Process & proc, size_t& reductions, Process*& Q, bool init = 0);

#endif // EXECUTORS_H
<commit_msg>executors.hpp: removed solved TODO<commit_after>#ifndef EXECUTORS_H
#define EXECUTORS_H

#include "processes.hpp"
#include "objects.hpp"
#include "reader.hpp" // for Bytecode classes
#include "types.hpp"

#include <map>

#include <boost/smart_ptr.hpp>

/*
  hl functions are represented by a Closure structure, which has an
  attached bytecode_t array.

  Calling convention:

  proc.stack[0] *must* be a Closure
  !! for now, at least.  in the future we will change this so that
  !! calls to non-Closure objects will be transformed to calls to
  !! the global <axiom>call*, which *should* be a Closure
  !! -- almkglor

  proc.stack[0] contains the closure.  If it is a "normal"
  function, proc.stack[1] is the "continuation" function
  and proc.stack[2..n] are the parameters.
  proc.stack.size() is the number of parameters including
  the function itself and the continuation.

  If it is a "continuation" function, proc.stack[1] is always
  the return value. proc.stack.size() will be 2.

  Functions never return.
*/

#define PASTE_SYMBOLS(x,y) x##y

/*
  Not necessary when using GCC.
  NOTE!  We retain this and even add references to
  an _e_bytecode_label type so that modders who
  happen to use *only* GCC will remember to update
  the declarations for the benefit of non-GCC
  users.
*/

#define DECLARE_BYTECODES enum _e_bytecode_label {
#define BYTECODE_ENUM(x) PASTE_SYMBOLS(_bytecode_, x)
#define A_BYTECODE(x) BYTECODE_ENUM(x),
#define END_DECLARE_BYTECODES __null_bytecode };
DECLARE_BYTECODES
	A_BYTECODE(apply)
	A_BYTECODE(apply_invert_k)
	A_BYTECODE(apply_list)
	A_BYTECODE(apply_k_release)
        A_BYTECODE(build_closure)
	A_BYTECODE(build_k_closure)
	A_BYTECODE(build_k_closure_recreate)
	A_BYTECODE(build_k_closure_reuse)
	A_BYTECODE(car)
	A_BYTECODE(car_local_push)
	A_BYTECODE(car_clos_push)
	A_BYTECODE(ccc)
	A_BYTECODE(cdr)
	A_BYTECODE(cdr_local_push)
	A_BYTECODE(cdr_clos_push)
	A_BYTECODE(check_vars)
	A_BYTECODE(closure_ref)
	A_BYTECODE(composeo)
	A_BYTECODE(composeo_continuation)
	A_BYTECODE(cons)
        A_BYTECODE(const_ref)
	A_BYTECODE(b_continue)
	A_BYTECODE(continue_local)
	A_BYTECODE(continue_on_clos)
	A_BYTECODE(global)
	A_BYTECODE(global_set)
	A_BYTECODE(halt)
	A_BYTECODE(halt_local_push)
	A_BYTECODE(halt_clos_push)
	A_BYTECODE(jmp_nil)
  //A_BYTECODE(if_local)
	A_BYTECODE(b_int)
	A_BYTECODE(b_float)
	A_BYTECODE(lit_nil)
	A_BYTECODE(lit_t)
	A_BYTECODE(local)
	A_BYTECODE(monomethod)
	A_BYTECODE(reducto)
        A_BYTECODE(reducto_continuation)
	A_BYTECODE(rep)
	A_BYTECODE(rep_local_push)
	A_BYTECODE(rep_clos_push)
	A_BYTECODE(scar)
	A_BYTECODE(scdr)
	A_BYTECODE(sv)
	A_BYTECODE(sv_local_push)
	A_BYTECODE(sv_clos_push)
	A_BYTECODE(sv_ref)
	A_BYTECODE(sv_ref_local_push)
	A_BYTECODE(sv_ref_clos_push)
	A_BYTECODE(sv_set)
	A_BYTECODE(sym)
	A_BYTECODE(symeval)
	A_BYTECODE(table_create)
	A_BYTECODE(table_ref)
	A_BYTECODE(table_sref)
	A_BYTECODE(table_map)
	A_BYTECODE(tag)
	A_BYTECODE(type)
	A_BYTECODE(type_local_push)
	A_BYTECODE(type_clos_push)
	A_BYTECODE(variadic)
	/*maybe organize by alphabetical order of bytecodes ^^*/
	A_BYTECODE(do_executor)
	A_BYTECODE(plus)
	A_BYTECODE(minus)
	A_BYTECODE(mul)
	A_BYTECODE(div)
	A_BYTECODE(mod)
END_DECLARE_BYTECODES

#ifdef __GNUC__

// use indirect goto when using GCC

typedef void* _bytecode_label;
#define DISPATCH_BYTECODES \
        bytecode_t *pc = expect_type<Bytecode>(clos->code())->getCode();\
	goto *(pc->op);
#define NEXT_BYTECODE goto *((++pc)->op)
#define BYTECODE(x) BYTECODE_ENUM(x); PASTE_SYMBOLS(label_b_, x)
#define THE_BYTECODE_LABEL(x) &&PASTE_SYMBOLS(label_b_, x)

#else // __GNUC__

// use an enum when using standard C

typedef enum _e_bytecode_label _bytecode_label;
#define DISPATCH_BYTECODES \
	bytecode_t *pc = expect_type<Bytecode>(clos->code())->getCode();\
	switch(pc->op)
#define NEXT_BYTECODE {pc++; continue;}
#define BYTECODE(x) case BYTECODE_ENUM(x)
#define THE_BYTECODE_LABEL(x) BYTECODE_ENUM(x)

#endif // __GNUC__

class Process;
class ProcessStack;

class Executor;

class ExecutorTable : public std::map<Symbol*, Executor*> {
public:
	~ExecutorTable();
};

/*
 * Generic executor
 * An executor represents a built-in function
 */
class Executor {
private:
  // table of available executors
  static ExecutorTable tbl;
public:
  // register an executor in the system
  // no locks: executors should be registered only during startup
  static void reg(Symbol *s, Executor *e) {
    tbl[s] = e;
  }
  // no locks: tbl stucture is immutable after initialization
  static Executor* findExecutor(Symbol *s) {
    std::map<Symbol*,Executor*>::iterator it = tbl.find(s);
    if (it==tbl.end())
      return NULL;
    else
      return it->second;
  }
  virtual ~Executor() {}
  // return true if a function call must be performed, false otherwise
  virtual bool run(Process & proc, size_t & reductions) = 0;
};

inline ExecutorTable::~ExecutorTable() {
	for(iterator i = begin(); i != end(); ++i) {
		delete i->second;
	}
}

/*
 * The bytecode read by the reader should be assembled before execution
 * an assembled bytecode is an array of bytecode_t
 * The executor can assume that the bytecodes are correct
 * The assembler must have already catched eventual errors
 */
struct bytecode_t {
  _bytecode_label op; // operation code
  intptr_t val; // simple value argument (may be invalid)
};

// a bytecode object contains a table of complex constants such as gensyms
class Bytecode : public GenericDerivedVariadic<Bytecode> {
private:
  boost::shared_array<bytecode_t> code;
  size_t codeSize;
  size_t nextCode; // next free position in code
  size_t nextPos; // next free position in variadic space

public:
  Bytecode(size_t sz)
    : GenericDerivedVariadic<Bytecode>(sz), codeSize(0), nextCode(0),
      nextPos(0) {}
  virtual ~Bytecode() {}

  Object::ref& operator[](size_t i) {
    if (i < size())
      return index(i);
    else
      throw_HlError("internal: trying to access objects in bytecode with an index too large!");
  }

  Object::ref type(void) const {
    return Object::to_ref(symbol_bytecode);
  }

  bytecode_t* getCode() { return code.get(); }

  // close a complex constants
  size_t closeOver(Object::ref obj) {
    if (nextPos >= size())
      throw_HlError("internal: trying to close over, but there is no space left in Bytecode");
    index(nextPos) = obj;
    return nextPos++;
  }

  // add a bytecode at the end of the sequence
  void push(bytecode_t b);
  void push(_bytecode_label op, intptr_t val);
  void push(Symbol *s, intptr_t val);
  void push(const char *s, intptr_t val);

  void traverse_references(GenericTraverser *gt) {
    for(size_t i = 0; i < nextPos; ++i) {
      gt->traverse(index(i));
    }
  }
};

#define INTPARAM(name) intptr_t name = pc->val
#define SYMPARAM(name) Symbol *name = (Symbol*)pc->val
#define FLOATPARAM(name) Float *name = (Float*)pc->val

class AsOp {
public:
  // expect arguments on the stack:
  //  - sequence arg (stack top)
  //  - simple arg
  //  - Bytecode object being assembled
  //  - seq being assembled
  virtual void assemble(Process & proc) = 0;
};

class Assembler {
private:
  typedef std::map<Symbol*, AsOp*> sym_op_tbl;
  sym_op_tbl tbl;

  // extracts a value pointer/immediate object, throwing away the type tag
  static intptr_t simpleVal(Object::ref sa);
public:
  ~Assembler() {
    for (sym_op_tbl::iterator i = tbl.begin(); i!=tbl.end(); i++)
      delete i->second;
  }

  // register a new assembler operation
  template <class T>
  void reg(Symbol* s) { tbl[s] = new T(); }

  // do the assembly, leave a Bytecode on the stack, expect a sequence on
  // the stack
  void go(Process & proc);

  // count number of comples constants in seq (not recursive)
  static size_t countConsts(Object::ref seq);
  // tells if an object is a complex one or not
  static bool isComplexConst(Object::ref obj);
};

extern Assembler assembler;

// Execute a given process
ProcessStatus execute(Process & proc, size_t& reductions, Process*& Q, bool init = 0);

#endif // EXECUTORS_H
<|endoftext|>


<commit_before>#pragma once

#include <Eigen/Dense>
#include <unsupported/Eigen/MatrixFunctions>

#include <map>
#include <vector>

using std::vector;
using std::map;

namespace mcl_cpp
{
	class mcl
	{
	public:
		//! @brief MCL ctor. Register a callback function to return the cluster results
		mcl(const Eigen::MatrixXd& Min, std::function< void(size_t cluster_j, size_t member_i) > f) : M(Min), ClusterResultCallback(f) {}

		/*! @brief Apply Markov clustering algorithm with specified parameters and return clusters
			For each cluster, returns the list of node-ids that belong to that cluster
			*/
		Eigen::MatrixXd cluster_mcl(double expand_factor = 2, double inflate_factor = 2, double max_loop = 10, double mult_factor = 1)
		{
			Eigen::MatrixXd M_selfloop = M + mult_factor * Eigen::MatrixXd::Identity(M.cols(), M.rows());
			Eigen::MatrixXd M_normalized = normalize(M_selfloop);
			int i;
			for (i = 0; i < max_loop && !stop(M_normalized, i); i++)
			{
				inflate(M_normalized, inflate_factor);
				expand(M_normalized, expand_factor);
			}
			for (auto row = 0; row<M_normalized.rows(); row++)
			{
				if (M_normalized(row, row) > 0)
				{
					for (auto col = 0; col < M_normalized.cols(); col++)
					{
						if (M_normalized.coeff(row, col) > 0)
							ClusterResultCallback(row, col);
					}
				}
			}
			return std::move(M_normalized);
		}

	private:
		bool stop(const Eigen::MatrixXd& in, int i)
		{
			auto m = in*in;
			auto diff = (m - in);
			auto mx = diff.maxCoeff(), mn = diff.minCoeff();
			return (diff.maxCoeff() == diff.minCoeff());
		}

		Eigen::MatrixXd normalize(Eigen::MatrixXd& in)
		{
			auto one_over_col_sum = in.colwise().sum().cwiseInverse();
			Eigen::MatrixXd M_normalized = in * one_over_col_sum.asDiagonal();
			return std::move(M_normalized);
		}

		void expand(Eigen::MatrixXd& in, double expand_factor)
		{
			Eigen::MatrixPower<Eigen::MatrixXd> Apow(in);
			in = Apow(expand_factor);
		}

		void inflate(Eigen::MatrixXd& in, double inflate_factor)
		{
			auto lam = [inflate_factor](double x) -> double { return std::pow(x, inflate_factor); };
			in = in.unaryExpr(lam);
			in = normalize(in);
		}

		const Eigen::MatrixXd & M;
		std::function< void(size_t cls_i, size_t mem_j) > ClusterResultCallback;
	};

}<commit_msg>Auto does some bad things on Visual Studio 2012.<commit_after>#pragma once

#include <Eigen/Dense>
#include <unsupported/Eigen/MatrixFunctions>

#include <map>
#include <vector>

using std::vector;
using std::map;

namespace mcl_cpp
{
	class mcl
	{
	public:
		//! @brief MCL ctor. Register a callback function to return the cluster results
		mcl(const Eigen::MatrixXd& Min, std::function< void(size_t cluster_j, size_t member_i) > f) : M(Min), ClusterResultCallback(f) {}

		/*! @brief Apply Markov clustering algorithm with specified parameters and return clusters
			For each cluster, returns the list of node-ids that belong to that cluster
			*/
		Eigen::MatrixXd cluster_mcl(double expand_factor = 2, double inflate_factor = 2, double max_loop = 10, double mult_factor = 1)
		{
			Eigen::MatrixXd M_selfloop = M + mult_factor * Eigen::MatrixXd::Identity(M.cols(), M.rows());
			Eigen::MatrixXd M_normalized = normalize(M_selfloop);
			int i;
			for (i = 0; i < max_loop && !stop(M_normalized, i); i++)
			{
				inflate(M_normalized, inflate_factor);
				expand(M_normalized, expand_factor);
			}
			for (auto row = 0; row<M_normalized.rows(); row++)
			{
				if (M_normalized(row, row) > 0)
				{
					for (auto col = 0; col < M_normalized.cols(); col++)
					{
						if (M_normalized.coeff(row, col) > 0)
							ClusterResultCallback(row, col);
					}
				}
			}
			return std::move(M_normalized);
		}

	private:
		bool stop(const Eigen::MatrixXd& in, int i)
		{
			Eigen::MatrixXd m = in*in;
			Eigen::MatrixXd diff = (m - in);
			double mx = diff.maxCoeff(), mn = diff.minCoeff();
			return (diff.maxCoeff() == diff.minCoeff());
		}

		Eigen::MatrixXd normalize(Eigen::MatrixXd& in)
		{
			Eigen::MatrixXd one_over_col_sum = in.colwise().sum().cwiseInverse();
			Eigen::MatrixXd M_normalized = in * one_over_col_sum.asDiagonal();
			return std::move(M_normalized);
		}

		void expand(Eigen::MatrixXd& in, double expand_factor)
		{
			Eigen::MatrixPower<Eigen::MatrixXd> Apow(in);
			in = Apow(expand_factor);
		}

		void inflate(Eigen::MatrixXd& in, double inflate_factor)
		{
			auto lam = [inflate_factor](double x) -> double { return std::pow(x, inflate_factor); };
			in = in.unaryExpr(lam);
			in = normalize(in);
		}

		const Eigen::MatrixXd & M;
		std::function< void(size_t cls_i, size_t mem_j) > ClusterResultCallback;
	};

}<|endoftext|>


<commit_before>/*******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2011, 2017 OpenWorm.
 * http://openworm.org
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the MIT License
 * which accompanies this distribution, and is available at
 * http://opensource.org/licenses/MIT
 *
 * Contributors:
 *     	OpenWorm - http://openworm.org/people.html
 *
 * 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 X_SPHMODEL
#define X_SPHMODEL

#include "particle.h"
#include "util/x_error.h"
#include <array>
#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <regex>
#include <string>
#include <vector>

namespace x_engine {
namespace model {
enum LOADMODE { NOMODE = -1, PARAMS, MODEL, POS, VEL };

template <class T = float, class container = std::vector<particle<T>>>
class sph_model {
  typedef std::map<std::string, size_t> sph_config;

public:
  sph_model(const std::string &config_file) {
    config = {{"particles", 0}, {"x_max", 0}, {"x_min", 0}, {"y_max", 0},
              {"y_min", 0},     {"z_max", 0}, {"z_min", 0}};
    read_model(config_file);
    std::cout << "Model was loaded: " << particles.size() << " partticles."
              << std::endl;
  }
  const sph_config &get_config() const { return config; }

private:
  container particles;
  sph_config config;
  std::map<std::string, T> phys_consts;
  std::shared_ptr<std::array<T, 4>> get_vector(const std::string &line) {
    std::shared_ptr<std::array<T, 4>> v(new std::array<T, 4>());
    std::stringstream ss(line);
    ss >> (*v)[0] >> (*v)[1] >> (*v)[2] >> (*v)[3]; // TODO check here!!!
    return v;
  }
  void read_model(const std::string &model_file) {
    std::ifstream file(model_file.c_str(), std::ios_base::binary);
    LOADMODE mode = NOMODE;
    bool is_model_mode = false;
    int index = 0;
    if (file.is_open()) {
      while (file.good()) {
        std::string cur_line;
        std::getline(file, cur_line);
        if (mode == NOMODE) {
          cur_line.erase(std::remove(cur_line.begin(), cur_line.end(), ' '),
                         cur_line.end());
          cur_line.erase(std::remove(cur_line.begin(), cur_line.end(), '\t'),
                         cur_line.end());
        }
        if (cur_line.compare("parametrs[") == 0) {
          mode = PARAMS;
          continue;
        } else if (cur_line.compare("model[") == 0) {
          mode = MODEL;
          is_model_mode = true;
          continue;
        } else if (cur_line.compare("position[") == 0) {
          mode = POS;
          continue;
        } else if (cur_line.compare("velocity[") == 0) {
          mode = VEL;
          continue;
        } else if (cur_line.compare("]") == 0) {
          mode = NOMODE;
          continue;
        }
        if (mode == PARAMS) {
          std::regex rgx("[\\t ]*(\\w+) *: *(\\d+) *([//]*.*)");
          std::smatch matches;
          if (std::regex_search(cur_line, matches, rgx)) {
            if (matches.size() > 2) {
              if (config.find(matches[1]) != config.end()) {
                config[matches[1]] =
                    static_cast<size_t>(stoi(matches[2].str()));
                continue;
              }
            } else {
              std::string msg = x_engine::make_msg(
                  "Problem with parsing parametrs:", matches[0].str(),
                  "Please check parametrs.");
              throw parser_error(msg);
            }
          } else {
            throw parser_error(
                "Please check parametrs section there are no parametrs.");
          }
        }
        if (is_model_mode) {
          switch (mode) {
          case POS: {
            particle<T> p;
            p.pos = *get_vector(cur_line);
            particles.push_back(p);
            break;
          }
          case VEL: {
            if (index >= particles.size())
              throw parser_error(
                  "Config file problem. Velocities more than partiles is.");
            particles[index].vel = *get_vector(cur_line);
            ++index;
            break;
          }
          default: { break; }
          }
        }
      }
    }
    file.close();
  }
};
}
}
#endif // X_SPHMODEL
<commit_msg>work with reader<commit_after>/*******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2011, 2017 OpenWorm.
 * http://openworm.org
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the MIT License
 * which accompanies this distribution, and is available at
 * http://opensource.org/licenses/MIT
 *
 * Contributors:
 *     	OpenWorm - http://openworm.org/people.html
 *
 * 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 X_SPHMODEL
#define X_SPHMODEL

#include "particle.h"
#include "util/x_error.h"
#include <array>
#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <regex>
#include <string>
#include <vector>

namespace x_engine {
namespace model {
enum LOADMODE { NOMODE = -1, PARAMS, MODEL, POS, VEL };

template <class T = float, class container = std::vector<particle<T>>>
class sph_model {
  typedef std::map<std::string, size_t> sph_config;

public:
  sph_model(const std::string &config_file) {
    config = {{"particles", 0}, {"x_max", 0}, {"x_min", 0}, {"y_max", 0},
              {"y_min", 0},     {"z_max", 0}, {"z_min", 0}};
    read_model(config_file);
    std::cout << "Model was loaded: " << particles.size() << " partticles."
              << std::endl;
  }
  const sph_config &get_config() const { return config; }

private:
  container particles;
  sph_config config;
  std::map<std::string, T> phys_consts;
  std::shared_ptr<std::array<T, 4>> get_vector(const std::string &line) {
    std::shared_ptr<std::array<T, 4>> v(new std::array<T, 4>());
    std::stringstream ss(line);
    ss >> (*v)[0] >> (*v)[1] >> (*v)[2] >> (*v)[3]; // TODO check here!!!
    return v;
  }
  void read_model(const std::string &model_file) {
    std::ifstream file(model_file.c_str(), std::ios_base::binary);
    LOADMODE mode = NOMODE;
    bool is_model_mode = false;
    int index = 0;
    if (file.is_open()) {
      while (file.good()) {
        std::string cur_line;
        std::getline(file, cur_line);
        auto i_space = cur_line.find_first_not_of(" ");
        auto i_tab = cur_line.find_first_not_of("\t");
        cur_line.erase(
            std::remove(cur_line.begin(), cur_line.begin() + i_space, ' '),
            cur_line.end());
        cur_line.erase(
            std::remove(cur_line.begin(), cur_line.end() + i_tab, '\t'),
            cur_line.end());
        if (cur_line.compare("parametrs[") == 0) {
          mode = PARAMS;
          continue;
        } else if (cur_line.compare("model[") == 0) {
          mode = MODEL;
          is_model_mode = true;
          continue;
        } else if (cur_line.compare("position[") == 0) {
          mode = POS;
          continue;
        } else if (cur_line.compare("velocity[") == 0) {
          mode = VEL;
          continue;
        } else if (cur_line.compare("]") == 0) {
          mode = NOMODE;
          continue;
        }
        if (mode == PARAMS) {
          std::regex rgx("[\\t ]*(\\w+) *: *(\\d+) *([//]*.*)");
          std::smatch matches;
          if (std::regex_search(cur_line, matches, rgx)) {
            if (matches.size() > 2) {
              if (config.find(matches[1]) != config.end()) {
                config[matches[1]] =
                    static_cast<size_t>(stoi(matches[2].str()));
                continue;
              }
            } else {
              std::string msg = x_engine::make_msg(
                  "Problem with parsing parametrs:", matches[0].str(),
                  "Please check parametrs.");
              throw parser_error(msg);
            }
          } else {
            throw parser_error(
                "Please check parametrs section there are no parametrs.");
          }
        }
        if (is_model_mode) {
          switch (mode) {
          case POS: {
            particle<T> p;
            p.pos = *get_vector(cur_line);
            particles.push_back(p);
            break;
          }
          case VEL: {
            if (index >= particles.size())
              throw parser_error(
                  "Config file problem. Velocities more than partiles is.");
            particles[index].vel = *get_vector(cur_line);
            ++index;
            break;
          }
          default: { break; }
          }
        }
      }
    }
    file.close();
  }
};
}
}
#endif // X_SPHMODEL
<|endoftext|>


<commit_before>#ifndef ___GFTOOLS_KMESH_HPP___
#define ___GFTOOLS_KMESH_HPP___

#include "Grid.hpp"
#include <numeric>

namespace GFTools {

class KMesh : public Grid<RealType, KMesh>
{
public:
    int _points;
    KMesh(size_t n_points);
    KMesh(const KMesh& rhs);
    KMesh(KMesh &&rhs);
    KMesh(){};
    KMesh& operator=(KMesh &&rhs){_points = rhs._points; _vals.swap(rhs._vals); return (*this);};
    KMesh& operator=(const KMesh &rhs){_points = rhs._points; _vals = rhs._vals; return (*this);};
    std::tuple <bool, size_t, RealType> find (RealType in) const ;
    template <class Obj> auto integrate(const Obj &in) const ->decltype(in(_vals[0]));
    template <class Obj, typename ...OtherArgTypes> auto integrate(const Obj &in, OtherArgTypes... Args) const -> decltype(in(_vals[0],Args...));
    //template <class Obj> auto gridIntegrate(std::vector<Obj> &in) const -> Obj;
    template <class Obj> auto getValue(Obj &in, RealType x) const ->decltype(in[0]);
    template <class Obj> auto getValue(Obj &in, point x) const ->decltype(in[0]);
    point shift(point in, point shift_arg) const;
    template <class ArgType> point shift(point in, ArgType shift_arg) const;
    template <class ArgType> RealType shift(RealType in, ArgType shift_arg) const;
};

struct KMeshPatch : public KMesh
{
    std::map<size_t,size_t> _map_vals;
public:
    const KMesh& _parent;
    size_t _npoints;
    using KMesh::_vals;
    KMeshPatch(const KMesh& parent, std::vector<size_t> indices);
    KMeshPatch(const KMesh& parent);
    template <class Obj> auto getValue(Obj &in, RealType x) const ->decltype(in[0]);
    template <class Obj> auto getValue(Obj &in, KMesh::point x) const ->decltype(in[0]);
    size_t getIndex(KMesh::point x) const;
};
template <>
inline std::ostream& operator<<(std::ostream& lhs, const __num_format< typename KMesh::point> &in){lhs << std::setprecision(in._prec) << RealType(in._v._val); return lhs;};

//
// KMesh
//

KMesh::KMesh(size_t n_points):
Grid<RealType,KMesh>(0,n_points,[n_points](size_t in){return 2.0*PI/n_points*in;}),
_points(n_points)
{
}

KMesh::KMesh(const KMesh& rhs):Grid(rhs._vals),_points(rhs._points)
{
}

KMesh::KMesh(KMesh &&rhs):Grid(rhs._vals),_points(rhs._points)
{
}

inline std::tuple <bool, size_t, RealType> KMesh::find (RealType in) const
{
    assert(in>=0 && in < 2.0*PI);
    int n = std::lround(in/2.0/PI*_points);
    if (n<0) { ERROR("KMesh point is out of bounds, " << in << "<" << 0); return std::make_tuple(0,0,0); };
    if (n==_points) n=0;
    if (n>_points) { ERROR("KMesh point is out of bounds, " << in << "> 2*PI"); return std::make_tuple(0,_points,0); };
    RealType weight=in/2.0/PI*_points-RealType(n);
    return std::make_tuple (1,n,weight);
}

template <class Obj>
inline auto KMesh::getValue(Obj &in, RealType x) const ->decltype(in[0])
{
    const auto find_result=this->find(x);
    if (!std::get<0>(find_result)) throw (exWrongIndex());
    return in[std::get<1>(find_result)];
}

template <class Obj>
inline auto KMesh::getValue(Obj &in, KMesh::point x) const ->decltype(in[0])
{
    if (x._index < _vals.size() && x == _vals[x._index])
    return in[x._index];
    else {
        #ifndef NDEBUG
        ERROR ("Point not found");
        #endif
        return this->getValue(in, RealType(x));
         };
}

template <class Obj>
auto KMesh::integrate(const Obj &in) const -> decltype(in(_vals[0]))
{
    decltype(in(_vals[0])) R = in(RealType(_vals[0]));
    R=std::accumulate(_vals.begin()+1, _vals.end(), R,[&](decltype(in(_vals[0]))& y,const decltype(_vals[0]) &x) {return y+in(x);});
    return R/_points;
}

template <class Obj, typename ...OtherArgTypes>
auto KMesh::integrate(const Obj &in, OtherArgTypes... Args) const -> decltype(in(_vals[0],Args...))
{
    decltype(in(_vals[0],Args...)) R = in(_vals[0],Args...);
    R=std::accumulate(_vals.begin()+1, _vals.end(), R,[&](decltype(in(_vals[0]))& y,const decltype(_vals[0]) &x) {return y+in(x,Args...);});
    return R/_points;
}

template <class ArgType>
inline RealType KMesh::shift(RealType in, ArgType shift_arg) const
{
    assert (in>=0 && in < 2.0*PI);
    //if (std::abs(RealType(shift_arg))<std::numeric_limits<RealType>::epsilon()) return in;
    RealType out;
    out = in + RealType(shift_arg);
    out-= std::floor(out/(2.0*PI))*2.0*PI;
    return out;
}

template <class ArgType>
inline typename KMesh::point KMesh::shift(point in, ArgType shift_arg) const
{
    if (std::abs(RealType(shift_arg))<std::numeric_limits<RealType>::epsilon()) return in;
    point out;
    out._val = this->shift(in._val, shift_arg);
    auto find_result = this->find(out._val);
    if (!std::get<0>(find_result)) throw (exWrongIndex());
    out._index = std::get<1>(find_result);
    return (*this)[out._index];
}

inline typename KMesh::point KMesh::shift(point in, point shift_arg) const
{
    size_t index = (in._index + shift_arg._index)%_points;
    #ifndef NDEBUG
    RealType val = this->shift(in._val, shift_arg._val);
    if (std::abs(val - _vals[index])>1e-3) throw (exWrongIndex());
    #endif
    //out._val = _vals[out._index];
    return _vals[index];
}

//
// KMeshPatch
//

KMeshPatch::KMeshPatch(const KMesh& parent, std::vector<size_t> indices):
    _parent(parent),
    _npoints(indices.size())
{
    _vals.resize(_npoints);
    for (size_t i=0; i<_npoints; ++i) {
        _vals[i]=_parent[indices[i]];
        _map_vals[size_t(_vals[i])] = i;
        }
}

KMeshPatch::KMeshPatch(const KMesh& parent):
    _parent(parent),
    _npoints(parent.getSize())
{
    _vals = parent.getPoints();
     for (size_t i=0; i<_npoints; ++i) {
        _map_vals[size_t(_vals[i])] = i;
        }
}

template <class Obj>
inline auto KMeshPatch::getValue(Obj &in, RealType x) const ->decltype(in[0])
{
    const auto find_result=_parent.find(x);
    if (!std::get<0>(find_result)) throw (exWrongIndex());
    return getValue(in, KMesh::point(std::get<1>(find_result), x));
}

template <class Obj>
inline auto KMeshPatch::getValue(Obj &in, KMesh::point x) const ->decltype(in[0])
{
    return in[getIndex(x)];
}

inline size_t KMeshPatch::getIndex(KMesh::point x) const
{
    auto f1 = _map_vals.find(size_t(x));
    if (f1!=_map_vals.end()) { return f1->second; }
    else throw (exWrongIndex());
}

} // end of namespace GFTools
#endif // endif :: ifndef ___GFTOOLS_KMESH_HPP___
<commit_msg>KMesh: default constructors and variable length<commit_after>#ifndef ___GFTOOLS_KMESH_HPP___
#define ___GFTOOLS_KMESH_HPP___

#include "Grid.hpp"
#include <numeric>

namespace GFTools {

class KMesh : public Grid<RealType, KMesh>
{
    mutable RealType _domain_len = 2.0*PI;
public:
    int _points;
    KMesh(size_t n_points, RealType len = 2.0*PI);
    KMesh(const KMesh& rhs) = default;
    KMesh(KMesh &&rhs) = default;
    KMesh() = default;
    KMesh& operator=(KMesh &&rhs) {_points = rhs._points; _domain_len = rhs._domain_len; _vals.swap(rhs._vals); return (*this);};
    KMesh& operator=(const KMesh &rhs) {_points = rhs._points; _domain_len = rhs._domain_len;_vals = rhs._vals; return (*this);};
    std::tuple <bool, size_t, RealType> find (RealType in) const ;
    template <class Obj> auto integrate(const Obj &in) const ->decltype(in(_vals[0]));
    template <class Obj, typename ...OtherArgTypes> auto integrate(const Obj &in, OtherArgTypes... Args) const -> decltype(in(_vals[0],Args...));
    //template <class Obj> auto gridIntegrate(std::vector<Obj> &in) const -> Obj;
    template <class Obj> auto getValue(Obj &in, RealType x) const ->decltype(in[0]);
    template <class Obj> auto getValue(Obj &in, point x) const ->decltype(in[0]);
    point shift(point in, point shift_arg) const;
    template <class ArgType> point shift(point in, ArgType shift_arg) const;
    template <class ArgType> RealType shift(RealType in, ArgType shift_arg) const;
};

struct KMeshPatch : public KMesh
{
    std::map<size_t,size_t> _map_vals;
public:
    const KMesh& _parent;
    size_t _npoints;
    using KMesh::_vals;
    KMeshPatch(const KMesh& parent, std::vector<size_t> indices);
    KMeshPatch(const KMesh& parent);
    template <class Obj> auto getValue(Obj &in, RealType x) const ->decltype(in[0]);
    template <class Obj> auto getValue(Obj &in, KMesh::point x) const ->decltype(in[0]);
    size_t getIndex(KMesh::point x) const;
};
template <>
inline std::ostream& operator<<(std::ostream& lhs, const __num_format< typename KMesh::point> &in){lhs << std::setprecision(in._prec) << RealType(in._v._val); return lhs;};

//
// KMesh
//

KMesh::KMesh(size_t n_points, RealType len):
Grid<RealType,KMesh>(0,n_points,[n_points,len](size_t in){return len/n_points*in;}),
_domain_len(len),
_points(n_points)
{
}
/*
KMesh::KMesh(const KMesh& rhs):Grid(rhs._vals),_points(rhs._points)
{
}

KMesh::KMesh(KMesh &&rhs):Grid(rhs._vals),_points(rhs._points)
{
}
*/
inline std::tuple <bool, size_t, RealType> KMesh::find (RealType in) const
{
    assert(in>=0 && in < _domain_len);
    int n = std::lround(in/_domain_len*_points);
    if (n<0) { ERROR("KMesh point is out of bounds, " << in << "<" << 0); return std::make_tuple(0,0,0); };
    if (n==_points) n=0;
    if (n>_points) { ERROR("KMesh point is out of bounds, " << in << ">" << _domain_len); return std::make_tuple(0,_points,0); };
    RealType weight=in/_domain_len*_points-RealType(n);
    return std::make_tuple (1,n,weight);
}

template <class Obj>
inline auto KMesh::getValue(Obj &in, RealType x) const ->decltype(in[0])
{
    const auto find_result=this->find(x);
    if (!std::get<0>(find_result)) throw (exWrongIndex());
    return in[std::get<1>(find_result)];
}

template <class Obj>
inline auto KMesh::getValue(Obj &in, KMesh::point x) const ->decltype(in[0])
{
    if (x._index < _vals.size() && x == _vals[x._index])
    return in[x._index];
    else {
        #ifndef NDEBUG
        ERROR ("Point not found");
        #endif
        return this->getValue(in, RealType(x));
         };
}

template <class Obj>
auto KMesh::integrate(const Obj &in) const -> decltype(in(_vals[0]))
{
    decltype(in(_vals[0])) R = in(RealType(_vals[0]));
    R=std::accumulate(_vals.begin()+1, _vals.end(), R,[&](decltype(in(_vals[0]))& y,const decltype(_vals[0]) &x) {return y+in(x);});
    return R/_points;
}

template <class Obj, typename ...OtherArgTypes>
auto KMesh::integrate(const Obj &in, OtherArgTypes... Args) const -> decltype(in(_vals[0],Args...))
{
    decltype(in(_vals[0],Args...)) R = in(_vals[0],Args...);
    R=std::accumulate(_vals.begin()+1, _vals.end(), R,[&](decltype(in(_vals[0]))& y,const decltype(_vals[0]) &x) {return y+in(x,Args...);});
    return R/_points;
}

template <class ArgType>
inline RealType KMesh::shift(RealType in, ArgType shift_arg) const
{
    assert (in>=0 && in < _domain_len);
    //if (std::abs(RealType(shift_arg))<std::numeric_limits<RealType>::epsilon()) return in;
    RealType out;
    out = in + RealType(shift_arg);
    out-= std::floor(out/_domain_len)*_domain_len;
    return out;
}

template <class ArgType>
inline typename KMesh::point KMesh::shift(point in, ArgType shift_arg) const
{
    if (std::abs(RealType(shift_arg))<std::numeric_limits<RealType>::epsilon()) return in;
    point out;
    out._val = this->shift(in._val, shift_arg);
    auto find_result = this->find(out._val);
    if (!std::get<0>(find_result)) throw (exWrongIndex());
    out._index = std::get<1>(find_result);
    return (*this)[out._index];
}

inline typename KMesh::point KMesh::shift(point in, point shift_arg) const
{
    size_t index = (in._index + shift_arg._index)%_points;
    #ifndef NDEBUG
    RealType val = this->shift(in._val, shift_arg._val);
    if (std::abs(val - _vals[index])>1e-3) throw (exWrongIndex());
    #endif
    //out._val = _vals[out._index];
    return _vals[index];
}

//
// KMeshPatch
//

KMeshPatch::KMeshPatch(const KMesh& parent, std::vector<size_t> indices):
    _parent(parent),
    _npoints(indices.size())
{
    _vals.resize(_npoints);
    for (size_t i=0; i<_npoints; ++i) {
        _vals[i]=_parent[indices[i]];
        _map_vals[size_t(_vals[i])] = i;
        }
}

KMeshPatch::KMeshPatch(const KMesh& parent):
    _parent(parent),
    _npoints(parent.getSize())
{
    _vals = parent.getPoints();
     for (size_t i=0; i<_npoints; ++i) {
        _map_vals[size_t(_vals[i])] = i;
        }
}

template <class Obj>
inline auto KMeshPatch::getValue(Obj &in, RealType x) const ->decltype(in[0])
{
    const auto find_result=_parent.find(x);
    if (!std::get<0>(find_result)) throw (exWrongIndex());
    return getValue(in, KMesh::point(std::get<1>(find_result), x));
}

template <class Obj>
inline auto KMeshPatch::getValue(Obj &in, KMesh::point x) const ->decltype(in[0])
{
    return in[getIndex(x)];
}

inline size_t KMeshPatch::getIndex(KMesh::point x) const
{
    auto f1 = _map_vals.find(size_t(x));
    if (f1!=_map_vals.end()) { return f1->second; }
    else throw (exWrongIndex());
}

} // end of namespace GFTools
#endif // endif :: ifndef ___GFTOOLS_KMESH_HPP___
<|endoftext|>


<commit_before>/***********************************************************************************************************************
 **
 ** Copyright (c) 2011, 2014 ETH Zurich
 ** 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 ETH Zurich 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 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **
 **********************************************************************************************************************/

#include "Cursor.h"
#include "../items/Item.h"
#include "../items/ItemStyle.h"

namespace Visualization {

Cursor::Cursor(Item* owner, CursorType type, Item* visualization)
	: owner_{owner}, visualization_{nullptr}, type_{type}, notLocationEquivalent_{false}
{
	if (visualization) setVisualization(visualization);
}

Cursor::Cursor(const Cursor& other) :	position_{other.position_}, region_{other.region_}, owner_{other.owner_},
		type_{other.type_}, notLocationEquivalent_{other.notLocationEquivalent_}
{}

Cursor::~Cursor()
{
	setVisualization(nullptr);
}

Cursor* Cursor::clone() const
{
	return new Cursor(*this);
}

void Cursor::update()
{
	if (type_ == BoxCursor)
	{
		setRegion( owner_->boundingRect().toRect() );
		setPosition( region_.center() );
	}
}

Item* Cursor::owner() const
{
	return owner_;
}

void Cursor::setVisualization(Item* visualization)
{
	SAFE_DELETE_ITEM(visualization_);
	visualization_ = visualization;

	if (visualization_)
	{
		auto item = owner();
		while (item)
		{
			if (item->flags() & Item::ItemIgnoresTransformations)
			{
				visualization_->setFlag(Item::ItemIgnoresTransformations);
				break;
			}
			item = item->parent();
		}
	}
}

bool Cursor::isSame(Cursor* other)
{
	return owner() == other->owner() && position() == other->position();
}

bool Cursor::isAtBoundary() const
{
	return false;
}

bool Cursor::isLocationEquivalent(Cursor* c)
{
	return isLocationEquivalent(c->notLocationEquivalent(), c->type(), c->isAtBoundary(), c->owner());
}

bool Cursor::isLocationEquivalent(bool otherNotLocationEquivalent, CursorType otherType, bool otherIsAtBoundary,
		Item* otherOwner)
{
	if (otherNotLocationEquivalent || notLocationEquivalent() ) return false;
	if (otherType != type() || otherType == BoxCursor) return false;
	if (!otherIsAtBoundary && ! isAtBoundary()) return false;
	if (owner() == otherOwner) return false;
	if (!( owner()->isAncestorOf(otherOwner) && allowEquivalentCursorsAcrossBoundaries(owner(), otherOwner))
			&& !(otherOwner->isAncestorOf(owner()) && allowEquivalentCursorsAcrossBoundaries(otherOwner, owner()) ) )
		return false;

	return true;
}

bool Cursor::allowEquivalentCursorsAcrossBoundaries(Item* parent, Item* child)
{
	if (!parent->style()->allowEquivalentCursorsThroughBoundary()) return false;
	while (child != parent)
	{
		if (!child->style()->allowEquivalentCursorsThroughBoundary()) return false;
		child = child->parent();
	};
	return true;
}

QRect Cursor::sceneRegion()
{
	return owner()->mapToScene(region()).boundingRect().toRect();
}

}
<commit_msg>remove semicolon after loop<commit_after>/***********************************************************************************************************************
 **
 ** Copyright (c) 2011, 2014 ETH Zurich
 ** 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 ETH Zurich 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 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **
 **********************************************************************************************************************/

#include "Cursor.h"
#include "../items/Item.h"
#include "../items/ItemStyle.h"

namespace Visualization {

Cursor::Cursor(Item* owner, CursorType type, Item* visualization)
	: owner_{owner}, visualization_{nullptr}, type_{type}, notLocationEquivalent_{false}
{
	if (visualization) setVisualization(visualization);
}

Cursor::Cursor(const Cursor& other) :	position_{other.position_}, region_{other.region_}, owner_{other.owner_},
		type_{other.type_}, notLocationEquivalent_{other.notLocationEquivalent_}
{}

Cursor::~Cursor()
{
	setVisualization(nullptr);
}

Cursor* Cursor::clone() const
{
	return new Cursor(*this);
}

void Cursor::update()
{
	if (type_ == BoxCursor)
	{
		setRegion( owner_->boundingRect().toRect() );
		setPosition( region_.center() );
	}
}

Item* Cursor::owner() const
{
	return owner_;
}

void Cursor::setVisualization(Item* visualization)
{
	SAFE_DELETE_ITEM(visualization_);
	visualization_ = visualization;

	if (visualization_)
	{
		auto item = owner();
		while (item)
		{
			if (item->flags() & Item::ItemIgnoresTransformations)
			{
				visualization_->setFlag(Item::ItemIgnoresTransformations);
				break;
			}
			item = item->parent();
		}
	}
}

bool Cursor::isSame(Cursor* other)
{
	return owner() == other->owner() && position() == other->position();
}

bool Cursor::isAtBoundary() const
{
	return false;
}

bool Cursor::isLocationEquivalent(Cursor* c)
{
	return isLocationEquivalent(c->notLocationEquivalent(), c->type(), c->isAtBoundary(), c->owner());
}

bool Cursor::isLocationEquivalent(bool otherNotLocationEquivalent, CursorType otherType, bool otherIsAtBoundary,
		Item* otherOwner)
{
	if (otherNotLocationEquivalent || notLocationEquivalent() ) return false;
	if (otherType != type() || otherType == BoxCursor) return false;
	if (!otherIsAtBoundary && ! isAtBoundary()) return false;
	if (owner() == otherOwner) return false;
	if (!( owner()->isAncestorOf(otherOwner) && allowEquivalentCursorsAcrossBoundaries(owner(), otherOwner))
			&& !(otherOwner->isAncestorOf(owner()) && allowEquivalentCursorsAcrossBoundaries(otherOwner, owner()) ) )
		return false;

	return true;
}

bool Cursor::allowEquivalentCursorsAcrossBoundaries(Item* parent, Item* child)
{
	if (!parent->style()->allowEquivalentCursorsThroughBoundary()) return false;
	while (child != parent)
	{
		if (!child->style()->allowEquivalentCursorsThroughBoundary()) return false;
		child = child->parent();
	}
	return true;
}

QRect Cursor::sceneRegion()
{
	return owner()->mapToScene(region()).boundingRect().toRect();
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/focus/accelerator_handler.h"

#include <bitset>
#include <gtk/gtk.h>
#if defined(HAVE_XINPUT2)
#include <X11/extensions/XInput2.h>
#else
#include <X11/Xlib.h>
#endif

#include "views/accelerator.h"
#include "views/events/event.h"
#include "views/focus/focus_manager.h"
#include "views/ime/input_method.h"
#include "views/touchui/touch_factory.h"
#include "views/widget/root_view.h"
#include "views/widget/widget_gtk.h"

namespace views {

namespace {

Widget* FindWidgetForGdkWindow(GdkWindow* gdk_window) {
  gpointer data = NULL;
  gdk_window_get_user_data(gdk_window, &data);
  GtkWidget* gtk_widget = reinterpret_cast<GtkWidget*>(data);
  if (!gtk_widget || !GTK_IS_WIDGET(gtk_widget)) {
    DLOG(WARNING) << "no GtkWidget found for that GdkWindow";
    return NULL;
  }
  NativeWidget* widget = NativeWidget::GetNativeWidgetForNativeView(gtk_widget);

  if (!widget) {
    DLOG(WARNING) << "no WidgetGtk found for that GtkWidget";
    return NULL;
  }
  return widget->GetWidget();
}

#if defined(HAVE_XINPUT2)
bool X2EventIsTouchEvent(XEvent* xev) {
  // TODO(sad): Determine if the captured event is a touch-event.
  XGenericEventCookie* cookie = &xev->xcookie;
  switch (cookie->evtype) {
    case XI_ButtonPress:
    case XI_ButtonRelease:
    case XI_Motion: {
      // Is the event coming from a touch device?
      return TouchFactory::GetInstance()->IsTouchDevice(
          static_cast<XIDeviceEvent*>(cookie->data)->sourceid);
    }
    default:
      return false;
  }
}
#endif  // HAVE_XINPUT2

}  // namespace

#if defined(HAVE_XINPUT2)
bool DispatchX2Event(RootView* root, XEvent* xev) {
  XGenericEventCookie* cookie = &xev->xcookie;
  bool touch_event = false;

  if (X2EventIsTouchEvent(xev)) {
    // Hide the cursor when a touch event comes in.
    TouchFactory::GetInstance()->SetCursorVisible(false, false);
    touch_event = true;

    // Create a TouchEvent, and send it off to |root|. If the event
    // is processed by |root|, then return. Otherwise let it fall through so it
    // can be used (if desired) as a mouse event.
    Event::FromNativeEvent2 from_native;
    TouchEvent touch(xev, from_native);
    if (root->OnTouchEvent(touch) != views::View::TOUCH_STATUS_UNKNOWN)
      return true;
  }

  switch (cookie->evtype) {
    case XI_KeyPress:
    case XI_KeyRelease: {
      // TODO(sad): We don't capture XInput2 events from keyboard yet.
      break;
    }
    case XI_ButtonPress:
    case XI_ButtonRelease:
    case XI_Motion: {
      // Scrolling the wheel generates press/release events with button id's 4
      // and 5. In case of a wheelscroll, we do not want to show the cursor.
      XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(cookie->data);
      if (xievent->detail == 4 || xievent->detail == 5) {
        Event::FromNativeEvent2 from_native;
        MouseWheelEvent wheelev(xev, from_native);
        return root->OnMouseWheel(wheelev);
      }

      Event::FromNativeEvent2 from_native;
      MouseEvent mouseev(xev, from_native);
      if (!touch_event) {
        // Show the cursor, and decide whether or not the cursor should be
        // automatically hidden after a certain time of inactivity.
        int button_flags = mouseev.flags() & (ui::EF_RIGHT_BUTTON_DOWN |
            ui::EF_MIDDLE_BUTTON_DOWN | ui::EF_LEFT_BUTTON_DOWN);
        bool start_timer = false;

        switch (cookie->evtype) {
          case XI_ButtonPress:
            start_timer = false;
            break;
          case XI_ButtonRelease:
            // For a release, start the timer if this was only button pressed
            // that is being released.
            if (button_flags == ui::EF_RIGHT_BUTTON_DOWN ||
                button_flags == ui::EF_LEFT_BUTTON_DOWN ||
                button_flags == ui::EF_MIDDLE_BUTTON_DOWN)
              start_timer = true;
            break;
          case XI_Motion:
            start_timer = !button_flags;
            break;
        }
        TouchFactory::GetInstance()->SetCursorVisible(true, start_timer);
      }

      // Dispatch the event.
      switch (cookie->evtype) {
        case XI_ButtonPress:
          return root->OnMousePressed(mouseev);
        case XI_ButtonRelease:
          root->OnMouseReleased(mouseev);
          return true;
        case XI_Motion: {
          if (mouseev.type() == ui::ET_MOUSE_DRAGGED) {
            return root->OnMouseDragged(mouseev);
          } else {
            root->OnMouseMoved(mouseev);
            return true;
          }
        }
      }
    }
  }

  return false;
}

#endif  // HAVE_XINPUT2

bool DispatchXEvent(XEvent* xev) {
  GdkDisplay* gdisp = gdk_display_get_default();
  XID xwindow = xev->xany.window;

#if defined(HAVE_XINPUT2)
  if (xev->type == GenericEvent) {
    if (!TouchFactory::GetInstance()->ShouldProcessXI2Event(xev))
      return true;  // Consume the event.

    XGenericEventCookie* cookie = &xev->xcookie;
    if (cookie->evtype == XI_HierarchyChanged) {
      TouchFactory::GetInstance()->UpdateDeviceList(cookie->display);
      return true;
    }

    XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(cookie->data);
    xwindow = xiev->event;
  }
#endif

  GdkWindow* gwind = gdk_window_lookup_for_display(gdisp, xwindow);
  Widget* widget = FindWidgetForGdkWindow(gwind);
  if (widget) {
    RootView* root = widget->GetRootView();
    switch (xev->type) {
      case KeyPress:
      case KeyRelease: {
        Event::FromNativeEvent2 from_native;
        KeyEvent keyev(xev, from_native);
        InputMethod* ime = widget->GetInputMethod();
        // Always dispatch key events to the input method first, to make sure
        // that the input method's hotkeys work all time.
        if (ime) {
          ime->DispatchKeyEvent(keyev);
          return true;
        }
        return widget->OnKeyEvent(keyev);
      }

      case ButtonPress:
      case ButtonRelease: {
        if (xev->xbutton.button == 4 || xev->xbutton.button == 5) {
          // Scrolling the wheel triggers button press/release events.
          Event::FromNativeEvent2 from_native;
          MouseWheelEvent wheelev(xev, from_native);
          return root->OnMouseWheel(wheelev);
        } else {
          Event::FromNativeEvent2 from_native;
          MouseEvent mouseev(xev, from_native);
          if (xev->type == ButtonPress) {
            return root->OnMousePressed(mouseev);
          } else {
            root->OnMouseReleased(mouseev);
            return true;  // Assume the event has been processed to make sure we
                          // don't process it twice.
          }
        }
      }

      case MotionNotify: {
        Event::FromNativeEvent2 from_native;
        MouseEvent mouseev(xev, from_native);
        if (mouseev.type() == ui::ET_MOUSE_DRAGGED) {
          return root->OnMouseDragged(mouseev);
        } else {
          root->OnMouseMoved(mouseev);
          return true;
        }
      }

#if defined(HAVE_XINPUT2)
      case GenericEvent: {
        return DispatchX2Event(root, xev);
      }
#endif
    }
  }

  return false;
}

#if defined(HAVE_XINPUT2)
void SetTouchDeviceList(std::vector<unsigned int>& devices) {
  TouchFactory::GetInstance()->SetTouchDeviceList(devices);
}
#endif

AcceleratorHandler::AcceleratorHandler() {}

bool AcceleratorHandler::Dispatch(GdkEvent* event) {
  gtk_main_do_event(event);
  return true;
}

base::MessagePumpGlibXDispatcher::DispatchStatus
    AcceleratorHandler::DispatchX(XEvent* xev) {
  return DispatchXEvent(xev) ?
      base::MessagePumpGlibXDispatcher::EVENT_PROCESSED :
      base::MessagePumpGlibXDispatcher::EVENT_IGNORED;
}

}  // namespace views
<commit_msg>Refactor some mouse/wheel/touch XEvent handling. Delegate logic to Widget; nix most direct RootView uses.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/focus/accelerator_handler.h"

#include <bitset>
#include <gtk/gtk.h>
#if defined(HAVE_XINPUT2)
#include <X11/extensions/XInput2.h>
#else
#include <X11/Xlib.h>
#endif

#include "views/accelerator.h"
#include "views/events/event.h"
#include "views/focus/focus_manager.h"
#include "views/ime/input_method.h"
#include "views/touchui/touch_factory.h"
#include "views/widget/root_view.h"
#include "views/widget/widget_gtk.h"

namespace views {

namespace {

Widget* FindWidgetForGdkWindow(GdkWindow* gdk_window) {
  gpointer data = NULL;
  gdk_window_get_user_data(gdk_window, &data);
  GtkWidget* gtk_widget = reinterpret_cast<GtkWidget*>(data);
  if (!gtk_widget || !GTK_IS_WIDGET(gtk_widget)) {
    DLOG(WARNING) << "no GtkWidget found for that GdkWindow";
    return NULL;
  }
  NativeWidget* widget = NativeWidget::GetNativeWidgetForNativeView(gtk_widget);

  if (!widget) {
    DLOG(WARNING) << "no WidgetGtk found for that GtkWidget";
    return NULL;
  }
  return widget->GetWidget();
}

}  // namespace

#if defined(HAVE_XINPUT2)
bool DispatchX2Event(Widget* widget, XEvent* xev) {
  XGenericEventCookie* cookie = &xev->xcookie;
  switch (cookie->evtype) {
    case XI_KeyPress:
    case XI_KeyRelease: {
      // TODO(sad): We don't capture XInput2 events from keyboard yet.
      break;
    }
    case XI_ButtonPress:
    case XI_ButtonRelease:
    case XI_Motion: {
      XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(cookie->data);
      Event::FromNativeEvent2 from_native;

      // Scrolling the wheel generates press/release events with button id's 4
      // and 5. In case of a wheelscroll, we do not want to show the cursor.
      if (xievent->detail == 4 || xievent->detail == 5) {
        MouseWheelEvent wheelev(xev, from_native);
        return widget->OnMouseEvent(wheelev);
      }

      MouseEvent mouseev(xev, from_native);
      // TODO(sad): Determine if the captured event is a touch-event.
      // Is the event coming from a touch device?
      if (TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid)) {
        // Hide the cursor when a touch event comes in.
        TouchFactory::GetInstance()->SetCursorVisible(false, false);
        // If the TouchEvent is processed by |root|, then return. Otherwise let
        // it fall through so it can be used as a MouseEvent, if desired.
        TouchEvent touch(xev, from_native);
        RootView* root = widget->GetRootView();
        if (root->OnTouchEvent(touch) != views::View::TOUCH_STATUS_UNKNOWN)
          return true;
      } else {
        // Show the cursor. Start a timer to hide the cursor after a delay on
        // move (not drag) events, or if the only button pressed is released.
        bool start_timer = mouseev.type() == ui::ET_MOUSE_MOVED;
        start_timer |= mouseev.type() == ui::ET_MOUSE_RELEASED &&
                       (mouseev.IsOnlyLeftMouseButton() ||
                        mouseev.IsOnlyMiddleMouseButton() ||
                        mouseev.IsOnlyRightMouseButton());
        TouchFactory::GetInstance()->SetCursorVisible(true, start_timer);
      }
      return widget->OnMouseEvent(mouseev);
    }
  }
  return false;
}

#endif  // HAVE_XINPUT2

bool DispatchXEvent(XEvent* xev) {
  GdkDisplay* gdisp = gdk_display_get_default();
  XID xwindow = xev->xany.window;

#if defined(HAVE_XINPUT2)
  if (xev->type == GenericEvent) {
    if (!TouchFactory::GetInstance()->ShouldProcessXI2Event(xev))
      return true;  // Consume the event.

    XGenericEventCookie* cookie = &xev->xcookie;
    if (cookie->evtype == XI_HierarchyChanged) {
      TouchFactory::GetInstance()->UpdateDeviceList(cookie->display);
      return true;
    }

    XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(cookie->data);
    xwindow = xiev->event;
  }
#endif

  GdkWindow* gwind = gdk_window_lookup_for_display(gdisp, xwindow);
  Widget* widget = FindWidgetForGdkWindow(gwind);
  if (widget) {
    Event::FromNativeEvent2 from_native;
    switch (xev->type) {
      case KeyPress:
      case KeyRelease: {
        KeyEvent keyev(xev, from_native);
        InputMethod* ime = widget->GetInputMethod();
        // Always dispatch key events to the input method first, to make sure
        // that the input method's hotkeys work all time.
        if (ime) {
          ime->DispatchKeyEvent(keyev);
          return true;
        }
        return widget->OnKeyEvent(keyev);
      }
      case ButtonPress:
      case ButtonRelease:
        if (xev->xbutton.button == 4 || xev->xbutton.button == 5) {
          // Scrolling the wheel triggers button press/release events.
          MouseWheelEvent wheelev(xev, from_native);
          return widget->OnMouseEvent(wheelev);
        }
        // fallthrough
      case MotionNotify: {
        MouseEvent mouseev(xev, from_native);
        return widget->OnMouseEvent(mouseev);
      }

#if defined(HAVE_XINPUT2)
      case GenericEvent: {
        return DispatchX2Event(widget, xev);
      }
#endif
    }
  }

  return false;
}

#if defined(HAVE_XINPUT2)
void SetTouchDeviceList(std::vector<unsigned int>& devices) {
  TouchFactory::GetInstance()->SetTouchDeviceList(devices);
}
#endif

AcceleratorHandler::AcceleratorHandler() {}

bool AcceleratorHandler::Dispatch(GdkEvent* event) {
  gtk_main_do_event(event);
  return true;
}

base::MessagePumpGlibXDispatcher::DispatchStatus
    AcceleratorHandler::DispatchX(XEvent* xev) {
  return DispatchXEvent(xev) ?
      base::MessagePumpGlibXDispatcher::EVENT_PROCESSED :
      base::MessagePumpGlibXDispatcher::EVENT_IGNORED;
}

}  // namespace views
<|endoftext|>