<commit_before>//===========================================
//  Lumina-DE source code
//  Copyright (c) 2015, Ken Moore
//  Available under the 3-clause BSD license
//  See the LICENSE file for full details
//===========================================
#include "syntaxSupport.h"

#include <QJsonArray>
#include <QJsonDocument>
#include <QFontDatabase>
#include <QFont>

#include <LUtils.h>

// ================
//  SYNTAX FILE CLASS
// ================
QColor SyntaxFile::colorFromOption(QString opt, QSettings *settings){
  opt = opt.simplified();
  if(opt.startsWith("rgb(")){
    QStringList opts = opt.section("(",1,-1).section(")",0,0).split(",");
    if(opts.length()!=3){ return QColor(); }
    return QColor( opts[0].simplified().toInt(), opts[1].simplified().toInt(), opts[2].simplified().toInt() );
  }else if(opt.startsWith("#")){
    return QColor(opt);
  }else if(opt.startsWith("colors/")){
    return QColor(settings->value(opt,"").toString());
  }
  return QColor("transparent");
}

QString SyntaxFile::name(){
  if(!metaObj.contains("name")){ return ""; }
  return metaObj.value("name").toString();
}

int SyntaxFile::char_limit(){
  if(!formatObj.contains("columns_per_line")){ return -1; }
  int num = formatObj.value("columns_per_line").toInt();
  return num;
}

bool SyntaxFile::highlight_excess_whitespace(){
  if(!formatObj.contains("highlight_whitespace_eol")){ return false; }
  return formatObj.value("highlight_whitespace_eol").toBool();
}

int SyntaxFile::tab_length(){
  int num = -1;
  if(formatObj.contains("tab_width")){ num = formatObj.value("tab_width").toInt(); }
  if(num<=0){ num = 8; } //UNIX Standard of 8 characters per tab
  return num;
}

void SyntaxFile::SetupDocument(QPlainTextEdit* editor){
  if(formatObj.contains("line_wrap")){
    editor->setLineWrapMode( formatObj.value("line_wrap").toBool() ? QPlainTextEdit::WidgetWidth : QPlainTextEdit::NoWrap);
  }
  if(formatObj.contains("font_type")){
    QString type = formatObj.value("font_type").toString();
    QFont font = editor->document()->defaultFont(); // current font
    if(type=="monospace"){
      font.setFamily("monospace"); //Make sure we don't change other properties of the font like size
    }
    font.setStyle(QFont::StyleNormal);
    font.setStyleStrategy(QFont::PreferAntialias);
    editor->document()->setDefaultFont(font);
  }
  if(formatObj.contains("tab_width")){
    int num = formatObj.value("tab_width").toInt();
    if(num<=0){ num = 8; } //UNIX Standard of 8 characters per tab
    editor->setTabStopWidth( num * QFontMetrics(editor->document()->defaultFont()).width(" ") );
  }
}

bool SyntaxFile::supportsFile(QString file){
  if(metaObj.contains("file_suffix")){
    return metaObj.value("file_suffix").toArray().contains( file.section("/",-1).section(".",-1) );
  }else if(metaObj.contains("file_regex")){
    return (QRegExp( metaObj.value("file_regex").toString() ).indexIn(file.section("/",-1) ) >=0 );
  }
  return false;
}

bool SyntaxFile::LoadFile(QString file, QSettings *settings){
  QStringList contents = LUtils::readFile(file);
  //Now trim the extra non-JSON off the beginning of the file
  while(!contents.isEmpty()){
    if(contents[0].startsWith("{")){ break; } //stop here
    else{ contents.removeAt(0); }
  }
  //qDebug() << "Contents:" << contents.join("\n").simplified();
  QJsonParseError err;
  QJsonDocument doc = QJsonDocument::fromJson(contents.join("\n").simplified().toLocal8Bit(), &err );
  if(doc.isNull()){ qDebug() << "JSON Syntax Error:" << err.errorString(); }
  QJsonObject obj = doc.object();
  if(!obj.contains("meta") || !obj.contains("format") || !obj.contains("rules")){ qDebug() << "Could not read syntax file:" << file; return false; } //could not get any info
  //Save the raw meta/format objects for later
  fileLoaded = file;
  metaObj = obj.value("meta").toObject();
  formatObj = obj.value("format").toObject();
  //Now read/save the rules structure
  QJsonArray rulesArray = obj.value("rules").toArray();
  rules.clear();
  //Create the blank/generic text format
  for(int i=0; i<rulesArray.count(); i++){
    QJsonObject rule = rulesArray[i].toObject();
    SyntaxRule tmp;
    //First load the rule
    //qDebug() << "Load Rule:" << rule.keys();
    if(rule.contains("words")){} //valid option - handled at the end though
    else if(rule.contains("regex")){
      tmp.pattern = QRegExp(rule.value("regex").toString());
    }else if(rule.contains("regex_start") && rule.contains("regex_end")){
      tmp.startPattern = QRegExp(rule.value("regex_start").toString());
      tmp.endPattern = QRegExp(rule.value("regex_end").toString());
      //qDebug() << " -- Multi-line Rule:" << tmp.startPattern << tmp.endPattern;
    }else{ continue; } //bad rule - missing the actual detection logic
    //Now load the appearance logic
    if(rule.contains("foreground")){ tmp.format.setForeground( colorFromOption(rule.value("foreground").toString(), settings) ); }
    if(rule.contains("background")){ tmp.format.setBackground( colorFromOption(rule.value("background").toString(), settings) ); }
    if(rule.contains("font_weight")){
      QString wgt = rule.value("font_weight").toString();
      if(wgt =="bold"){ tmp.format.setFontWeight(QFont::Bold); }
      if(wgt =="light"){ tmp.format.setFontWeight(QFont::Light); }
      else{ tmp.format.setFontWeight(QFont::Normal); }
    }
    if(rule.contains("font_style")){
      if(rule.value("font_style").toString()=="italic"){ tmp.format.setFontItalic(true); }
    }
    //Now save the rule(s) to the list
    if(rule.contains("words")){
      //special logic - this generates a bunch of rules all at once (one per word)
      QJsonArray tmpArr = rule.value("words").toArray();
      for(int a=0; a<tmpArr.count(); a++){
        tmp.pattern = QRegExp("\\b"+tmpArr[a].toString()+"\\b"); //turn each keyword into a QRegExp and insert the rule
        rules << tmp;
      }
    }else{ rules << tmp; } //just a single rule
  }
  return true;
}

//Main function for finding/loading all syntax files
QList<SyntaxFile> SyntaxFile::availableFiles(QSettings *settings){
  static QList<SyntaxFile> list; //keep this list around between calls - prevent re-reading all the files
  //Remove/update any files from the list as needed
  QStringList found;
  for(int i=0; i<list.length(); i++){
    if( !QFileInfo::exists(list[i].fileLoaded) ){ list.removeAt(i); i--; continue; } //obsolete file
    else if(QFileInfo(list[i].fileLoaded).lastModified() > list[i].lastLoaded){ list[i].LoadFile(list[i].fileLoaded, settings); } //out-of-date file
    found << list[i].fileLoaded; //save for later
  }
  //Now scan for any new files
  QStringList paths;
  paths << QString(getenv("XDG_DATA_HOME")) << QString(getenv("XDG_DATA_DIRS")).split(":");
  for(int i=0; i<paths.length(); i++){
    QDir dir(paths[i]+"/lumina-desktop/syntax_rules");
    if(!dir.exists()){ continue; }
    //qDebug() << "Found directory:" << dir.absolutePath();
    QFileInfoList files = dir.entryInfoList(QStringList() << "*.syntax", QDir::Files, QDir::Name);
    for(int f=0; f<files.length(); f++){
      if(paths.contains(files[f].absoluteFilePath()) ){ continue; } //already handled
      //New Syntax File found
      //qDebug() << "Found File:" << files[f].fileName();
      SyntaxFile nfile;
      if( nfile.LoadFile(files[f].absoluteFilePath(), settings) ){ list << nfile; }
    }
  }
  return list;
}

QStringList Custom_Syntax::availableRules(QSettings *settings){
  QStringList avail;
  QList<SyntaxFile> files = SyntaxFile::availableFiles(settings);
  for(int i=0; i<files.length(); i++){ avail << files[i].name(); }
  return avail;
}

QStringList Custom_Syntax::knownColors(){
  //Note: All these colors should be prefixed with "colors/" when accessing them from the settings file
  QStringList avail;
    //Standard colors
    avail << "keyword" << "altkeyword" << "class" << "text" << "function" << "comment";
    //Bracket/parenthesis/brace matching
    avail << "bracket-found" << "bracket-missing";
  return avail;
}

void Custom_Syntax::SetupDefaultColors(QSettings *settings){
  if(!settings->contains("colors/keyword")){settings->setValue("colors/keyword", QColor(Qt::blue).name() ); }
  if(!settings->contains("colors/altkeyword")){settings->setValue("colors/altkeyword", QColor(Qt::darkBlue).name() ); }
  if(!settings->contains("colors/class")){settings->setValue("colors/class", QColor(Qt::darkRed).name() ); }
  if(!settings->contains("colors/text")){settings->setValue("colors/text", QColor(Qt::darkMagenta).name() ); }
  if(!settings->contains("colors/function")){settings->setValue("colors/function", QColor(Qt::darkCyan).name() ); }
  if(!settings->contains("colors/comment")){settings->setValue("colors/comment", QColor(Qt::darkGreen).name() ); }
  if(!settings->contains("colors/bracket-found")){settings->setValue("colors/bracket-found", QColor(Qt::green).name() ); }
  if(!settings->contains("colors/bracket-missing")){settings->setValue("colors/bracket-missing", QColor(Qt::red).name() ); }
  if(!settings->contains("colors/preprocessor")){settings->setValue("colors/preprocessor", QColor(Qt::darkYellow).name() ); }
}

QString Custom_Syntax::ruleForFile(QString filename, QSettings *settings){
  QList<SyntaxFile> files = SyntaxFile::availableFiles(settings);
  for(int i=0; i<files.length(); i++){
    if(files[i].supportsFile(filename)){ return files[i].name(); }
  }

  /*QString suffix = filename.section(".",-1);
  if(suffix=="cpp" || suffix=="hpp" || suffix=="c" || suffix=="h"){ return "C++"; }
  //else if(suffix=="py" || suffix=="pyc"){ return "Python"; }
  else if(suffix=="sh"){ return "Shell"; }
  else if(suffix=="rst"){ return "reST"; }*/
  return "";
}

void Custom_Syntax::loadRules(QString type){
  QList<SyntaxFile> files = SyntaxFile::availableFiles(settings);
  for(int i=0; i<files.length(); i++){
    if(files[i].name() == type){ syntax = files[i]; break; }
  }
  return;
}

void Custom_Syntax::loadRules(SyntaxFile sfile){
  syntax = sfile;
}
<commit_msg>Fix up the font weight setting for the new syntax highlighting rule formats.<commit_after>//===========================================
//  Lumina-DE source code
//  Copyright (c) 2015, Ken Moore
//  Available under the 3-clause BSD license
//  See the LICENSE file for full details
//===========================================
#include "syntaxSupport.h"

#include <QJsonArray>
#include <QJsonDocument>
#include <QFontDatabase>
#include <QFont>

#include <LUtils.h>

// ================
//  SYNTAX FILE CLASS
// ================
QColor SyntaxFile::colorFromOption(QString opt, QSettings *settings){
  opt = opt.simplified();
  if(opt.startsWith("rgb(")){
    QStringList opts = opt.section("(",1,-1).section(")",0,0).split(",");
    if(opts.length()!=3){ return QColor(); }
    return QColor( opts[0].simplified().toInt(), opts[1].simplified().toInt(), opts[2].simplified().toInt() );
  }else if(opt.startsWith("#")){
    return QColor(opt);
  }else if(opt.startsWith("colors/")){
    return QColor(settings->value(opt,"").toString());
  }
  return QColor("transparent");
}

QString SyntaxFile::name(){
  if(!metaObj.contains("name")){ return ""; }
  return metaObj.value("name").toString();
}

int SyntaxFile::char_limit(){
  if(!formatObj.contains("columns_per_line")){ return -1; }
  int num = formatObj.value("columns_per_line").toInt();
  return num;
}

bool SyntaxFile::highlight_excess_whitespace(){
  if(!formatObj.contains("highlight_whitespace_eol")){ return false; }
  return formatObj.value("highlight_whitespace_eol").toBool();
}

int SyntaxFile::tab_length(){
  int num = -1;
  if(formatObj.contains("tab_width")){ num = formatObj.value("tab_width").toInt(); }
  if(num<=0){ num = 8; } //UNIX Standard of 8 characters per tab
  return num;
}

void SyntaxFile::SetupDocument(QPlainTextEdit* editor){
  if(formatObj.contains("line_wrap")){
    editor->setLineWrapMode( formatObj.value("line_wrap").toBool() ? QPlainTextEdit::WidgetWidth : QPlainTextEdit::NoWrap);
  }
  if(formatObj.contains("font_type")){
    QString type = formatObj.value("font_type").toString();
    QFont font = editor->document()->defaultFont(); // current font
    if(type=="monospace"){
      font.setFamily("monospace"); //Make sure we don't change other properties of the font like size
    }
    font.setStyle(QFont::StyleNormal);
    font.setStyleStrategy(QFont::PreferAntialias);
    editor->document()->setDefaultFont(font);
  }
  if(formatObj.contains("tab_width")){
    int num = formatObj.value("tab_width").toInt();
    if(num<=0){ num = 8; } //UNIX Standard of 8 characters per tab
    editor->setTabStopWidth( num * QFontMetrics(editor->document()->defaultFont()).width(" ") );
  }
}

bool SyntaxFile::supportsFile(QString file){
  if(metaObj.contains("file_suffix")){
    return metaObj.value("file_suffix").toArray().contains( file.section("/",-1).section(".",-1) );
  }else if(metaObj.contains("file_regex")){
    return (QRegExp( metaObj.value("file_regex").toString() ).indexIn(file.section("/",-1) ) >=0 );
  }
  return false;
}

bool SyntaxFile::LoadFile(QString file, QSettings *settings){
  QStringList contents = LUtils::readFile(file);
  //Now trim the extra non-JSON off the beginning of the file
  while(!contents.isEmpty()){
    if(contents[0].startsWith("{")){ break; } //stop here
    else{ contents.removeAt(0); }
  }
  //qDebug() << "Contents:" << contents.join("\n").simplified();
  QJsonParseError err;
  QJsonDocument doc = QJsonDocument::fromJson(contents.join("\n").simplified().toLocal8Bit(), &err );
  if(doc.isNull()){ qDebug() << "JSON Syntax Error:" << err.errorString(); }
  QJsonObject obj = doc.object();
  if(!obj.contains("meta") || !obj.contains("format") || !obj.contains("rules")){ qDebug() << "Could not read syntax file:" << file; return false; } //could not get any info
  //Save the raw meta/format objects for later
  fileLoaded = file;
  metaObj = obj.value("meta").toObject();
  formatObj = obj.value("format").toObject();
  //Now read/save the rules structure
  QJsonArray rulesArray = obj.value("rules").toArray();
  rules.clear();
  //Create the blank/generic text format
  for(int i=0; i<rulesArray.count(); i++){
    QJsonObject rule = rulesArray[i].toObject();
    SyntaxRule tmp;
    //First load the rule
    //qDebug() << "Load Rule:" << rule.keys();
    if(rule.contains("words")){} //valid option - handled at the end though
    else if(rule.contains("regex")){
      tmp.pattern = QRegExp(rule.value("regex").toString());
    }else if(rule.contains("regex_start") && rule.contains("regex_end")){
      tmp.startPattern = QRegExp(rule.value("regex_start").toString());
      tmp.endPattern = QRegExp(rule.value("regex_end").toString());
      //qDebug() << " -- Multi-line Rule:" << tmp.startPattern << tmp.endPattern;
    }else{ continue; } //bad rule - missing the actual detection logic
    //Now load the appearance logic
    if(rule.contains("foreground")){ tmp.format.setForeground( colorFromOption(rule.value("foreground").toString(), settings) ); }
    if(rule.contains("background")){ tmp.format.setBackground( colorFromOption(rule.value("background").toString(), settings) ); }
    if(rule.contains("font_weight")){
      QString wgt = rule.value("font_weight").toString();
      if(wgt =="bold"){ tmp.format.setFontWeight(QFont::Bold); }
      else if(wgt =="light"){ tmp.format.setFontWeight(QFont::Light); }
      else{ tmp.format.setFontWeight(QFont::Normal); }
    }
    if(rule.contains("font_style")){
      if(rule.value("font_style").toString()=="italic"){ tmp.format.setFontItalic(true); }
    }

    //Now save the rule(s) to the list
    if(rule.contains("words")){
      //special logic - this generates a bunch of rules all at once (one per word)
      QJsonArray tmpArr = rule.value("words").toArray();
      for(int a=0; a<tmpArr.count(); a++){
        tmp.pattern = QRegExp("\\b"+tmpArr[a].toString()+"\\b"); //turn each keyword into a QRegExp and insert the rule
        rules << tmp;
      }
    }else{ rules << tmp; } //just a single rule
  }
  return true;
}

//Main function for finding/loading all syntax files
QList<SyntaxFile> SyntaxFile::availableFiles(QSettings *settings){
  static QList<SyntaxFile> list; //keep this list around between calls - prevent re-reading all the files
  //Remove/update any files from the list as needed
  QStringList found;
  for(int i=0; i<list.length(); i++){
    if( !QFileInfo::exists(list[i].fileLoaded) ){ list.removeAt(i); i--; continue; } //obsolete file
    else if(QFileInfo(list[i].fileLoaded).lastModified() > list[i].lastLoaded){ list[i].LoadFile(list[i].fileLoaded, settings); } //out-of-date file
    found << list[i].fileLoaded; //save for later
  }
  //Now scan for any new files
  QStringList paths;
  paths << QString(getenv("XDG_DATA_HOME")) << QString(getenv("XDG_DATA_DIRS")).split(":");
  for(int i=0; i<paths.length(); i++){
    QDir dir(paths[i]+"/lumina-desktop/syntax_rules");
    if(!dir.exists()){ continue; }
    //qDebug() << "Found directory:" << dir.absolutePath();
    QFileInfoList files = dir.entryInfoList(QStringList() << "*.syntax", QDir::Files, QDir::Name);
    for(int f=0; f<files.length(); f++){
      if(paths.contains(files[f].absoluteFilePath()) ){ continue; } //already handled
      //New Syntax File found
      //qDebug() << "Found File:" << files[f].fileName();
      SyntaxFile nfile;
      if( nfile.LoadFile(files[f].absoluteFilePath(), settings) ){ list << nfile; }
    }
  }
  return list;
}

QStringList Custom_Syntax::availableRules(QSettings *settings){
  QStringList avail;
  QList<SyntaxFile> files = SyntaxFile::availableFiles(settings);
  for(int i=0; i<files.length(); i++){ avail << files[i].name(); }
  return avail;
}

QStringList Custom_Syntax::knownColors(){
  //Note: All these colors should be prefixed with "colors/" when accessing them from the settings file
  QStringList avail;
    //Standard colors
    avail << "keyword" << "altkeyword" << "class" << "text" << "function" << "comment";
    //Bracket/parenthesis/brace matching
    avail << "bracket-found" << "bracket-missing";
  return avail;
}

void Custom_Syntax::SetupDefaultColors(QSettings *settings){
  if(!settings->contains("colors/keyword")){settings->setValue("colors/keyword", QColor(Qt::blue).name() ); }
  if(!settings->contains("colors/altkeyword")){settings->setValue("colors/altkeyword", QColor(Qt::darkBlue).name() ); }
  if(!settings->contains("colors/class")){settings->setValue("colors/class", QColor(Qt::darkRed).name() ); }
  if(!settings->contains("colors/text")){settings->setValue("colors/text", QColor(Qt::darkMagenta).name() ); }
  if(!settings->contains("colors/function")){settings->setValue("colors/function", QColor(Qt::darkCyan).name() ); }
  if(!settings->contains("colors/comment")){settings->setValue("colors/comment", QColor(Qt::darkGreen).name() ); }
  if(!settings->contains("colors/bracket-found")){settings->setValue("colors/bracket-found", QColor(Qt::green).name() ); }
  if(!settings->contains("colors/bracket-missing")){settings->setValue("colors/bracket-missing", QColor(Qt::red).name() ); }
  if(!settings->contains("colors/preprocessor")){settings->setValue("colors/preprocessor", QColor(Qt::darkYellow).name() ); }
}

QString Custom_Syntax::ruleForFile(QString filename, QSettings *settings){
  QList<SyntaxFile> files = SyntaxFile::availableFiles(settings);
  for(int i=0; i<files.length(); i++){
    if(files[i].supportsFile(filename)){ return files[i].name(); }
  }
  return "";
}

void Custom_Syntax::loadRules(QString type){
  QList<SyntaxFile> files = SyntaxFile::availableFiles(settings);
  for(int i=0; i<files.length(); i++){
    if(files[i].name() == type){ syntax = files[i]; break; }
  }
  return;
}

void Custom_Syntax::loadRules(SyntaxFile sfile){
  syntax = sfile;
}
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2007 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#include <memory.h>

#include <osgSim/ShapeAttribute>

namespace osgSim
{
ShapeAttribute::ShapeAttribute() :
    _type(UNKNOW),
    _integer(0)
{}

ShapeAttribute::ShapeAttribute(const char * name) :
    _name(name),
    _type(UNKNOW),
    _integer(0)
{}

ShapeAttribute::ShapeAttribute(const char * name, int value) :
    _name(name),
    _type(INTEGER),
    _integer(value)
{}

ShapeAttribute::ShapeAttribute(const char * name, double value) :
    _name(name),
    _type(DOUBLE),
    _double(value)
{}

ShapeAttribute::ShapeAttribute(const char * name, const char * value) :
    _name(name),
    _type(STRING),
    _string(value ? strdup(value) : 0)
{
}

ShapeAttribute::ShapeAttribute(const ShapeAttribute & sa)
{
    copy(sa);
}

ShapeAttribute::~ShapeAttribute()
{
    free();
}

void ShapeAttribute::free()
{
    if ((_type == STRING) && (_string))
    {
        ::free(_string);
        _string = 0;
    }
}

void ShapeAttribute::copy(const ShapeAttribute& sa)
{
    _name = sa._name;
    _type = sa._type;

    switch (_type)
    {
        case INTEGER:
        {
            _integer = sa._integer;
            break;
        }
        case STRING:
        {
            _string = sa._string ? strdup(sa._string) : 0;
            break;
        }
        case DOUBLE:
        {
            _double = sa._double;
            break;
        }
        case UNKNOW:
        default:
        {
            _integer = 0;
            break;
        }
    }
}

ShapeAttribute& ShapeAttribute::operator = (const ShapeAttribute& sa)
{
    if (&sa == this) return *this;

    free();
    copy(sa);

    return *this;
}

int ShapeAttribute::compare(const osgSim::ShapeAttribute& sa) const
{
    if (_name<sa._name) return -1;
    if (sa._name<_name) return 1;

    if (_type<sa._type) return -1;
    if (sa._type<_type) return 1;

    if (_name<sa._name) return -1;
    if (sa._name<_name) return 1;

    switch (_type)
    {
        case STRING:
        {
            if (_string<sa._string) return -1;
            if (sa._string<_string) return 1;
        }
        case DOUBLE:
        {
            if (_double<sa._double) return -1;
            if (sa._double<_double) return 1;
        }
        case INTEGER:
        case UNKNOW:
        default:
        {
            if (_integer<sa._integer) return -1;
            if (sa._integer<_integer) return 1;
        }
    }
    return 0;
}

/** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/
int ShapeAttributeList::compare(const osgSim::ShapeAttributeList& sal) const
{
    const_iterator salIt, thisIt, thisEnd = end();

    int ret;
    for (thisIt = begin(), salIt = sal.begin(); thisIt!= thisEnd; ++thisIt, ++salIt)
        if ((ret = thisIt->compare(*salIt)) != 0) return ret;

    return 0;
}

}
<commit_msg>From Mathias Froehlich, "Fixes a compile of src/osgSim/ShapeAttribute.cpp on suse 10.2."<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2007 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#include <memory.h>
#include <stdlib.h>

#include <osgSim/ShapeAttribute>

namespace osgSim
{
ShapeAttribute::ShapeAttribute() :
    _type(UNKNOW),
    _integer(0)
{}

ShapeAttribute::ShapeAttribute(const char * name) :
    _name(name),
    _type(UNKNOW),
    _integer(0)
{}

ShapeAttribute::ShapeAttribute(const char * name, int value) :
    _name(name),
    _type(INTEGER),
    _integer(value)
{}

ShapeAttribute::ShapeAttribute(const char * name, double value) :
    _name(name),
    _type(DOUBLE),
    _double(value)
{}

ShapeAttribute::ShapeAttribute(const char * name, const char * value) :
    _name(name),
    _type(STRING),
    _string(value ? strdup(value) : 0)
{
}

ShapeAttribute::ShapeAttribute(const ShapeAttribute & sa)
{
    copy(sa);
}

ShapeAttribute::~ShapeAttribute()
{
    free();
}

void ShapeAttribute::free()
{
    if ((_type == STRING) && (_string))
    {
        ::free(_string);
        _string = 0;
    }
}

void ShapeAttribute::copy(const ShapeAttribute& sa)
{
    _name = sa._name;
    _type = sa._type;

    switch (_type)
    {
        case INTEGER:
        {
            _integer = sa._integer;
            break;
        }
        case STRING:
        {
            _string = sa._string ? strdup(sa._string) : 0;
            break;
        }
        case DOUBLE:
        {
            _double = sa._double;
            break;
        }
        case UNKNOW:
        default:
        {
            _integer = 0;
            break;
        }
    }
}

ShapeAttribute& ShapeAttribute::operator = (const ShapeAttribute& sa)
{
    if (&sa == this) return *this;

    free();
    copy(sa);

    return *this;
}

int ShapeAttribute::compare(const osgSim::ShapeAttribute& sa) const
{
    if (_name<sa._name) return -1;
    if (sa._name<_name) return 1;

    if (_type<sa._type) return -1;
    if (sa._type<_type) return 1;

    if (_name<sa._name) return -1;
    if (sa._name<_name) return 1;

    switch (_type)
    {
        case STRING:
        {
            if (_string<sa._string) return -1;
            if (sa._string<_string) return 1;
        }
        case DOUBLE:
        {
            if (_double<sa._double) return -1;
            if (sa._double<_double) return 1;
        }
        case INTEGER:
        case UNKNOW:
        default:
        {
            if (_integer<sa._integer) return -1;
            if (sa._integer<_integer) return 1;
        }
    }
    return 0;
}

/** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/
int ShapeAttributeList::compare(const osgSim::ShapeAttributeList& sal) const
{
    const_iterator salIt, thisIt, thisEnd = end();

    int ret;
    for (thisIt = begin(), salIt = sal.begin(); thisIt!= thisEnd; ++thisIt, ++salIt)
        if ((ret = thisIt->compare(*salIt)) != 0) return ret;

    return 0;
}

}
<|endoftext|>


<commit_before>/* Copyright (c) 2008-2021 the MRtrix3 contributors.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Covered Software is provided under this License on an "as is"
 * basis, without warranty of any kind, either expressed, implied, or
 * statutory, including, without limitation, warranties that the
 * Covered Software is free of defects, merchantable, fit for a
 * particular purpose or non-infringing.
 * See the Mozilla Public License v. 2.0 for more details.
 *
 * For more details, see http://www.mrtrix.org/.
 */

#include "dwi/tractography/file_base.h"
#include "file/path.h"

namespace MR {
  namespace DWI {
    namespace Tractography {

      void __ReaderBase__::open (const std::string& file, const std::string& type, Properties& properties)
      {
        properties.clear();
        dtype = DataType::Undefined;

        const std::string firstline ("mrtrix " + type);
        File::KeyValue::Reader kv (file, firstline.c_str());
        std::string data_file;

        while (kv.next()) {
          const std::string key = lowercase (kv.key());
          if (key == "roi" || key == "prior_roi") {
            try {
              vector<std::string> V (split (kv.value(), " \t", true, 2));
              properties.prior_rois.insert (std::pair<std::string,std::string> (V[0], V[1]));
            }
            catch (...) {
              WARN ("invalid ROI specification in " + type  + " file \"" + file + "\" - ignored");
            }
          }
          else if (key == "comment") properties.comments.push_back (kv.value());
          else if (key == "file") data_file = kv.value();
          else if (key == "datatype") dtype = DataType::parse (kv.value());
          else add_line (properties[kv.key()], kv.value());
        }

        if (dtype == DataType::Undefined)
          throw Exception ("no datatype specified for tracks file \"" + file + "\"");
        if (dtype != DataType::Float32LE && dtype != DataType::Float32BE &&
            dtype != DataType::Float64LE && dtype != DataType::Float64BE)
          throw Exception ("only supported datatype for tracks file are "
              "Float32LE, Float32BE, Float64LE & Float64BE (in " + type  + " file \"" + file + "\")");

        if (data_file.empty())
          throw Exception ("missing \"files\" specification for " + type  + " file \"" + file + "\"");

        std::istringstream files_stream (data_file);
        std::string fname;
        files_stream >> fname;
        int64_t offset = 0;
        if (files_stream.good()) {
          try { files_stream >> offset; }
          catch (...) {
            throw Exception ("invalid offset specified for file \""
                + fname + "\" in " + type  + " file \"" + file + "\"");
          }
        }

        if (fname != ".")
          fname = Path::join (Path::dirname (file), fname);
        else
          fname = file;

        in.open (fname.c_str(), std::ios::in | std::ios::binary);
        if (!in)
          throw Exception ("error opening " + type  + " data file \"" + fname + "\": " + strerror(errno));
        in.seekg (offset);
      }

    }
  }
}

<commit_msg>Avoid invalid memory access when ROI is malformed in tck header<commit_after>/* Copyright (c) 2008-2021 the MRtrix3 contributors.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Covered Software is provided under this License on an "as is"
 * basis, without warranty of any kind, either expressed, implied, or
 * statutory, including, without limitation, warranties that the
 * Covered Software is free of defects, merchantable, fit for a
 * particular purpose or non-infringing.
 * See the Mozilla Public License v. 2.0 for more details.
 *
 * For more details, see http://www.mrtrix.org/.
 */

#include "dwi/tractography/file_base.h"
#include "file/path.h"

namespace MR {
  namespace DWI {
    namespace Tractography {

      void __ReaderBase__::open (const std::string& file, const std::string& type, Properties& properties)
      {
        properties.clear();
        dtype = DataType::Undefined;

        const std::string firstline ("mrtrix " + type);
        File::KeyValue::Reader kv (file, firstline.c_str());
        std::string data_file;

        while (kv.next()) {
          const std::string key = lowercase (kv.key());
          if (key == "roi" || key == "prior_roi") {
            try {
              vector<std::string> V (split (kv.value(), " \t", true, 2));
              if (V.size() < 2)
                V.push_back (std::string());
              properties.prior_rois.insert (std::pair<std::string,std::string> (V[0], V[1]));
            }
            catch (...) {
              WARN ("invalid ROI specification in " + type  + " file \"" + file + "\" - ignored");
            }
          }
          else if (key == "comment") properties.comments.push_back (kv.value());
          else if (key == "file") data_file = kv.value();
          else if (key == "datatype") dtype = DataType::parse (kv.value());
          else add_line (properties[kv.key()], kv.value());
        }

        if (dtype == DataType::Undefined)
          throw Exception ("no datatype specified for tracks file \"" + file + "\"");
        if (dtype != DataType::Float32LE && dtype != DataType::Float32BE &&
            dtype != DataType::Float64LE && dtype != DataType::Float64BE)
          throw Exception ("only supported datatype for tracks file are "
              "Float32LE, Float32BE, Float64LE & Float64BE (in " + type  + " file \"" + file + "\")");

        if (data_file.empty())
          throw Exception ("missing \"files\" specification for " + type  + " file \"" + file + "\"");

        std::istringstream files_stream (data_file);
        std::string fname;
        files_stream >> fname;
        int64_t offset = 0;
        if (files_stream.good()) {
          try { files_stream >> offset; }
          catch (...) {
            throw Exception ("invalid offset specified for file \""
                + fname + "\" in " + type  + " file \"" + file + "\"");
          }
        }

        if (fname != ".")
          fname = Path::join (Path::dirname (file), fname);
        else
          fname = file;

        in.open (fname.c_str(), std::ios::in | std::ios::binary);
        if (!in)
          throw Exception ("error opening " + type  + " data file \"" + fname + "\": " + strerror(errno));
        in.seekg (offset);
      }

    }
  }
}

<|endoftext|>


<commit_before>//
//   Copyright 2015 Pixar
//
//   Licensed under the Apache License, Version 2.0 (the "Apache License")
//   with the following modification; you may not use this file except in
//   compliance with the Apache License and the following modification to it:
//   Section 6. Trademarks. is deleted and replaced with:
//
//   6. Trademarks. This License does not grant permission to use the trade
//      names, trademarks, service marks, or product names of the Licensor
//      and its affiliates, except as required to comply with Section 4(c) of
//      the License and to reproduce the content of the NOTICE file.
//
//   You may obtain a copy of the Apache License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the Apache License with the above modification is
//   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//   KIND, either express or implied. See the Apache License for the specific
//   language governing permissions and limitations under the Apache License.
//

#include "clDeviceContext.h"

#if defined(_WIN32)
    #include <windows.h>
#elif defined(__APPLE__)
    #include <OpenGL/OpenGL.h>
#else
    #include <GL/glx.h>
#endif

#include <cstdio>
#include <cstring>
#include <string>

#if defined(OPENSUBDIV_HAS_DX)
#include <D3D11.h>
#include <CL/cl_d3d11.h>
#endif

#define message(...)    // fprintf(stderr, __VA_ARGS__)
#define error(...)  fprintf(stderr, __VA_ARGS__)

// returns the first found platform.
//
static cl_platform_id
findPlatform() {
    cl_uint numPlatforms;
    cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);

    if (ciErrNum != CL_SUCCESS) {
        error("Error %d in clGetPlatformIDs call.\n", ciErrNum);
        return NULL;
    }
    if (numPlatforms == 0) {
        error("No OpenCL platform found.\n");
        return NULL;
    }

    cl_platform_id *clPlatformIDs = new cl_platform_id[numPlatforms];
    ciErrNum = clGetPlatformIDs(numPlatforms, clPlatformIDs, NULL);
    char chBuffer[1024];
    for (cl_uint i = 0; i < numPlatforms; ++i) {
        ciErrNum = clGetPlatformInfo(clPlatformIDs[i], CL_PLATFORM_NAME,
                                     1024, chBuffer,NULL);
        if (ciErrNum == CL_SUCCESS) {
            cl_platform_id platformId = clPlatformIDs[i];
            delete[] clPlatformIDs;
            return platformId;
        }
    }
    delete[] clPlatformIDs;
    return NULL;
}

// returns the device in clDevices which supports the extension.
//
static int
findExtensionSupportedDevice(cl_device_id *clDevices,
                             int numDevices,
                             const char *extensionName) {
    // find a device that supports sharing with GL/D3D11
    // (SLI / X-fire configurations)
    cl_int ciErrNum;

    for (int i = 0; i < numDevices; ++i) {
        // get extensions string size
        size_t extensionSize;
        ciErrNum = clGetDeviceInfo(clDevices[i],
                                   CL_DEVICE_EXTENSIONS, 0, NULL,
                                   &extensionSize );

        if (ciErrNum != CL_SUCCESS) {
            error("Error %d in clGetDeviceInfo\n", ciErrNum);
            return -1;
        }

        if (extensionSize>0) {
            // get extensions string
            char *extensions = new char[extensionSize];
            ciErrNum = clGetDeviceInfo(clDevices[i], CL_DEVICE_EXTENSIONS,
                                       extensionSize, extensions,
                                       &extensionSize);
            if (ciErrNum != CL_SUCCESS) {
                error("Error %d in clGetDeviceInfo\n", ciErrNum);
                delete[] extensions;
                continue;
            }
            std::string extString(extensions);
            delete[] extensions;

            // parse string. This is bit deficient since the extentions
            // is space separated.
            //
            // The actual string would be "cl_khr_d3d11_sharing"
            //                         or "cl_nv_d3d11_sharing"
            if (extString.find(extensionName) != std::string::npos) {
                return i;
            }
        }
    }
    return -1;
}

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

CLDeviceContext::CLDeviceContext() :
    _clContext(NULL), _clCommandQueue(NULL) {
}

CLDeviceContext::~CLDeviceContext() {

    if (_clCommandQueue)
        clReleaseCommandQueue(_clCommandQueue);
    if (_clContext)
        clReleaseContext(_clContext);
}

/*static*/
bool
CLDeviceContext::HAS_CL_VERSION_1_1 () {

#ifdef OPENSUBDIV_HAS_CLEW
    static bool clewInitialized = false;
    static bool clewLoadSuccess;
    if (not clewInitialized) {
        clewInitialized = true;
        clewLoadSuccess = clewInit() == CLEW_SUCCESS;
        if (not clewLoadSuccess) {
            error(stderr, "Loading OpenCL failed.\n");
        }
    }
    return clewLoadSuccess;
#endif
    return true;
}

bool
CLDeviceContext::Initialize() {

#ifdef OPENSUBDIV_HAS_CLEW
    if (!clGetPlatformIDs) {
        error("Error clGetPlatformIDs function not bound.\n");
        return false;
    }
#endif

    cl_int ciErrNum;
    cl_platform_id cpPlatform = findPlatform();

#if defined(_WIN32)
    cl_context_properties props[] = {
        CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(),
        CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC(),
        CL_CONTEXT_PLATFORM, (cl_context_properties)cpPlatform,
        0
    };
#elif defined(__APPLE__)
    CGLContextObj kCGLContext = CGLGetCurrentContext();
    CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext);
    cl_context_properties props[] = {
        CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)kCGLShareGroup,
        0
    };
#else
    cl_context_properties props[] = {
        CL_GL_CONTEXT_KHR, (cl_context_properties)glXGetCurrentContext(),
        CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay(),
        CL_CONTEXT_PLATFORM, (cl_context_properties)cpPlatform,
        0
    };
#endif

#if defined(__APPLE__)
    _clContext = clCreateContext(props, 0, NULL, clLogMessagesToStdoutAPPLE,
                                 NULL, &ciErrNum);
    if (ciErrNum != CL_SUCCESS) {
        error("Error %d in clCreateContext\n", ciErrNum);
        return false;
    }

    size_t devicesSize = 0;
    clGetGLContextInfoAPPLE(_clContext, kCGLContext,
                            CL_CGL_DEVICES_FOR_SUPPORTED_VIRTUAL_SCREENS_APPLE,
                            0, NULL, &devicesSize);
    int numDevices = int(devicesSize / sizeof(cl_device_id));
    if (numDevices == 0) {
        error("No sharable devices.\n");
        return false;
    }
    cl_device_id *clDevices = new cl_device_id[numDevices];
    clGetGLContextInfoAPPLE(_clContext, kCGLContext,
                            CL_CGL_DEVICES_FOR_SUPPORTED_VIRTUAL_SCREENS_APPLE,
                            numDevices * sizeof(cl_device_id), clDevices, NULL);

#else   // not __APPLE__

    // get the number of GPU devices available to the platform
    cl_uint numDevices = 0;
    clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 0, NULL, &numDevices);
    if (numDevices == 0) {
        error("No CL GPU device found.\n");
        return false;
    }

    // create the device list
    cl_device_id *clDevices = new cl_device_id[numDevices];
    clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, numDevices, clDevices, NULL);

    const char *extension = "cl_khr_gl_sharing";
    int clDeviceUsed = findExtensionSupportedDevice(clDevices, numDevices,
                                                    extension);

    if (clDeviceUsed < 0) {
        error("No device found that supports CL/GL context sharing\n");
        delete[] clDevices;
        return false;
    }

    _clContext = clCreateContext(props, 1, &clDevices[clDeviceUsed],
                                 NULL, NULL, &ciErrNum);

#endif   // not __APPLE__

    if (ciErrNum != CL_SUCCESS) {
        error("Error %d in clCreateContext\n", ciErrNum);
        delete[] clDevices;
        return false;
    }

    _clCommandQueue = clCreateCommandQueue(_clContext, clDevices[clDeviceUsed],
                                    0, &ciErrNum);
    delete[] clDevices;
    if (ciErrNum != CL_SUCCESS) {
        error("Error %d in clCreateCommandQueue\n", ciErrNum);
        return false;
    }
    return true;
}

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

bool
CLD3D11DeviceContext::Initialize(ID3D11DeviceContext *d3dDeviceContext) {

#if defined(OPENSUBDIV_HAS_DX)
    _d3dDeviceContext = d3dDeviceContext;

    cl_int ciErrNum;
    cl_platform_id cpPlatform = findPlatform();

    ID3D11Device *device;
    d3dDeviceContext->GetDevice(&device);

    cl_context_properties props[] = {
        CL_CONTEXT_D3D11_DEVICE_KHR, (cl_context_properties)device,
        CL_CONTEXT_PLATFORM, (cl_context_properties)cpPlatform,
        0
    };

    // get the number of GPU devices available to the platform
    cl_uint numDevices = 0;
    clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 0, NULL, &numDevices);
    if (numDevices == 0) {
        error("No CL GPU device found.\n");
        return false;
    }

    // create the device list
    cl_device_id *clDevices = new cl_device_id[numDevices];
    clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, numDevices, clDevices, NULL);

    // we're cheating a little bit.
    // try to find both cl_khr_d3d11_sharing and cl_nv_d3d11_sharing.
    const char *extension = "_d3d11_sharing";
    int clDeviceUsed = findExtensionSupportedDevice(clDevices, numDevices,
                                                    extension);

    if (clDeviceUsed < 0) {
        error("No device found that supports CL/D3D11 context sharing\n");
        delete[] clDevices;
        return false;
    }

    _clContext = clCreateContext(props, 1, &clDevices[clDeviceUsed],
                                 NULL, NULL, &ciErrNum);
    if (ciErrNum != CL_SUCCESS) {
        error("Error %d in clCreateContext\n", ciErrNum);
        delete[] clDevices;
        return false;
    }

    _clCommandQueue = clCreateCommandQueue(_clContext, clDevices[clDeviceUsed],
                                    0, &ciErrNum);
    delete[] clDevices;
    if (ciErrNum != CL_SUCCESS) {
        error("Error %d in clCreateCommandQueue\n", ciErrNum);
        return false;
    }
    return true;
#else
    (void)d3dDeviceContext;  // unused
    return false;
#endif
}
<commit_msg>fix mac build.<commit_after>//
//   Copyright 2015 Pixar
//
//   Licensed under the Apache License, Version 2.0 (the "Apache License")
//   with the following modification; you may not use this file except in
//   compliance with the Apache License and the following modification to it:
//   Section 6. Trademarks. is deleted and replaced with:
//
//   6. Trademarks. This License does not grant permission to use the trade
//      names, trademarks, service marks, or product names of the Licensor
//      and its affiliates, except as required to comply with Section 4(c) of
//      the License and to reproduce the content of the NOTICE file.
//
//   You may obtain a copy of the Apache License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the Apache License with the above modification is
//   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//   KIND, either express or implied. See the Apache License for the specific
//   language governing permissions and limitations under the Apache License.
//

#include "clDeviceContext.h"

#if defined(_WIN32)
    #include <windows.h>
#elif defined(__APPLE__)
    #include <OpenGL/OpenGL.h>
#else
    #include <GL/glx.h>
#endif

#include <cstdio>
#include <cstring>
#include <string>

#if defined(OPENSUBDIV_HAS_DX)
#include <D3D11.h>
#include <CL/cl_d3d11.h>
#endif

#define message(...)    // fprintf(stderr, __VA_ARGS__)
#define error(...)  fprintf(stderr, __VA_ARGS__)

// returns the first found platform.
//
static cl_platform_id
findPlatform() {
    cl_uint numPlatforms;
    cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);

    if (ciErrNum != CL_SUCCESS) {
        error("Error %d in clGetPlatformIDs call.\n", ciErrNum);
        return NULL;
    }
    if (numPlatforms == 0) {
        error("No OpenCL platform found.\n");
        return NULL;
    }

    cl_platform_id *clPlatformIDs = new cl_platform_id[numPlatforms];
    ciErrNum = clGetPlatformIDs(numPlatforms, clPlatformIDs, NULL);
    char chBuffer[1024];
    for (cl_uint i = 0; i < numPlatforms; ++i) {
        ciErrNum = clGetPlatformInfo(clPlatformIDs[i], CL_PLATFORM_NAME,
                                     1024, chBuffer,NULL);
        if (ciErrNum == CL_SUCCESS) {
            cl_platform_id platformId = clPlatformIDs[i];
            delete[] clPlatformIDs;
            return platformId;
        }
    }
    delete[] clPlatformIDs;
    return NULL;
}

// returns the device in clDevices which supports the extension.
//
static int
findExtensionSupportedDevice(cl_device_id *clDevices,
                             int numDevices,
                             const char *extensionName) {
    // find a device that supports sharing with GL/D3D11
    // (SLI / X-fire configurations)
    cl_int ciErrNum;

    for (int i = 0; i < numDevices; ++i) {
        // get extensions string size
        size_t extensionSize;
        ciErrNum = clGetDeviceInfo(clDevices[i],
                                   CL_DEVICE_EXTENSIONS, 0, NULL,
                                   &extensionSize );

        if (ciErrNum != CL_SUCCESS) {
            error("Error %d in clGetDeviceInfo\n", ciErrNum);
            return -1;
        }

        if (extensionSize>0) {
            // get extensions string
            char *extensions = new char[extensionSize];
            ciErrNum = clGetDeviceInfo(clDevices[i], CL_DEVICE_EXTENSIONS,
                                       extensionSize, extensions,
                                       &extensionSize);
            if (ciErrNum != CL_SUCCESS) {
                error("Error %d in clGetDeviceInfo\n", ciErrNum);
                delete[] extensions;
                continue;
            }
            std::string extString(extensions);
            delete[] extensions;

            // parse string. This is bit deficient since the extentions
            // is space separated.
            //
            // The actual string would be "cl_khr_d3d11_sharing"
            //                         or "cl_nv_d3d11_sharing"
            if (extString.find(extensionName) != std::string::npos) {
                return i;
            }
        }
    }
    return -1;
}

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

CLDeviceContext::CLDeviceContext() :
    _clContext(NULL), _clCommandQueue(NULL) {
}

CLDeviceContext::~CLDeviceContext() {

    if (_clCommandQueue)
        clReleaseCommandQueue(_clCommandQueue);
    if (_clContext)
        clReleaseContext(_clContext);
}

/*static*/
bool
CLDeviceContext::HAS_CL_VERSION_1_1 () {

#ifdef OPENSUBDIV_HAS_CLEW
    static bool clewInitialized = false;
    static bool clewLoadSuccess;
    if (not clewInitialized) {
        clewInitialized = true;
        clewLoadSuccess = clewInit() == CLEW_SUCCESS;
        if (not clewLoadSuccess) {
            error(stderr, "Loading OpenCL failed.\n");
        }
    }
    return clewLoadSuccess;
#endif
    return true;
}

bool
CLDeviceContext::Initialize() {

#ifdef OPENSUBDIV_HAS_CLEW
    if (!clGetPlatformIDs) {
        error("Error clGetPlatformIDs function not bound.\n");
        return false;
    }
#endif

    cl_int ciErrNum;
    cl_platform_id cpPlatform = findPlatform();

#if defined(_WIN32)
    cl_context_properties props[] = {
        CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(),
        CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC(),
        CL_CONTEXT_PLATFORM, (cl_context_properties)cpPlatform,
        0
    };
#elif defined(__APPLE__)
    CGLContextObj kCGLContext = CGLGetCurrentContext();
    CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext);
    cl_context_properties props[] = {
        CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)kCGLShareGroup,
        0
    };
#else
    cl_context_properties props[] = {
        CL_GL_CONTEXT_KHR, (cl_context_properties)glXGetCurrentContext(),
        CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay(),
        CL_CONTEXT_PLATFORM, (cl_context_properties)cpPlatform,
        0
    };
#endif

#if defined(__APPLE__)
    _clContext = clCreateContext(props, 0, NULL, clLogMessagesToStdoutAPPLE,
                                 NULL, &ciErrNum);
    if (ciErrNum != CL_SUCCESS) {
        error("Error %d in clCreateContext\n", ciErrNum);
        return false;
    }

    size_t devicesSize = 0;
    clGetGLContextInfoAPPLE(_clContext, kCGLContext,
                            CL_CGL_DEVICES_FOR_SUPPORTED_VIRTUAL_SCREENS_APPLE,
                            0, NULL, &devicesSize);
    int numDevices = int(devicesSize / sizeof(cl_device_id));
    if (numDevices == 0) {
        error("No sharable devices.\n");
        return false;
    }
    cl_device_id *clDevices = new cl_device_id[numDevices];
    clGetGLContextInfoAPPLE(_clContext, kCGLContext,
                            CL_CGL_DEVICES_FOR_SUPPORTED_VIRTUAL_SCREENS_APPLE,
                            numDevices * sizeof(cl_device_id), clDevices, NULL);
    int clDeviceUsed = 0;

#else   // not __APPLE__

    // get the number of GPU devices available to the platform
    cl_uint numDevices = 0;
    clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 0, NULL, &numDevices);
    if (numDevices == 0) {
        error("No CL GPU device found.\n");
        return false;
    }

    // create the device list
    cl_device_id *clDevices = new cl_device_id[numDevices];
    clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, numDevices, clDevices, NULL);

    const char *extension = "cl_khr_gl_sharing";
    int clDeviceUsed = findExtensionSupportedDevice(clDevices, numDevices,
                                                    extension);

    if (clDeviceUsed < 0) {
        error("No device found that supports CL/GL context sharing\n");
        delete[] clDevices;
        return false;
    }

    _clContext = clCreateContext(props, 1, &clDevices[clDeviceUsed],
                                 NULL, NULL, &ciErrNum);

#endif   // not __APPLE__

    if (ciErrNum != CL_SUCCESS) {
        error("Error %d in clCreateContext\n", ciErrNum);
        delete[] clDevices;
        return false;
    }

    _clCommandQueue = clCreateCommandQueue(_clContext, clDevices[clDeviceUsed],
                                    0, &ciErrNum);
    delete[] clDevices;
    if (ciErrNum != CL_SUCCESS) {
        error("Error %d in clCreateCommandQueue\n", ciErrNum);
        return false;
    }
    return true;
}

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

bool
CLD3D11DeviceContext::Initialize(ID3D11DeviceContext *d3dDeviceContext) {

#if defined(OPENSUBDIV_HAS_DX)
    _d3dDeviceContext = d3dDeviceContext;

    cl_int ciErrNum;
    cl_platform_id cpPlatform = findPlatform();

    ID3D11Device *device;
    d3dDeviceContext->GetDevice(&device);

    cl_context_properties props[] = {
        CL_CONTEXT_D3D11_DEVICE_KHR, (cl_context_properties)device,
        CL_CONTEXT_PLATFORM, (cl_context_properties)cpPlatform,
        0
    };

    // get the number of GPU devices available to the platform
    cl_uint numDevices = 0;
    clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 0, NULL, &numDevices);
    if (numDevices == 0) {
        error("No CL GPU device found.\n");
        return false;
    }

    // create the device list
    cl_device_id *clDevices = new cl_device_id[numDevices];
    clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, numDevices, clDevices, NULL);

    // we're cheating a little bit.
    // try to find both cl_khr_d3d11_sharing and cl_nv_d3d11_sharing.
    const char *extension = "_d3d11_sharing";
    int clDeviceUsed = findExtensionSupportedDevice(clDevices, numDevices,
                                                    extension);

    if (clDeviceUsed < 0) {
        error("No device found that supports CL/D3D11 context sharing\n");
        delete[] clDevices;
        return false;
    }

    _clContext = clCreateContext(props, 1, &clDevices[clDeviceUsed],
                                 NULL, NULL, &ciErrNum);
    if (ciErrNum != CL_SUCCESS) {
        error("Error %d in clCreateContext\n", ciErrNum);
        delete[] clDevices;
        return false;
    }

    _clCommandQueue = clCreateCommandQueue(_clContext, clDevices[clDeviceUsed],
                                    0, &ciErrNum);
    delete[] clDevices;
    if (ciErrNum != CL_SUCCESS) {
        error("Error %d in clCreateCommandQueue\n", ciErrNum);
        return false;
    }
    return true;
#else
    (void)d3dDeviceContext;  // unused
    return false;
#endif
}
<|endoftext|>


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

////////////////////////////////////////////////////////////
// THIS EXAMPLE MUST BE BUILT WITH A VERSION
// OF GASNET CONFIGURED WITH MPI COMPATIBILITY
//
// NOTE THAT GASNET ONLY SUPPORTS MPI-COMPATIBILITY
// ON SOME CONDUITS. CURRENTLY THESE ARE IBV, GEMINI,
// ARIES, MXM, and OFI. IF YOU WOULD LIKE ADDITIONAL
// CONDUITS SUPPORTED PLEASE CONTACT THE MAINTAINERS
// OF GASNET.
//
// Note: there is a way to use this example with the
// MPI conduit, but you have to have a version of
// MPI that supports MPI_THREAD_MULTIPLE. See the
// macro GASNET_CONDUIT_MPI below.
////////////////////////////////////////////////////////////

#include <cstdio>
// Need MPI header file
#include <mpi.h>

#include "legion.h"

using namespace Legion;

enum TaskID
{
  TOP_LEVEL_TASK_ID,
  MPI_INTEROP_TASK_ID,
  WORKER_TASK_ID,
};

// Here is our global MPI-Legion handshake
// You can have as many of these as you
// want but the common case is just to
// have one per Legion-MPI rank pair
MPILegionHandshake handshake;

// Have a global static number of iterations for
// this example, but you can easily configure it
// from command line arguments which get passed
// to both MPI and Legion
const int total_iterations = 10;

void worker_task(const Task *task,
                 const std::vector<PhysicalRegion> &regions,
                 Context ctx, Runtime *runtime)
{
  printf("Legion Doing Work in Rank %lld\n",
          task->parent_task->index_point[0]);
}

void mpi_interop_task(const Task *task,
                      const std::vector<PhysicalRegion> &regions,
                      Context ctx, Runtime *runtime)
{
  printf("Hello from Legion MPI-Interop Task %lld\n", task->index_point[0]);
  for (int i = 0; i < total_iterations; i++)
  {
    // Legion can interop with MPI in blocking and non-blocking
    // ways. You can use the calls to 'legion_wait_on_mpi' and
    // 'legion_handoff_to_mpi' in the same way as the MPI thread
    // does. Alternatively, you can get a phase barrier associated
    // with a LegionMPIHandshake object which will allow you to
    // continue launching more sub-tasks without blocking.
    // For deferred execution we prefer the later style, but
    // both will work correctly.
    if (i < (total_iterations/2))
    {
      // This is the blocking way of using handshakes, it
      // is not the ideal way, but it works correctly
      // Wait for MPI to give us control to run our worker
      // This is a blocking call
      handshake.legion_wait_on_mpi();
      // Launch our worker task
      TaskLauncher worker_launcher(WORKER_TASK_ID, TaskArgument(NULL,0));
      Future f = runtime->execute_task(ctx, worker_launcher);
      // Have to wait for the result before signaling MPI
      f.get_void_result();
      // Perform a non-blocking call to signal
      // MPI that we are giving it control back
      handshake.legion_handoff_to_mpi();
    }
    else
    {
      // This is the preferred way of using handshakes in Legion
      TaskLauncher worker_launcher(WORKER_TASK_ID, TaskArgument(NULL,0));
      // We can user our handshake as a phase barrier
      // Record that we will wait on this handshake
      worker_launcher.add_wait_handshake(handshake);
      // Advance the handshake to the next version
      handshake.advance_legion_handshake();
      // Then record that we will arrive on this versions
      worker_launcher.add_arrival_handshake(handshake);
      // Launch our worker task
      // No need to wait for anything
      runtime->execute_task(ctx, worker_launcher);
    }
  }
}

void top_level_task(const Task *task,
                    const std::vector<PhysicalRegion> &regions,
                    Context ctx, Runtime *runtime)
{
  printf("Hello from Legion Top-Level Task\n");
  // Both the application and Legion mappers have access to
  // the mappings between MPI Ranks and Legion address spaces
  // The reverse mapping goes the other way
  const std::map<int,AddressSpace> &forward_mapping =
    runtime->find_forward_MPI_mapping();
  for (std::map<int,AddressSpace>::const_iterator it =
        forward_mapping.begin(); it != forward_mapping.end(); it++)
    printf("MPI Rank %d maps to Legion Address Space %d\n",
            it->first, it->second);

  int rank = -1, size = -1;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  // Do a must epoch launch to align with the number of MPI ranks
  MustEpochLauncher must_epoch_launcher;
  Rect<1> launch_bounds(Point<1>(0),Point<1>(size - 1));
  Domain launch_domain = Domain::from_rect<1>(launch_bounds);
  ArgumentMap args_map;
  IndexLauncher index_launcher(MPI_INTEROP_TASK_ID, launch_domain,
                               TaskArgument(NULL, 0), args_map);
  must_epoch_launcher.add_index_task(index_launcher);
  runtime->execute_must_epoch(ctx, must_epoch_launcher);
}

int main(int argc, char **argv)
{
#ifdef GASNET_CONDUIT_MPI
  // The GASNet MPI conduit requires special start-up
  // in order to handle MPI calls from multiple threads
  int provided;
  MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
  // If you fail this assertion, then your version of MPI
  // does not support calls from multiple threads and you
  // cannot use the GASNet MPI conduit
  if (provided < MPI_THREAD_MULTIPLE)
    printf("ERROR: Your implementation of MPI does not support "
           "MPI_THREAD_MULTIPLE which is required for use of the "
           "GASNet MPI conduit with the Legion-MPI Interop!\n");
  assert(provided == MPI_THREAD_MULTIPLE);
#else
  // Perform MPI start-up like normal for most GASNet conduits
  MPI_Init(&argc, &argv);
#endif

  int rank = -1, size = -1;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  printf("Hello from MPI process %d of %d\n", rank, size);

  // Configure the Legion runtime with the rank of this process
  Runtime::configure_MPI_interoperability(rank);
  // Register our task variants
  {
    TaskVariantRegistrar top_level_registrar(TOP_LEVEL_TASK_ID);
    top_level_registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
    Runtime::preregister_task_variant<top_level_task>(top_level_registrar,
                                                      "Top Level Task");
    Runtime::set_top_level_task_id(TOP_LEVEL_TASK_ID);
  }
  {
    TaskVariantRegistrar mpi_interop_registrar(MPI_INTEROP_TASK_ID);
    mpi_interop_registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
    Runtime::preregister_task_variant<mpi_interop_task>(mpi_interop_registrar,
                                                        "MPI Interop Task");
  }
  {
    TaskVariantRegistrar worker_task_registrar(WORKER_TASK_ID);
    worker_task_registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
    Runtime::preregister_task_variant<worker_task>(worker_task_registrar,
                                                   "Worker Task");
  }
  // Create a handshake for passing control between Legion and MPI
  // Indicate that MPI has initial control and that there is one
  // participant on each side
  handshake = Runtime::create_handshake(true/*MPI initial control*/,
                                        1/*MPI participants*/,
                                        1/*Legion participants*/);
  // Start the Legion runtime in background mode
  // This call will return immediately
  Runtime::start(argc, argv, true/*background*/);
  // Run your MPI program like normal
  // If you want strict bulk-synchronous execution include
  // the barriers protected by this variable, otherwise
  // you can elide them, they are not required for correctness
  const bool strict_bulk_synchronous_execution = true;
  for (int i = 0; i < total_iterations; i++)
  {
    printf("MPI Doing Work on rank %d\n", rank);
    if (strict_bulk_synchronous_execution)
      MPI_Barrier(MPI_COMM_WORLD);
    // Perform a handoff to Legion, this call is
    // asynchronous and will return immediately
    handshake.mpi_handoff_to_legion();
    // You can put additional work in here if you like
    // but it may interfere with Legion work

    // Wait for Legion to hand control back,
    // This call will block until a Legion task
    // running in this same process hands control back
    handshake.mpi_wait_on_legion();
    if (strict_bulk_synchronous_execution)
      MPI_Barrier(MPI_COMM_WORLD);
  }
  // When you're done wait for the Legion runtime to shutdown
  Runtime::wait_for_shutdown();
#ifndef GASNET_CONDUIT_MPI
  // Then finalize MPI like normal
  // Exception for the MPI conduit which does its own finalization
  MPI_Finalize();
#endif

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

////////////////////////////////////////////////////////////
// THIS EXAMPLE MUST BE BUILT WITH A VERSION
// OF GASNET CONFIGURED WITH MPI COMPATIBILITY
//
// NOTE THAT GASNET ONLY SUPPORTS MPI-COMPATIBILITY
// ON SOME CONDUITS. CURRENTLY THESE ARE IBV, GEMINI,
// ARIES, MXM, and OFI. IF YOU WOULD LIKE ADDITIONAL
// CONDUITS SUPPORTED PLEASE CONTACT THE MAINTAINERS
// OF GASNET.
//
// Note: there is a way to use this example with the
// MPI conduit, but you have to have a version of
// MPI that supports MPI_THREAD_MULTIPLE. See the
// macro GASNET_CONDUIT_MPI below.
////////////////////////////////////////////////////////////

#include <cstdio>
// Need MPI header file
#include <mpi.h>

#include "legion.h"

using namespace Legion;
using namespace LegionRuntime::Arrays;

enum TaskID
{
  TOP_LEVEL_TASK_ID,
  MPI_INTEROP_TASK_ID,
  WORKER_TASK_ID,
};

// Here is our global MPI-Legion handshake
// You can have as many of these as you
// want but the common case is just to
// have one per Legion-MPI rank pair
MPILegionHandshake handshake;

// Have a global static number of iterations for
// this example, but you can easily configure it
// from command line arguments which get passed
// to both MPI and Legion
const int total_iterations = 10;

void worker_task(const Task *task,
                 const std::vector<PhysicalRegion> &regions,
                 Context ctx, Runtime *runtime)
{
  printf("Legion Doing Work in Rank %lld\n",
          task->parent_task->index_point[0]);
}

void mpi_interop_task(const Task *task,
                      const std::vector<PhysicalRegion> &regions,
                      Context ctx, Runtime *runtime)
{
  printf("Hello from Legion MPI-Interop Task %lld\n", task->index_point[0]);
  for (int i = 0; i < total_iterations; i++)
  {
    // Legion can interop with MPI in blocking and non-blocking
    // ways. You can use the calls to 'legion_wait_on_mpi' and
    // 'legion_handoff_to_mpi' in the same way as the MPI thread
    // does. Alternatively, you can get a phase barrier associated
    // with a LegionMPIHandshake object which will allow you to
    // continue launching more sub-tasks without blocking.
    // For deferred execution we prefer the later style, but
    // both will work correctly.
    if (i < (total_iterations/2))
    {
      // This is the blocking way of using handshakes, it
      // is not the ideal way, but it works correctly
      // Wait for MPI to give us control to run our worker
      // This is a blocking call
      handshake.legion_wait_on_mpi();
      // Launch our worker task
      TaskLauncher worker_launcher(WORKER_TASK_ID, TaskArgument(NULL,0));
      Future f = runtime->execute_task(ctx, worker_launcher);
      // Have to wait for the result before signaling MPI
      f.get_void_result();
      // Perform a non-blocking call to signal
      // MPI that we are giving it control back
      handshake.legion_handoff_to_mpi();
    }
    else
    {
      // This is the preferred way of using handshakes in Legion
      TaskLauncher worker_launcher(WORKER_TASK_ID, TaskArgument(NULL,0));
      // We can user our handshake as a phase barrier
      // Record that we will wait on this handshake
      worker_launcher.add_wait_handshake(handshake);
      // Advance the handshake to the next version
      handshake.advance_legion_handshake();
      // Then record that we will arrive on this versions
      worker_launcher.add_arrival_handshake(handshake);
      // Launch our worker task
      // No need to wait for anything
      runtime->execute_task(ctx, worker_launcher);
    }
  }
}

void top_level_task(const Task *task,
                    const std::vector<PhysicalRegion> &regions,
                    Context ctx, Runtime *runtime)
{
  printf("Hello from Legion Top-Level Task\n");
  // Both the application and Legion mappers have access to
  // the mappings between MPI Ranks and Legion address spaces
  // The reverse mapping goes the other way
  const std::map<int,AddressSpace> &forward_mapping =
    runtime->find_forward_MPI_mapping();
  for (std::map<int,AddressSpace>::const_iterator it =
        forward_mapping.begin(); it != forward_mapping.end(); it++)
    printf("MPI Rank %d maps to Legion Address Space %d\n",
            it->first, it->second);

  int rank = -1, size = -1;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  // Do a must epoch launch to align with the number of MPI ranks
  MustEpochLauncher must_epoch_launcher;
  Rect<1> launch_bounds(Point<1>(0),Point<1>(size - 1));
  Domain launch_domain = Domain::from_rect<1>(launch_bounds);
  ArgumentMap args_map;
  IndexLauncher index_launcher(MPI_INTEROP_TASK_ID, launch_domain,
                               TaskArgument(NULL, 0), args_map);
  must_epoch_launcher.add_index_task(index_launcher);
  runtime->execute_must_epoch(ctx, must_epoch_launcher);
}

int main(int argc, char **argv)
{
#ifdef GASNET_CONDUIT_MPI
  // The GASNet MPI conduit requires special start-up
  // in order to handle MPI calls from multiple threads
  int provided;
  MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
  // If you fail this assertion, then your version of MPI
  // does not support calls from multiple threads and you
  // cannot use the GASNet MPI conduit
  if (provided < MPI_THREAD_MULTIPLE)
    printf("ERROR: Your implementation of MPI does not support "
           "MPI_THREAD_MULTIPLE which is required for use of the "
           "GASNet MPI conduit with the Legion-MPI Interop!\n");
  assert(provided == MPI_THREAD_MULTIPLE);
#else
  // Perform MPI start-up like normal for most GASNet conduits
  MPI_Init(&argc, &argv);
#endif

  int rank = -1, size = -1;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  printf("Hello from MPI process %d of %d\n", rank, size);

  // Configure the Legion runtime with the rank of this process
  Runtime::configure_MPI_interoperability(rank);
  // Register our task variants
  {
    TaskVariantRegistrar top_level_registrar(TOP_LEVEL_TASK_ID);
    top_level_registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
    Runtime::preregister_task_variant<top_level_task>(top_level_registrar,
                                                      "Top Level Task");
    Runtime::set_top_level_task_id(TOP_LEVEL_TASK_ID);
  }
  {
    TaskVariantRegistrar mpi_interop_registrar(MPI_INTEROP_TASK_ID);
    mpi_interop_registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
    Runtime::preregister_task_variant<mpi_interop_task>(mpi_interop_registrar,
                                                        "MPI Interop Task");
  }
  {
    TaskVariantRegistrar worker_task_registrar(WORKER_TASK_ID);
    worker_task_registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
    Runtime::preregister_task_variant<worker_task>(worker_task_registrar,
                                                   "Worker Task");
  }
  // Create a handshake for passing control between Legion and MPI
  // Indicate that MPI has initial control and that there is one
  // participant on each side
  handshake = Runtime::create_handshake(true/*MPI initial control*/,
                                        1/*MPI participants*/,
                                        1/*Legion participants*/);
  // Start the Legion runtime in background mode
  // This call will return immediately
  Runtime::start(argc, argv, true/*background*/);
  // Run your MPI program like normal
  // If you want strict bulk-synchronous execution include
  // the barriers protected by this variable, otherwise
  // you can elide them, they are not required for correctness
  const bool strict_bulk_synchronous_execution = true;
  for (int i = 0; i < total_iterations; i++)
  {
    printf("MPI Doing Work on rank %d\n", rank);
    if (strict_bulk_synchronous_execution)
      MPI_Barrier(MPI_COMM_WORLD);
    // Perform a handoff to Legion, this call is
    // asynchronous and will return immediately
    handshake.mpi_handoff_to_legion();
    // You can put additional work in here if you like
    // but it may interfere with Legion work

    // Wait for Legion to hand control back,
    // This call will block until a Legion task
    // running in this same process hands control back
    handshake.mpi_wait_on_legion();
    if (strict_bulk_synchronous_execution)
      MPI_Barrier(MPI_COMM_WORLD);
  }
  // When you're done wait for the Legion runtime to shutdown
  Runtime::wait_for_shutdown();
#ifndef GASNET_CONDUIT_MPI
  // Then finalize MPI like normal
  // Exception for the MPI conduit which does its own finalization
  MPI_Finalize();
#endif

  return 0;
}
<|endoftext|>


<commit_before>#include "depthai/pipeline/AssetManager.hpp"

#include "spdlog/fmt/fmt.h"
#include "utility/spdlog-fmt.hpp"

// std
#include <fstream>

namespace dai {

std::string Asset::getRelativeUri() {
    return fmt::format("{}:{}", "asset", key);
}

std::shared_ptr<dai::Asset> AssetManager::set(Asset asset) {
    // make sure that key doesn't exist already
    if(assetMap.count(asset.key) > 0) throw std::logic_error("An Asset with the key: " + asset.key + " already exists.");
    std::string key = asset.key;
    assetMap[key] = std::make_shared<Asset>(std::move(asset));
    return assetMap[key];
}

std::shared_ptr<dai::Asset> AssetManager::set(const std::string& key, Asset asset) {
    // Rename the asset with supplied key and store
    Asset a(key);
    a.data = std::move(asset.data);
    a.alignment = asset.alignment;
    return set(std::move(a));
}

std::shared_ptr<dai::Asset> AssetManager::set(const std::string& key, const dai::Path& path, int alignment) {
    // Load binary file at path
    std::ifstream stream(path, std::ios::in | std::ios::binary);
    if(!stream.is_open()) {
        // Throw an error
        // TODO(themarpe) - Unify exceptions into meaningful groups
        throw std::runtime_error(fmt::format("Cannot load asset, file at path {} doesn't exist.", path));
    }

    // Create an asset
    Asset binaryAsset(key);
    binaryAsset.alignment = alignment;
    binaryAsset.data = std::vector<std::uint8_t>(std::istreambuf_iterator<char>(stream), {});
    // Store asset
    return set(std::move(binaryAsset));
}

std::shared_ptr<dai::Asset> AssetManager::set(const std::string& key, const std::vector<std::uint8_t>& data, int alignment) {
    // Create an asset
    Asset binaryAsset(key);
    binaryAsset.alignment = alignment;
    binaryAsset.data = std::move(data);
    // Store asset
    return set(std::move(binaryAsset));
}

std::shared_ptr<dai::Asset> AssetManager::set(const std::string& key, std::vector<std::uint8_t>&& data, int alignment) {
    // Create an asset
    Asset binaryAsset(key);
    binaryAsset.alignment = alignment;
    binaryAsset.data = std::move(data);
    // Store asset
    return set(std::move(binaryAsset));
}

std::shared_ptr<const Asset> AssetManager::get(const std::string& key) const {
    if(assetMap.count(key) == 0) {
        return nullptr;
    }
    return assetMap.at(key);
}

std::shared_ptr<Asset> AssetManager::get(const std::string& key) {
    if(assetMap.count(key) == 0) {
        return nullptr;
    }
    return assetMap.at(key);
}

void AssetManager::addExisting(std::vector<std::shared_ptr<Asset>> assets) {
    // make sure that key doesn't exist already
    for(const auto& asset : assets) {
        if(assetMap.count(asset->key) > 0) throw std::logic_error("An Asset with the key: " + asset->key + " already exists.");
        std::string key = asset->key;
        assetMap[key] = asset;
    }
}

std::vector<std::shared_ptr<const Asset>> AssetManager::getAll() const {
    std::vector<std::shared_ptr<const Asset>> a;
    for(const auto& kv : assetMap) {
        a.push_back(kv.second);
    }
    return a;
}

std::vector<std::shared_ptr<Asset>> AssetManager::getAll() {
    std::vector<std::shared_ptr<Asset>> a;
    for(const auto& kv : assetMap) {
        a.push_back(kv.second);
    }
    return a;
}

std::size_t AssetManager::size() const {
    return assetMap.size();
}

void AssetManager::remove(const std::string& key) {
    assetMap.erase(key);
}

void AssetManager::serialize(AssetsMutable& mutableAssets, std::vector<std::uint8_t>& storage, std::string prefix) const {
    using namespace std;

    for(auto& kv : assetMap) {
        auto& a = *kv.second;

        // calculate additional bytes needed to offset to alignment
        int toAdd = 0;
        if(a.alignment > 1 && storage.size() % a.alignment != 0) {
            toAdd = a.alignment - (storage.size() % a.alignment);
        }

        // calculate offset
        std::uint32_t offset = static_cast<uint32_t>(storage.size()) + toAdd;

        // Add alignment bytes
        storage.resize(storage.size() + toAdd);

        // copy data
        storage.insert(storage.end(), a.data.begin(), a.data.end());

        // Add to map the currently added asset
        mutableAssets.set(prefix + a.key, offset, static_cast<uint32_t>(a.data.size()), a.alignment);
    }
}

void AssetsMutable::set(std::string key, std::uint32_t offset, std::uint32_t size, std::uint32_t alignment) {
    AssetInternal internal = {};
    internal.offset = offset;
    internal.size = size;
    internal.alignment = alignment;
    map[key] = internal;
}

}  // namespace dai
<commit_msg>Fixed AssetManager 'set' function to allow overwriting an asset<commit_after>#include "depthai/pipeline/AssetManager.hpp"

#include "spdlog/fmt/fmt.h"
#include "utility/spdlog-fmt.hpp"

// std
#include <fstream>

namespace dai {

std::string Asset::getRelativeUri() {
    return fmt::format("{}:{}", "asset", key);
}

std::shared_ptr<dai::Asset> AssetManager::set(Asset asset) {
    std::string key = asset.key;
    assetMap[key] = std::make_shared<Asset>(std::move(asset));
    return assetMap[key];
}

std::shared_ptr<dai::Asset> AssetManager::set(const std::string& key, Asset asset) {
    // Rename the asset with supplied key and store
    Asset a(key);
    a.data = std::move(asset.data);
    a.alignment = asset.alignment;
    return set(std::move(a));
}

std::shared_ptr<dai::Asset> AssetManager::set(const std::string& key, const dai::Path& path, int alignment) {
    // Load binary file at path
    std::ifstream stream(path, std::ios::in | std::ios::binary);
    if(!stream.is_open()) {
        // Throw an error
        // TODO(themarpe) - Unify exceptions into meaningful groups
        throw std::runtime_error(fmt::format("Cannot load asset, file at path {} doesn't exist.", path));
    }

    // Create an asset
    Asset binaryAsset(key);
    binaryAsset.alignment = alignment;
    binaryAsset.data = std::vector<std::uint8_t>(std::istreambuf_iterator<char>(stream), {});
    // Store asset
    return set(std::move(binaryAsset));
}

std::shared_ptr<dai::Asset> AssetManager::set(const std::string& key, const std::vector<std::uint8_t>& data, int alignment) {
    // Create an asset
    Asset binaryAsset(key);
    binaryAsset.alignment = alignment;
    binaryAsset.data = std::move(data);
    // Store asset
    return set(std::move(binaryAsset));
}

std::shared_ptr<dai::Asset> AssetManager::set(const std::string& key, std::vector<std::uint8_t>&& data, int alignment) {
    // Create an asset
    Asset binaryAsset(key);
    binaryAsset.alignment = alignment;
    binaryAsset.data = std::move(data);
    // Store asset
    return set(std::move(binaryAsset));
}

std::shared_ptr<const Asset> AssetManager::get(const std::string& key) const {
    if(assetMap.count(key) == 0) {
        return nullptr;
    }
    return assetMap.at(key);
}

std::shared_ptr<Asset> AssetManager::get(const std::string& key) {
    if(assetMap.count(key) == 0) {
        return nullptr;
    }
    return assetMap.at(key);
}

void AssetManager::addExisting(std::vector<std::shared_ptr<Asset>> assets) {
    // make sure that key doesn't exist already
    for(const auto& asset : assets) {
        if(assetMap.count(asset->key) > 0) throw std::logic_error("An Asset with the key: " + asset->key + " already exists.");
        std::string key = asset->key;
        assetMap[key] = asset;
    }
}

std::vector<std::shared_ptr<const Asset>> AssetManager::getAll() const {
    std::vector<std::shared_ptr<const Asset>> a;
    for(const auto& kv : assetMap) {
        a.push_back(kv.second);
    }
    return a;
}

std::vector<std::shared_ptr<Asset>> AssetManager::getAll() {
    std::vector<std::shared_ptr<Asset>> a;
    for(const auto& kv : assetMap) {
        a.push_back(kv.second);
    }
    return a;
}

std::size_t AssetManager::size() const {
    return assetMap.size();
}

void AssetManager::remove(const std::string& key) {
    assetMap.erase(key);
}

void AssetManager::serialize(AssetsMutable& mutableAssets, std::vector<std::uint8_t>& storage, std::string prefix) const {
    using namespace std;

    for(auto& kv : assetMap) {
        auto& a = *kv.second;

        // calculate additional bytes needed to offset to alignment
        int toAdd = 0;
        if(a.alignment > 1 && storage.size() % a.alignment != 0) {
            toAdd = a.alignment - (storage.size() % a.alignment);
        }

        // calculate offset
        std::uint32_t offset = static_cast<uint32_t>(storage.size()) + toAdd;

        // Add alignment bytes
        storage.resize(storage.size() + toAdd);

        // copy data
        storage.insert(storage.end(), a.data.begin(), a.data.end());

        // Add to map the currently added asset
        mutableAssets.set(prefix + a.key, offset, static_cast<uint32_t>(a.data.size()), a.alignment);
    }
}

void AssetsMutable::set(std::string key, std::uint32_t offset, std::uint32_t size, std::uint32_t alignment) {
    AssetInternal internal = {};
    internal.offset = offset;
    internal.size = size;
    internal.alignment = alignment;
    map[key] = internal;
}

}  // namespace dai
<|endoftext|>