<commit_before>// This file is part of the KDE libraries
// Copyright (C) 2008 Paul Giannaros <paul@giannaros.org>
// Copyright (C) 2009 Dominik Haumann <dhaumann kde org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) version 3.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public License
// along with this library; see the file COPYING.LIB.  If not, write to
// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
// Boston, MA 02110-1301, USA.

#include "katescript.h"
#include "katescriptdocument.h"
#include "katescriptview.h"
#include "kateview.h"
#include "katedocument.h"

#include <iostream>

#include <QFile>

#include <QScriptEngine>
#include <QScriptValue>
#include <QScriptContext>
#include <QFileInfo>

#include <kdebug.h>
#include <klocale.h>
#include <kstandarddirs.h>

//BEGIN conversion functions for Cursors and Ranges
/** Converstion function from KTextEditor::Cursor to QtScript cursor */
static QScriptValue cursorToScriptValue(QScriptEngine *engine, const KTextEditor::Cursor &cursor)
{
  QString code = QString("new Cursor(%1, %2);").arg(cursor.line())
                                               .arg(cursor.column());
  return engine->evaluate(code);
}

/** Converstion function from QtScript cursor to KTextEditor::Cursor */
static void cursorFromScriptValue(const QScriptValue &obj, KTextEditor::Cursor &cursor)
{
  cursor.setPosition(obj.property("line").toInt32(),
                     obj.property("column").toInt32());
}

/** Converstion function from QtScript range to KTextEditor::Range */
static QScriptValue rangeToScriptValue(QScriptEngine *engine, const KTextEditor::Range &range)
{
  QString code = QString("new Range(%1, %2, %3, %4);").arg(range.start().line())
                                                      .arg(range.start().column())
                                                      .arg(range.end().line())
                                                      .arg(range.end().column());
  return engine->evaluate(code);
}

/** Converstion function from QtScript range to KTextEditor::Range */
static void rangeFromScriptValue(const QScriptValue &obj, KTextEditor::Range &range)
{
  range.start().setPosition(obj.property("start").property("line").toInt32(),
                            obj.property("start").property("column").toInt32());
  range.end().setPosition(obj.property("end").property("line").toInt32(),
                          obj.property("end").property("column").toInt32());
}
//END

namespace Kate {
  namespace Script {

    QScriptValue debug(QScriptContext *context, QScriptEngine *engine) {
      QStringList message;
      for(int i = 0; i < context->argumentCount(); ++i) {
        message << context->argument(i).toString();
      }
      // debug in blue to distance from other debug output if necessary
      std::cerr << "\033[34m" << qPrintable(message.join(" ")) << "\033[0m\n";
      return engine->nullValue();
    }

  }
}

bool KateScript::s_scriptingApiLoaded = false;

void KateScript::reloadScriptingApi()
{
  s_scriptingApiLoaded = false;
}

bool KateScript::readFile(const QString& sourceUrl, QString& sourceCode)
{
  sourceCode = QString();

  QFile file(sourceUrl);
  if (!file.open(QIODevice::ReadOnly)) {
    kDebug(13050) << i18n("Unable to find '%1'", sourceUrl);
    return false;
  } else {
    QTextStream stream(&file);
    stream.setCodec("UTF-8");
    sourceCode = stream.readAll();
    file.close();
  }
  return true;
}

KateScript::KateScript(const QString &url)
  : m_loaded(false)
  , m_loadSuccessful(false)
  , m_url(url)
  , m_engine(0)
  , m_document(0)
  , m_view(0)
{
}

KateScript::~KateScript()
{
  if(m_loadSuccessful) {
    // remove data...
    delete m_engine;
    delete m_document;
    delete m_view;
  }
}

void KateScript::displayBacktrace(const QScriptValue &error, const QString &header)
{
  if(!m_engine) {
    std::cerr << "KateScript::displayBacktrace: no engine, cannot display error\n";
    return;
  }
  std::cerr << "\033[31m";
  if(!header.isNull())
    std::cerr << qPrintable(header) << ":\n";
  if(error.isError())
    std::cerr << qPrintable(error.toString()) << '\n';
    std::cerr << qPrintable(m_engine->uncaughtExceptionBacktrace().join("\n"));
    std::cerr << "\033[0m" << '\n';
}

void KateScript::clearExceptions()
{
  m_engine->clearExceptions();
}

QScriptValue KateScript::global(const QString &name)
{
  // load the script if necessary
  if(!load())
    return QScriptValue();
  return m_engine->globalObject().property(name);
}

QScriptValue KateScript::function(const QString &name)
{
  QScriptValue value = global(name);
  if(!value.isFunction())
    return QScriptValue();
  return value;
}

bool KateScript::initApi ()
{
  // cache file names
  static QStringList apiFileBaseNames;
  static QHash<QString, QString> apiBaseName2FileName;
  static QHash<QString, QString> apiBaseName2Content;

  // read katepart javascript api
  if (!s_scriptingApiLoaded) {
    s_scriptingApiLoaded = true;
    apiFileBaseNames.clear ();
    apiBaseName2FileName.clear ();
    apiBaseName2Content.clear ();

    // get all api files
    const QStringList list = KGlobal::dirs()->findAllResources("data","katepart/api/*.js", KStandardDirs::NoDuplicates);

    for ( QStringList::ConstIterator it = list.begin(); it != list.end(); ++it )
    {
      // get abs filename....
      QFileInfo fi(*it);
      const QString absPath = fi.absoluteFilePath();
      const QString baseName = fi.baseName ();

      // remember filenames
      apiFileBaseNames.append (baseName);
      apiBaseName2FileName[baseName] = absPath;

      // read the file
      QString content;
      readFile(absPath, content);
      apiBaseName2Content[baseName] = content;
    }

    // sort...
    apiFileBaseNames.sort ();
  }

  // register all script apis found
  for ( QStringList::ConstIterator it = apiFileBaseNames.begin(); it != apiFileBaseNames.end(); ++it )
  {
    // try to load into engine, bail out one error, use fullpath for error messages
    QScriptValue apiObject = m_engine->evaluate(apiBaseName2Content[*it], apiBaseName2FileName[*it]);
    if (hasException(apiObject, apiBaseName2FileName[*it])) {
      return false;
    }
  }

  // success ;)
  return true;
}

bool KateScript::load()
{
  if(m_loaded)
    return m_loadSuccessful;

  m_loaded = true;
  m_loadSuccessful = false; // here set to false, and at end of function to true

  // read the script file into memory
  QString source;
  if (!readFile(m_url, source)) {
    return false;
  }

  // create script engine, register meta types
  m_engine = new QScriptEngine();
  qScriptRegisterMetaType (m_engine, cursorToScriptValue, cursorFromScriptValue);
  qScriptRegisterMetaType (m_engine, rangeToScriptValue, rangeFromScriptValue);

  // init API
  if (!initApi ())
    return false;

  // register scripts itself
  QScriptValue result = m_engine->evaluate(source, m_url);
  if (hasException(result, m_url)) {
    return false;
  }

  // yip yip!
  initEngine();
  m_loadSuccessful = true;
  return true;
}

bool KateScript::hasException(const QScriptValue& object, const QString& file)
{
  if(m_engine->hasUncaughtException()) {
    displayBacktrace(object, i18n("Error loading script %1\n", file));
    m_errorMessage = i18n("Error loading script %1", file);
    delete m_engine;
    m_engine = 0;
    m_loadSuccessful = false;
    return true;
  }
  return false;
}

void KateScript::initEngine() {
  // set the view/document objects as necessary
  m_engine->globalObject().setProperty("document", m_engine->newQObject(m_document = new KateScriptDocument()));
  m_engine->globalObject().setProperty("view", m_engine->newQObject(m_view = new KateScriptView()));

  m_engine->globalObject().setProperty("debug", m_engine->newFunction(Kate::Script::debug));
}

bool KateScript::setView(KateView *view)
{
  if (!load())
    return false;
  // setup the stuff
  m_document->setDocument (view->doc());
  m_view->setView (view);
  return true;
}

// kate: space-indent on; indent-width 2; replace-tabs on;
<commit_msg>Fix iterator<commit_after>// This file is part of the KDE libraries
// Copyright (C) 2008 Paul Giannaros <paul@giannaros.org>
// Copyright (C) 2009 Dominik Haumann <dhaumann kde org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) version 3.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public License
// along with this library; see the file COPYING.LIB.  If not, write to
// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
// Boston, MA 02110-1301, USA.

#include "katescript.h"
#include "katescriptdocument.h"
#include "katescriptview.h"
#include "kateview.h"
#include "katedocument.h"

#include <iostream>

#include <QFile>

#include <QScriptEngine>
#include <QScriptValue>
#include <QScriptContext>
#include <QFileInfo>

#include <kdebug.h>
#include <klocale.h>
#include <kstandarddirs.h>

//BEGIN conversion functions for Cursors and Ranges
/** Converstion function from KTextEditor::Cursor to QtScript cursor */
static QScriptValue cursorToScriptValue(QScriptEngine *engine, const KTextEditor::Cursor &cursor)
{
  QString code = QString("new Cursor(%1, %2);").arg(cursor.line())
                                               .arg(cursor.column());
  return engine->evaluate(code);
}

/** Converstion function from QtScript cursor to KTextEditor::Cursor */
static void cursorFromScriptValue(const QScriptValue &obj, KTextEditor::Cursor &cursor)
{
  cursor.setPosition(obj.property("line").toInt32(),
                     obj.property("column").toInt32());
}

/** Converstion function from QtScript range to KTextEditor::Range */
static QScriptValue rangeToScriptValue(QScriptEngine *engine, const KTextEditor::Range &range)
{
  QString code = QString("new Range(%1, %2, %3, %4);").arg(range.start().line())
                                                      .arg(range.start().column())
                                                      .arg(range.end().line())
                                                      .arg(range.end().column());
  return engine->evaluate(code);
}

/** Converstion function from QtScript range to KTextEditor::Range */
static void rangeFromScriptValue(const QScriptValue &obj, KTextEditor::Range &range)
{
  range.start().setPosition(obj.property("start").property("line").toInt32(),
                            obj.property("start").property("column").toInt32());
  range.end().setPosition(obj.property("end").property("line").toInt32(),
                          obj.property("end").property("column").toInt32());
}
//END

namespace Kate {
  namespace Script {

    QScriptValue debug(QScriptContext *context, QScriptEngine *engine) {
      QStringList message;
      for(int i = 0; i < context->argumentCount(); ++i) {
        message << context->argument(i).toString();
      }
      // debug in blue to distance from other debug output if necessary
      std::cerr << "\033[34m" << qPrintable(message.join(" ")) << "\033[0m\n";
      return engine->nullValue();
    }

  }
}

bool KateScript::s_scriptingApiLoaded = false;

void KateScript::reloadScriptingApi()
{
  s_scriptingApiLoaded = false;
}

bool KateScript::readFile(const QString& sourceUrl, QString& sourceCode)
{
  sourceCode = QString();

  QFile file(sourceUrl);
  if (!file.open(QIODevice::ReadOnly)) {
    kDebug(13050) << i18n("Unable to find '%1'", sourceUrl);
    return false;
  } else {
    QTextStream stream(&file);
    stream.setCodec("UTF-8");
    sourceCode = stream.readAll();
    file.close();
  }
  return true;
}

KateScript::KateScript(const QString &url)
  : m_loaded(false)
  , m_loadSuccessful(false)
  , m_url(url)
  , m_engine(0)
  , m_document(0)
  , m_view(0)
{
}

KateScript::~KateScript()
{
  if(m_loadSuccessful) {
    // remove data...
    delete m_engine;
    delete m_document;
    delete m_view;
  }
}

void KateScript::displayBacktrace(const QScriptValue &error, const QString &header)
{
  if(!m_engine) {
    std::cerr << "KateScript::displayBacktrace: no engine, cannot display error\n";
    return;
  }
  std::cerr << "\033[31m";
  if(!header.isNull())
    std::cerr << qPrintable(header) << ":\n";
  if(error.isError())
    std::cerr << qPrintable(error.toString()) << '\n';
    std::cerr << qPrintable(m_engine->uncaughtExceptionBacktrace().join("\n"));
    std::cerr << "\033[0m" << '\n';
}

void KateScript::clearExceptions()
{
  m_engine->clearExceptions();
}

QScriptValue KateScript::global(const QString &name)
{
  // load the script if necessary
  if(!load())
    return QScriptValue();
  return m_engine->globalObject().property(name);
}

QScriptValue KateScript::function(const QString &name)
{
  QScriptValue value = global(name);
  if(!value.isFunction())
    return QScriptValue();
  return value;
}

bool KateScript::initApi ()
{
  // cache file names
  static QStringList apiFileBaseNames;
  static QHash<QString, QString> apiBaseName2FileName;
  static QHash<QString, QString> apiBaseName2Content;

  // read katepart javascript api
  if (!s_scriptingApiLoaded) {
    s_scriptingApiLoaded = true;
    apiFileBaseNames.clear ();
    apiBaseName2FileName.clear ();
    apiBaseName2Content.clear ();

    // get all api files
    const QStringList list = KGlobal::dirs()->findAllResources("data","katepart/api/*.js", KStandardDirs::NoDuplicates);

    for ( QStringList::ConstIterator it = list.begin(); it != list.end(); ++it )
    {
      // get abs filename....
      QFileInfo fi(*it);
      const QString absPath = fi.absoluteFilePath();
      const QString baseName = fi.baseName ();

      // remember filenames
      apiFileBaseNames.append (baseName);
      apiBaseName2FileName[baseName] = absPath;

      // read the file
      QString content;
      readFile(absPath, content);
      apiBaseName2Content[baseName] = content;
    }

    // sort...
    apiFileBaseNames.sort ();
  }

  // register all script apis found
  for ( QStringList::ConstIterator it = apiFileBaseNames.constBegin(); it != apiFileBaseNames.constEnd(); ++it )
  {
    // try to load into engine, bail out one error, use fullpath for error messages
    QScriptValue apiObject = m_engine->evaluate(apiBaseName2Content[*it], apiBaseName2FileName[*it]);
    if (hasException(apiObject, apiBaseName2FileName[*it])) {
      return false;
    }
  }

  // success ;)
  return true;
}

bool KateScript::load()
{
  if(m_loaded)
    return m_loadSuccessful;

  m_loaded = true;
  m_loadSuccessful = false; // here set to false, and at end of function to true

  // read the script file into memory
  QString source;
  if (!readFile(m_url, source)) {
    return false;
  }

  // create script engine, register meta types
  m_engine = new QScriptEngine();
  qScriptRegisterMetaType (m_engine, cursorToScriptValue, cursorFromScriptValue);
  qScriptRegisterMetaType (m_engine, rangeToScriptValue, rangeFromScriptValue);

  // init API
  if (!initApi ())
    return false;

  // register scripts itself
  QScriptValue result = m_engine->evaluate(source, m_url);
  if (hasException(result, m_url)) {
    return false;
  }

  // yip yip!
  initEngine();
  m_loadSuccessful = true;
  return true;
}

bool KateScript::hasException(const QScriptValue& object, const QString& file)
{
  if(m_engine->hasUncaughtException()) {
    displayBacktrace(object, i18n("Error loading script %1\n", file));
    m_errorMessage = i18n("Error loading script %1", file);
    delete m_engine;
    m_engine = 0;
    m_loadSuccessful = false;
    return true;
  }
  return false;
}

void KateScript::initEngine() {
  // set the view/document objects as necessary
  m_engine->globalObject().setProperty("document", m_engine->newQObject(m_document = new KateScriptDocument()));
  m_engine->globalObject().setProperty("view", m_engine->newQObject(m_view = new KateScriptView()));

  m_engine->globalObject().setProperty("debug", m_engine->newFunction(Kate::Script::debug));
}

bool KateScript::setView(KateView *view)
{
  if (!load())
    return false;
  // setup the stuff
  m_document->setDocument (view->doc());
  m_view->setView (view);
  return true;
}

// kate: space-indent on; indent-width 2; replace-tabs on;
<|endoftext|>


<commit_before>/*
Copyright (c) 2009 Yahoo! Inc.  All rights reserved.  The copyrights
embodied in the content of this file are licensed under the BSD
(revised) open source license
 */

#include <math.h>
#include <ctype.h>
#include "parse_example.h"
#include "hash.h"
#include "cache.h"
#include "unique_sort.h"

using namespace std;

size_t hashstring (substring s, unsigned long h)
{
  size_t ret = 0;
  //trim leading whitespace
  for(; *(s.start) <= 0x20 && s.start < s.end; s.start++);
  //trim trailing white space
  for(; *(s.end-1) <= 0x20 && s.end > s.start; s.end--);

  char *p = s.start;
  while (p != s.end)
    if (isdigit(*p))
      ret = 10*ret + *(p++) - '0';
    else
      return uniform_hash((unsigned char *)s.start, s.end - s.start, h);

  return ret + h;
}

size_t hashall (substring s, unsigned long h)
{
  return uniform_hash((unsigned char *)s.start, s.end - s.start, h);
}

hash_func_t getHasher(const string& s){
  if (s=="strings")
    return hashstring;
  else if(s=="all")
    return hashall;
  else{
    cerr << "Unknown hash function: " << s << ". Exiting " << endl;
    exit(1);
  }
}

void feature_value(substring &s, v_array<substring>& name, float &v)
{
  tokenize(':', s, name);

  switch (name.index()) {
  case 0:
  case 1:
    v = 1.;
    break;
  case 2:
    v = float_of_substring(name[1]);
    if ( isnan(v))
      {
	cerr << "error NaN value for feature: ";
	cerr.write(name[0].start, name[0].end - name[0].start);
	cerr << " terminating." << endl;
	exit(1);
      }
    break;
  default:
    cerr << "example with a wierd name.  What is ";
    cerr.write(s.start, s.end - s.start);
    cerr << "\n";
  }
}

// new should be empty. --Alex
template<class T> void copy_v_array(v_array<T>& old, v_array<T>& new_va)
{
  // allocate new memory for new.
  new_va.begin = (T *) malloc(sizeof(T)*old.index());

  // copy the old to the new.
  memcpy(new_va.begin,old.begin,sizeof(T)*old.index());

  // update pointers
  new_va.end = new_va.begin + old.index();
  new_va.end_array = new_va.end;
}

char* c_string_of_substring(substring s)
{
  size_t len = s.end - s.start+1;
  char* ret = (char *)calloc(len,sizeof(char));
  memcpy(ret,s.start,len-1);
  return ret;
}

char* copy(char* base)
{
  size_t len = 0;
  while (base[len++] != '\0');
  char* ret = (char *)calloc(len,sizeof(char));
  memcpy(ret,base,len);
  return ret;
}

int read_features(parser* p, void* ex)
{
  example* ae = (example*)ex;
  char *line=NULL;
  int num_chars = readto(*(p->input), line, '\n');
  if (num_chars == 0)
    return num_chars;

  substring example = {line, line + num_chars};

  tokenize('|', example, p->channels);
  p->lp->default_label(ae->ld);
  substring* feature_start = &(p->channels[1]);
  if (*line == '|')
    feature_start = &(p->channels[0]);
  else
    {
      substring label_space = p->channels[0];
      char* tab_location = safe_index(label_space.start, '\t', label_space.end);
      if (tab_location != label_space.end)
	label_space.start = tab_location+1;

      tokenize(' ',label_space,p->words);
      if (p->words.index() > 0 && p->words.last().end == label_space.end) //The last field is a tag, so record and strip it off
	{
	  substring tag = p->words.pop();
	  push_many(ae->tag, tag.start, tag.end - tag.start);
	}

      p->lp->parse_label(ae->ld, p->words);
    }

  size_t mask = global.parse_mask;
  bool audit = global.audit;
  for (substring* i = feature_start; i != p->channels.end; i++) {
    substring channel = *i;

    tokenize(' ',channel, p->words);
    if (p->words.begin == p->words.end)
      continue;

    float channel_v = 1.;
    size_t channel_hash;
    char* base=NULL;
    size_t index = 0;
    bool new_index = false;
    size_t feature_offset = 0;
    if (channel.start[0] != ' ')//we have a nonanonymous namespace
      {
	feature_offset++;
	feature_value(p->words[0], p->name, channel_v);

	if (p->name.index() > 0) {
	  index = (unsigned char)(*p->name[0].start);
	  if (ae->atomics[index].begin == ae->atomics[index].end)
	    new_index = true;
	}
	if (audit)
	  base = c_string_of_substring(p->name[0]);
	channel_hash = p->hasher(p->name[0], hash_base);
      }
    else
      {
	index = (unsigned char)' ';
	if (ae->atomics[index].begin == ae->atomics[index].end)
	  new_index = true;
	if (audit)
	  {
	    base = (char *)calloc(2,sizeof(char));
	    base[0]=' ';
	    base[1]='\0';
	  }
	channel_hash = 0;
      }

    for (substring* i = p->words.begin+feature_offset; i != p->words.end; i++) {
      float v = 0.;
      feature_value(*i, p->name, v);
      v *= channel_v;

      size_t word_hash = (p->hasher(p->name[0], channel_hash)) & mask;
      feature f = {v,(uint32_t)word_hash};
      ae->sum_feat_sq[index] += v*v;
      push(ae->atomics[index], f);
    }

    if (new_index && ae->atomics[index].begin != ae->atomics[index].end)
      push(ae->indices, index);

    if (audit)
      {
	for (substring* i = p->words.begin+feature_offset; i != p->words.end; i++) {
	  float v = 0.;
	  feature_value(*i, p->name, v);
	  v *= channel_v;

	  size_t word_hash = (p->hasher(p->name[0], channel_hash)) & mask;

	  char* feature = c_string_of_substring(p->name[0]);
	  audit_data ad = {copy(base), feature, word_hash, v, true};
	  push(ae->audit_features[index], ad);
	}
	free(base);
      }
  }

  return num_chars;
}

<commit_msg>tweaked tag format to allow whitespace<commit_after>/*
Copyright (c) 2009 Yahoo! Inc.  All rights reserved.  The copyrights
embodied in the content of this file are licensed under the BSD
(revised) open source license
 */

#include <math.h>
#include <ctype.h>
#include "parse_example.h"
#include "hash.h"
#include "cache.h"
#include "unique_sort.h"

using namespace std;

size_t hashstring (substring s, unsigned long h)
{
  size_t ret = 0;
  //trim leading whitespace
  for(; *(s.start) <= 0x20 && s.start < s.end; s.start++);
  //trim trailing white space
  for(; *(s.end-1) <= 0x20 && s.end > s.start; s.end--);

  char *p = s.start;
  while (p != s.end)
    if (isdigit(*p))
      ret = 10*ret + *(p++) - '0';
    else
      return uniform_hash((unsigned char *)s.start, s.end - s.start, h);

  return ret + h;
}

size_t hashall (substring s, unsigned long h)
{
  return uniform_hash((unsigned char *)s.start, s.end - s.start, h);
}

hash_func_t getHasher(const string& s){
  if (s=="strings")
    return hashstring;
  else if(s=="all")
    return hashall;
  else{
    cerr << "Unknown hash function: " << s << ". Exiting " << endl;
    exit(1);
  }
}

void feature_value(substring &s, v_array<substring>& name, float &v)
{
  tokenize(':', s, name);

  switch (name.index()) {
  case 0:
  case 1:
    v = 1.;
    break;
  case 2:
    v = float_of_substring(name[1]);
    if ( isnan(v))
      {
	cerr << "error NaN value for feature: ";
	cerr.write(name[0].start, name[0].end - name[0].start);
	cerr << " terminating." << endl;
	exit(1);
      }
    break;
  default:
    cerr << "example with a wierd name.  What is ";
    cerr.write(s.start, s.end - s.start);
    cerr << "\n";
  }
}

// new should be empty. --Alex
template<class T> void copy_v_array(v_array<T>& old, v_array<T>& new_va)
{
  // allocate new memory for new.
  new_va.begin = (T *) malloc(sizeof(T)*old.index());

  // copy the old to the new.
  memcpy(new_va.begin,old.begin,sizeof(T)*old.index());

  // update pointers
  new_va.end = new_va.begin + old.index();
  new_va.end_array = new_va.end;
}

char* c_string_of_substring(substring s)
{
  size_t len = s.end - s.start+1;
  char* ret = (char *)calloc(len,sizeof(char));
  memcpy(ret,s.start,len-1);
  return ret;
}

char* copy(char* base)
{
  size_t len = 0;
  while (base[len++] != '\0');
  char* ret = (char *)calloc(len,sizeof(char));
  memcpy(ret,base,len);
  return ret;
}

int read_features(parser* p, void* ex)
{
  example* ae = (example*)ex;
  char *line=NULL;
  int num_chars = readto(*(p->input), line, '\n');
  if (num_chars == 0)
    return num_chars;

  substring example = {line, line + num_chars};

  tokenize('|', example, p->channels);
  p->lp->default_label(ae->ld);
  substring* feature_start = &(p->channels[1]);
  if (*line == '|')
    feature_start = &(p->channels[0]);
  else
    {
      substring label_space = p->channels[0];
      char* tab_location = safe_index(label_space.start, '\t', label_space.end);
      if (tab_location != label_space.end)
	label_space.start = tab_location+1;

      tokenize(' ',label_space,p->words);
      if (p->words.index() > 0 && (p->words.last().end == label_space.end || *(p->words.last().start)=='\'') ) //The last field is a tag, so record and strip it off
	{
	  substring tag = p->words.pop();
	  if (*tag.start == '\'')
	    tag.start++;

	  push_many(ae->tag, tag.start, tag.end - tag.start);
	}

      p->lp->parse_label(ae->ld, p->words);
    }

  size_t mask = global.parse_mask;
  bool audit = global.audit;
  for (substring* i = feature_start; i != p->channels.end; i++) {
    substring channel = *i;

    tokenize(' ',channel, p->words);
    if (p->words.begin == p->words.end)
      continue;

    float channel_v = 1.;
    size_t channel_hash;
    char* base=NULL;
    size_t index = 0;
    bool new_index = false;
    size_t feature_offset = 0;
    if (channel.start[0] != ' ')//we have a nonanonymous namespace
      {
	feature_offset++;
	feature_value(p->words[0], p->name, channel_v);

	if (p->name.index() > 0) {
	  index = (unsigned char)(*p->name[0].start);
	  if (ae->atomics[index].begin == ae->atomics[index].end)
	    new_index = true;
	}
	if (audit)
	  base = c_string_of_substring(p->name[0]);
	channel_hash = p->hasher(p->name[0], hash_base);
      }
    else
      {
	index = (unsigned char)' ';
	if (ae->atomics[index].begin == ae->atomics[index].end)
	  new_index = true;
	if (audit)
	  {
	    base = (char *)calloc(2,sizeof(char));
	    base[0]=' ';
	    base[1]='\0';
	  }
	channel_hash = 0;
      }

    for (substring* i = p->words.begin+feature_offset; i != p->words.end; i++) {
      float v = 0.;
      feature_value(*i, p->name, v);
      v *= channel_v;

      size_t word_hash = (p->hasher(p->name[0], channel_hash)) & mask;
      feature f = {v,(uint32_t)word_hash};
      ae->sum_feat_sq[index] += v*v;
      push(ae->atomics[index], f);
    }

    if (new_index && ae->atomics[index].begin != ae->atomics[index].end)
      push(ae->indices, index);

    if (audit)
      {
	for (substring* i = p->words.begin+feature_offset; i != p->words.end; i++) {
	  float v = 0.;
	  feature_value(*i, p->name, v);
	  v *= channel_v;

	  size_t word_hash = (p->hasher(p->name[0], channel_hash)) & mask;

	  char* feature = c_string_of_substring(p->name[0]);
	  audit_data ad = {copy(base), feature, word_hash, v, true};
	  push(ae->audit_features[index], ad);
	}
	free(base);
      }
  }

  return num_chars;
}

<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    PyVTKSpecialObject.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
/*-----------------------------------------------------------------------
  The PyVTKSpecialObject was created in Feb 2001 by David Gobbi.
  It was substantially updated in April 2010 by David Gobbi.

  A PyVTKSpecialObject is a python object that represents an object
  that belongs to one of the special classes in VTK, that is, classes
  that are not derived from vtkObjectBase.  Unlike vtkObjects, these
  special objects are not reference counted: a PyVTKSpecialObject
  always contains its own copy of the C++ object.

  A PyVTKSpecialType is a simple structure that contains information
  about the C++ class, including the class name and methods.  Each
  PyVTKSpecialObject contains a pointer to its PyVTKSpecialType.
  The use of PyVTKSpecialType is a bit of a cop-out.  Ideally, each
  special type should have its own PyTypeObject struct that defines
  it as a distinct sub-type of PyVTKSpecialObjectType.  This would
  allow different special types to support different protocols and
  behaviours, instead of just supporting different methods.
-----------------------------------------------------------------------*/

#include "PyVTKSpecialObject.h"
#include "vtkPythonUtil.h"

#include <vtksys/ios/sstream>

//--------------------------------------------------------------------
PyVTKSpecialType::PyVTKSpecialType(
    char *cname, char *cdocs[], PyMethodDef *cmethods, PyMethodDef *ccons,
    PyVTKSpecialMethods *smethods)
{
  this->classname = PyString_FromString(cname);
  this->docstring = vtkPythonUtil::BuildDocString(cdocs);
  this->methods = cmethods;
  this->constructors = ccons;
  this->copy_func = smethods->copy_func;
  this->delete_func = smethods->delete_func;
  this->print_func = smethods->print_func;
  this->compare_func = smethods->compare_func;
  this->hash_func = smethods->hash_func;
}

//--------------------------------------------------------------------
static PyObject *PyVTKSpecialObject_PyString(PyVTKSpecialObject *self)
{
  vtksys_ios::ostringstream os;
  self->vtk_info->print_func(os, self->vtk_ptr);
  const vtksys_stl::string &s = os.str();
  return PyString_FromStringAndSize(s.data(), s.size());
}

//--------------------------------------------------------------------
static PyObject *PyVTKSpecialObject_PyRepr(PyVTKSpecialObject *self)
{
  vtksys_ios::ostringstream os;
  os << "(" << PyString_AS_STRING(self->vtk_info->classname) << ")";
  self->vtk_info->print_func(os, self->vtk_ptr);
  const vtksys_stl::string &s = os.str();
  return PyString_FromStringAndSize(s.data(), s.size());
}

//--------------------------------------------------------------------
static PyObject *PyVTKSpecialObject_PyGetAttr(PyVTKSpecialObject *self,
                                              PyObject *attr)
{
  char *name = PyString_AsString(attr);
  PyMethodDef *meth;

  if (name[0] == '_')
    {
    if (strcmp(name,"__name__") == 0)
      {
      Py_INCREF(self->vtk_info->classname);
      return self->vtk_info->classname;
      }
    if (strcmp(name,"__doc__") == 0)
      {
      Py_INCREF(self->vtk_info->docstring);
      return self->vtk_info->docstring;
      }
    if (strcmp(name,"__methods__") == 0)
      {
      meth = self->vtk_info->methods;
      PyObject *lst;
      int i, n;

      for (n = 0; meth && meth[n].ml_name; n++)
        {
        ;
        }

      if ((lst = PyList_New(n)) != NULL)
        {
        meth = self->vtk_info->methods;
        for (i = 0; i < n; i++)
          {
          PyList_SetItem(lst, i, PyString_FromString(meth[i].ml_name));
          }
        PyList_Sort(lst);
        }
      return lst;
      }

    if (strcmp(name,"__members__") == 0)
      {
      PyObject *lst;
      if ((lst = PyList_New(4)) != NULL)
        {
        PyList_SetItem(lst,0,PyString_FromString("__doc__"));
        PyList_SetItem(lst,1,PyString_FromString("__members__"));
        PyList_SetItem(lst,2,PyString_FromString("__methods__"));
        PyList_SetItem(lst,3,PyString_FromString("__name__"));
        }
      return lst;
      }
    }

  for (meth = self->vtk_info->methods; meth && meth->ml_name; meth++)
    {
    if (name[0] == meth->ml_name[0] && strcmp(name+1, meth->ml_name+1) == 0)
      {
      return PyCFunction_New(meth, (PyObject *)self);
      }
    }

  PyErr_SetString(PyExc_AttributeError, name);
  return NULL;
}

//--------------------------------------------------------------------
static void PyVTKSpecialObject_PyDelete(PyVTKSpecialObject *self)
{
  if (self->vtk_ptr)
    {
    self->vtk_info->delete_func(self->vtk_ptr);
    }
  self->vtk_ptr = NULL;
#if (PY_MAJOR_VERSION >= 2)
  PyObject_Del(self);
#else
  PyMem_DEL(self);
#endif
}

//--------------------------------------------------------------------
static long PyVTKSpecialObject_PyHash(PyVTKSpecialObject *self)
{
  // self->vtk_hash must never be set to anything but -1 for mutable objects
  if (self->vtk_hash != -1)
    {
    return self->vtk_hash;
    }

  if (self->vtk_ptr && self->vtk_info->hash_func)
    {
    int imm = 0;
    long val = self->vtk_info->hash_func(self->vtk_ptr, &imm);
    if (val != -1)
      {
      if (imm)
        {
        // cache the hash for immutable objects
        self->vtk_hash = val;
        }
      return val;
      }
    }
// python 2.6
#if PY_VERSION_HEX >= 0x02060000
  return PyObject_HashNotImplemented((PyObject *)self);
#else
  PyErr_SetString(PyExc_TypeError, (char *)"object is not hashable");
  return -1;
#endif
}

//--------------------------------------------------------------------
static PyObject *PyVTKSpecialObject_PyRichCompare(
  PyVTKSpecialObject *self, PyVTKSpecialObject *o, int opid)
{
  if (self->vtk_ptr && self->vtk_info->compare_func)
    {
    int val = self->vtk_info->compare_func(self->vtk_ptr, o->vtk_ptr, opid);
    if (val == 0)
      {
      Py_INCREF(Py_False);
      return Py_False;
      }
    else if (val != -1)
      {
      Py_INCREF(Py_True);
      return Py_True;
      }
    }

  PyErr_SetString(PyExc_TypeError, (char *)"operation not available");
  return NULL;
// Returning "None" is also valid, but not as informative
#if PY_VERSION_HEX >= 0x02010000
//  Py_INCREF(Py_NotImplemented);
//  return Py_NotImplemented;
#else
//  Py_INCREF(Py_None);
//  return Py_None;
#endif
}

//--------------------------------------------------------------------
static PyTypeObject PyVTKSpecialObjectType = {
  PyObject_HEAD_INIT(&PyType_Type)
  0,
  (char*)"vtkspecialobject",             // tp_name
  sizeof(PyVTKSpecialObject),            // tp_basicsize
  0,                                     // tp_itemsize
  (destructor)PyVTKSpecialObject_PyDelete, // tp_dealloc
  (printfunc)0,                          // tp_print
  (getattrfunc)0,                        // tp_getattr
  (setattrfunc)0,                        // tp_setattr
  (cmpfunc)0,                            // tp_compare
  (reprfunc)PyVTKSpecialObject_PyRepr,   // tp_repr
  0,                                     // tp_as_number
  0,                                     // tp_as_sequence
  0,                                     // tp_as_mapping
  (hashfunc)PyVTKSpecialObject_PyHash,   // tp_hash
  (ternaryfunc)0,                        // tp_call
  (reprfunc)PyVTKSpecialObject_PyString, // tp_string
  (getattrofunc)PyVTKSpecialObject_PyGetAttr, // tp_getattro
  (setattrofunc)0,                       // tp_setattro
  0,                                     // tp_as_buffer
  Py_TPFLAGS_HAVE_RICHCOMPARE,           // tp_flags
  (char*)"vtkspecialobject - a vtk object not derived from vtkObjectBase.", // tp_doc
  0,                                     // tp_traverse
  0,                                     // tp_clear
  (richcmpfunc)PyVTKSpecialObject_PyRichCompare,  // tp_richcompare
  0,                                     // tp_weaklistoffset
  VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED
};

//--------------------------------------------------------------------
int PyVTKSpecialObject_Check(PyObject *obj)
{
  return (obj->ob_type == &PyVTKSpecialObjectType);
}

//--------------------------------------------------------------------
PyObject *PyVTKSpecialObject_New(const char *classname, void *ptr)
{
  // would be nice if "info" could be passed instead if "classname"
  PyVTKSpecialType *info = vtkPythonUtil::FindSpecialType(classname);

#if (PY_MAJOR_VERSION >= 2)
  PyVTKSpecialObject *self = PyObject_New(PyVTKSpecialObject,
                                          &PyVTKSpecialObjectType);
#else
  PyVTKSpecialObject *self = PyObject_NEW(PyVTKSpecialObject,
                                          &PyVTKSpecialObjectType);
#endif

  self->vtk_ptr = ptr;
  self->vtk_hash = -1;
  self->vtk_info = info;

  return (PyObject *)self;
}

//--------------------------------------------------------------------
PyObject *PyVTKSpecialObject_CopyNew(const char *classname, const void *ptr)
{
  PyVTKSpecialType *info = vtkPythonUtil::FindSpecialType(classname);

  if (info == 0)
    {
    char buf[256];
    sprintf(buf,"cannot create object of unknown type \"%s\"",classname);
    PyErr_SetString(PyExc_ValueError,buf);
    return NULL;
    }

#if (PY_MAJOR_VERSION >= 2)
  PyVTKSpecialObject *self = PyObject_New(PyVTKSpecialObject,
                                          &PyVTKSpecialObjectType);
#else
  PyVTKSpecialObject *self = PyObject_NEW(PyVTKSpecialObject,
                                          &PyVTKSpecialObjectType);
#endif

  self->vtk_ptr = info->copy_func(ptr);
  self->vtk_hash = -1;
  self->vtk_info = info;

  return (PyObject *)self;
}

//--------------------------------------------------------------------
PyObject *PyVTKSpecialType_New(
  PyMethodDef *newmethod, PyMethodDef *methods, PyMethodDef *constructors,
  char *classname, char *docstring[], PyVTKSpecialMethods *smethods)
{
  // Add this type to the special type map
  PyVTKSpecialType *info =
    vtkPythonUtil::AddSpecialTypeToMap(
      classname, docstring, methods, constructors, smethods);

  // Add the built docstring to the method
  newmethod->ml_doc = PyString_AsString(info->docstring);

  // Returns a function.  Returning a type object would be nicer.
  return PyCFunction_New(newmethod, Py_None);
}
<commit_msg>BUG: PyVTKSpecialObject RichCompare needs to check arg types<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    PyVTKSpecialObject.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
/*-----------------------------------------------------------------------
  The PyVTKSpecialObject was created in Feb 2001 by David Gobbi.
  It was substantially updated in April 2010 by David Gobbi.

  A PyVTKSpecialObject is a python object that represents an object
  that belongs to one of the special classes in VTK, that is, classes
  that are not derived from vtkObjectBase.  Unlike vtkObjects, these
  special objects are not reference counted: a PyVTKSpecialObject
  always contains its own copy of the C++ object.

  A PyVTKSpecialType is a simple structure that contains information
  about the C++ class, including the class name and methods.  Each
  PyVTKSpecialObject contains a pointer to its PyVTKSpecialType.
  The use of PyVTKSpecialType is a bit of a cop-out.  Ideally, each
  special type should have its own PyTypeObject struct that defines
  it as a distinct sub-type of PyVTKSpecialObjectType.  This would
  allow different special types to support different protocols and
  behaviours, instead of just supporting different methods.
-----------------------------------------------------------------------*/

#include "PyVTKSpecialObject.h"
#include "vtkPythonUtil.h"

#include <vtksys/ios/sstream>

//--------------------------------------------------------------------
PyVTKSpecialType::PyVTKSpecialType(
    char *cname, char *cdocs[], PyMethodDef *cmethods, PyMethodDef *ccons,
    PyVTKSpecialMethods *smethods)
{
  this->classname = PyString_FromString(cname);
  this->docstring = vtkPythonUtil::BuildDocString(cdocs);
  this->methods = cmethods;
  this->constructors = ccons;
  this->copy_func = smethods->copy_func;
  this->delete_func = smethods->delete_func;
  this->print_func = smethods->print_func;
  this->compare_func = smethods->compare_func;
  this->hash_func = smethods->hash_func;
}

//--------------------------------------------------------------------
static PyObject *PyVTKSpecialObject_PyString(PyVTKSpecialObject *self)
{
  vtksys_ios::ostringstream os;
  self->vtk_info->print_func(os, self->vtk_ptr);
  const vtksys_stl::string &s = os.str();
  return PyString_FromStringAndSize(s.data(), s.size());
}

//--------------------------------------------------------------------
static PyObject *PyVTKSpecialObject_PyRepr(PyVTKSpecialObject *self)
{
  vtksys_ios::ostringstream os;
  os << "(" << PyString_AS_STRING(self->vtk_info->classname) << ")";
  self->vtk_info->print_func(os, self->vtk_ptr);
  const vtksys_stl::string &s = os.str();
  return PyString_FromStringAndSize(s.data(), s.size());
}

//--------------------------------------------------------------------
static PyObject *PyVTKSpecialObject_PyGetAttr(PyVTKSpecialObject *self,
                                              PyObject *attr)
{
  char *name = PyString_AsString(attr);
  PyMethodDef *meth;

  if (name[0] == '_')
    {
    if (strcmp(name,"__name__") == 0)
      {
      Py_INCREF(self->vtk_info->classname);
      return self->vtk_info->classname;
      }
    if (strcmp(name,"__doc__") == 0)
      {
      Py_INCREF(self->vtk_info->docstring);
      return self->vtk_info->docstring;
      }
    if (strcmp(name,"__methods__") == 0)
      {
      meth = self->vtk_info->methods;
      PyObject *lst;
      int i, n;

      for (n = 0; meth && meth[n].ml_name; n++)
        {
        ;
        }

      if ((lst = PyList_New(n)) != NULL)
        {
        meth = self->vtk_info->methods;
        for (i = 0; i < n; i++)
          {
          PyList_SetItem(lst, i, PyString_FromString(meth[i].ml_name));
          }
        PyList_Sort(lst);
        }
      return lst;
      }

    if (strcmp(name,"__members__") == 0)
      {
      PyObject *lst;
      if ((lst = PyList_New(4)) != NULL)
        {
        PyList_SetItem(lst,0,PyString_FromString("__doc__"));
        PyList_SetItem(lst,1,PyString_FromString("__members__"));
        PyList_SetItem(lst,2,PyString_FromString("__methods__"));
        PyList_SetItem(lst,3,PyString_FromString("__name__"));
        }
      return lst;
      }
    }

  for (meth = self->vtk_info->methods; meth && meth->ml_name; meth++)
    {
    if (name[0] == meth->ml_name[0] && strcmp(name+1, meth->ml_name+1) == 0)
      {
      return PyCFunction_New(meth, (PyObject *)self);
      }
    }

  PyErr_SetString(PyExc_AttributeError, name);
  return NULL;
}

//--------------------------------------------------------------------
static void PyVTKSpecialObject_PyDelete(PyVTKSpecialObject *self)
{
  if (self->vtk_ptr)
    {
    self->vtk_info->delete_func(self->vtk_ptr);
    }
  self->vtk_ptr = NULL;
#if (PY_MAJOR_VERSION >= 2)
  PyObject_Del(self);
#else
  PyMem_DEL(self);
#endif
}

//--------------------------------------------------------------------
static long PyVTKSpecialObject_PyHash(PyVTKSpecialObject *self)
{
  // self->vtk_hash must never be set to anything but -1 for mutable objects
  if (self->vtk_hash != -1)
    {
    return self->vtk_hash;
    }

  if (self->vtk_ptr && self->vtk_info->hash_func)
    {
    int imm = 0;
    long val = self->vtk_info->hash_func(self->vtk_ptr, &imm);
    if (val != -1)
      {
      if (imm)
        {
        // cache the hash for immutable objects
        self->vtk_hash = val;
        }
      return val;
      }
    }
// python 2.6
#if PY_VERSION_HEX >= 0x02060000
  return PyObject_HashNotImplemented((PyObject *)self);
#else
  PyErr_SetString(PyExc_TypeError, (char *)"object is not hashable");
  return -1;
#endif
}

//--------------------------------------------------------------------
static PyObject *PyVTKSpecialObject_PyRichCompare(
  PyObject *o1, PyObject *o2, int opid)
{
  // Heterogenous comparisons are not implemented
  if (!PyVTKSpecialObject_Check(o1) ||
      !PyVTKSpecialObject_Check(o2) ||
      (((PyVTKSpecialObject *)o1)->vtk_info !=
       ((PyVTKSpecialObject *)o2)->vtk_info))
    {
#if PY_VERSION_HEX >= 0x02010000
    Py_INCREF(Py_NotImplemented);
    return Py_NotImplemented;
#else
    Py_INCREF(Py_None);
    return Py_None;
#endif
    }

  // Types are matched, try to do the comparison
  PyVTKSpecialCompareFunc cmpfunc =
    ((PyVTKSpecialObject *)o1)->vtk_info->compare_func;

  if (cmpfunc)
    {
    int val = cmpfunc(((PyVTKSpecialObject *)o1)->vtk_ptr,
                      ((PyVTKSpecialObject *)o2)->vtk_ptr, opid);

    if (val == 0)
      {
      Py_INCREF(Py_False);
      return Py_False;
      }
    else if (val != -1)
      {
      Py_INCREF(Py_True);
      return Py_True;
      }
    }

  PyErr_SetString(PyExc_TypeError, (char *)"operation not available");
  return NULL;
}

//--------------------------------------------------------------------
static PyTypeObject PyVTKSpecialObjectType = {
  PyObject_HEAD_INIT(&PyType_Type)
  0,
  (char*)"vtkspecialobject",             // tp_name
  sizeof(PyVTKSpecialObject),            // tp_basicsize
  0,                                     // tp_itemsize
  (destructor)PyVTKSpecialObject_PyDelete, // tp_dealloc
  (printfunc)0,                          // tp_print
  (getattrfunc)0,                        // tp_getattr
  (setattrfunc)0,                        // tp_setattr
  (cmpfunc)0,                            // tp_compare
  (reprfunc)PyVTKSpecialObject_PyRepr,   // tp_repr
  0,                                     // tp_as_number
  0,                                     // tp_as_sequence
  0,                                     // tp_as_mapping
  (hashfunc)PyVTKSpecialObject_PyHash,   // tp_hash
  (ternaryfunc)0,                        // tp_call
  (reprfunc)PyVTKSpecialObject_PyString, // tp_string
  (getattrofunc)PyVTKSpecialObject_PyGetAttr, // tp_getattro
  (setattrofunc)0,                       // tp_setattro
  0,                                     // tp_as_buffer
  Py_TPFLAGS_HAVE_RICHCOMPARE,           // tp_flags
  (char*)"vtkspecialobject - a vtk object not derived from vtkObjectBase.", // tp_doc
  0,                                     // tp_traverse
  0,                                     // tp_clear
  (richcmpfunc)PyVTKSpecialObject_PyRichCompare,  // tp_richcompare
  0,                                     // tp_weaklistoffset
  VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED
};

//--------------------------------------------------------------------
int PyVTKSpecialObject_Check(PyObject *obj)
{
  return (obj->ob_type == &PyVTKSpecialObjectType);
}

//--------------------------------------------------------------------
PyObject *PyVTKSpecialObject_New(const char *classname, void *ptr)
{
  // would be nice if "info" could be passed instead if "classname"
  PyVTKSpecialType *info = vtkPythonUtil::FindSpecialType(classname);

#if (PY_MAJOR_VERSION >= 2)
  PyVTKSpecialObject *self = PyObject_New(PyVTKSpecialObject,
                                          &PyVTKSpecialObjectType);
#else
  PyVTKSpecialObject *self = PyObject_NEW(PyVTKSpecialObject,
                                          &PyVTKSpecialObjectType);
#endif

  self->vtk_ptr = ptr;
  self->vtk_hash = -1;
  self->vtk_info = info;

  return (PyObject *)self;
}

//--------------------------------------------------------------------
PyObject *PyVTKSpecialObject_CopyNew(const char *classname, const void *ptr)
{
  PyVTKSpecialType *info = vtkPythonUtil::FindSpecialType(classname);

  if (info == 0)
    {
    char buf[256];
    sprintf(buf,"cannot create object of unknown type \"%s\"",classname);
    PyErr_SetString(PyExc_ValueError,buf);
    return NULL;
    }

#if (PY_MAJOR_VERSION >= 2)
  PyVTKSpecialObject *self = PyObject_New(PyVTKSpecialObject,
                                          &PyVTKSpecialObjectType);
#else
  PyVTKSpecialObject *self = PyObject_NEW(PyVTKSpecialObject,
                                          &PyVTKSpecialObjectType);
#endif

  self->vtk_ptr = info->copy_func(ptr);
  self->vtk_hash = -1;
  self->vtk_info = info;

  return (PyObject *)self;
}

//--------------------------------------------------------------------
PyObject *PyVTKSpecialType_New(
  PyMethodDef *newmethod, PyMethodDef *methods, PyMethodDef *constructors,
  char *classname, char *docstring[], PyVTKSpecialMethods *smethods)
{
  // Add this type to the special type map
  PyVTKSpecialType *info =
    vtkPythonUtil::AddSpecialTypeToMap(
      classname, docstring, methods, constructors, smethods);

  // Add the built docstring to the method
  newmethod->ml_doc = PyString_AsString(info->docstring);

  // Returns a function.  Returning a type object would be nicer.
  return PyCFunction_New(newmethod, Py_None);
}
<|endoftext|>


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

  Library   : Image Registration Toolkit (IRTK)
  Module    : $Id$
  Copyright : Imperial College, Department of Computing
              Visual Information Processing (VIP), 2008 onwards
  Date      : $Date$
  Version   : $Revision$
  Changes   : $Author$

=========================================================================*/

#include <irtkImage.h>

#include <irtkHistogram.h>

#include <irtkTransformation.h>

// Default filenames
char *output_name = NULL, *prefix_name = NULL, *suffix_name = NULL, *textfile = NULL;

#define MAX_IMAGES 10000
#define EPSILON    0.001

void usage()
{
  cerr << "Usage: atlas [output] <input1..inputN> <options>\n" << endl;
  cerr << "where <options> is one or more of the following:\n";
  cerr << "<-imagenames file>      Name of file containing image names for <input1..inputN>\n";
  cerr << "<-prefix directory>     Directory in which to find the images\n";
  cerr << "<-gaussian mean sigma>  Use Gaussian with mean and sigma for kernel-based smoothing\n";
  cerr << "<-epsilon value>        Epsilon value for ignoring image in kernel-based smoothing (default = " << EPSILON << ")\n";
  cerr << "<-scaling value>        Scaling value for final atlas (default = 1)\n";
  cerr << "<-norm>                 Normalise intensities before atlas construction (default = off)\n";
  exit(1);
}

void normalise(irtkGreyImage &input, irtkRealImage &output)
{
  int j;
  double mean, std;
  irtkGreyPixel *ptr1;
  irtkRealPixel *ptr2;

  // Set up input histogram
  cerr << "Setting up input histogram..."; cout.flush();
  irtkGreyPixel min, max;
  input.GetMinMax(&min, &max);
  irtkHistogram histogram(max-min+1);
  histogram.PutMin(min-0.5);
  histogram.PutMax(max+0.5);

  ptr1 = input.GetPointerToVoxels();
  for (j = 0; j < input.GetNumberOfVoxels(); j++) {
    histogram.AddSample(*ptr1);
    ptr1++;
  }

  mean = histogram.Mean();
  std  = histogram.StandardDeviation();
  cout << "done" << endl;
  cerr << "Stats: Mean = " << mean << " SD = " << std << endl;

  ptr1 = input.GetPointerToVoxels();
  ptr2 = output.GetPointerToVoxels();
  for (j = 0; j < input.GetNumberOfVoxels(); j++) {
    *ptr2 = (*ptr1 - mean) / std;
    ptr1++;
    ptr2++;
  }
}

int main(int argc, char **argv)
{
  double scale, mean, sigma, epsilon;
  int i, j, n, padding, norm, no, ok;
  irtkGreyPixel *ptr1;
  irtkGreyImage input;
  irtkRealPixel *ptr2;
  irtkRealImage tmp, output;

  // Check command line
  if (argc < 5) {
    usage();
  }

  // Parse parameters
  output_name = argv[1];
  argc--;
  argv++;

  // Default: scaling factor
  scale = 1;

  // Default: No kernel smoothing
  mean  = 0;
  sigma = 1;

  // Default: No intensity  normalisation
  norm  = False;

  // Default: Epsilon
  epsilon = EPSILON;

  // Default padding
  padding = MIN_GREY;

  // Parse input file names and values
  char  **input_name   = new char *[MAX_IMAGES];
  double *input_value  = new double[MAX_IMAGES];
  double *input_weight = new double[MAX_IMAGES];
  double  total_weight = 0;

  // Parse any remaining paramters
  no = 0;

  while ((argc > 1) && (argv[1][0] != '-' )) {
    input_name[no]   = argv[1];
    input_weight[no] = 1;
    total_weight    += 1;
    no++;
    argc--;
    argv++;
  }

  while (argc > 1) {
    ok = False;
    if ((ok == False) && (strcmp(argv[1], "-scaling") == 0)) {
      argc--;
      argv++;
      scale = atof(argv[1]);
      argc--;
      argv++;
      ok = True;
    }
    if ((ok == False) && (strcmp(argv[1], "-gaussian") == 0)) {
      argc--;
      argv++;
      mean = atof(argv[1]);
      argc--;
      argv++;
      sigma = atof(argv[1]);
      argc--;
      argv++;
      ok = True;
    }
    if ((ok == False) && (strcmp(argv[1], "-norm") == 0)) {
      argc--;
      argv++;
      norm = True;
      ok = True;
    }
    if ((ok == False) && (strcmp(argv[1], "-imagenames") == 0)) {
      argc--;
      argv++;
      textfile = argv[1];
      argc--;
      argv++;
      ok = True;
    }
    if ((ok == False) && (strcmp(argv[1], "-padding") == 0)) {
      argc--;
      argv++;
      padding = atoi(argv[1]);
      argc--;
      argv++;
      ok = True;
    }
    if ((ok == False) && (strcmp(argv[1], "-prefix") == 0)) {
       argc--;
       argv++;
       prefix_name = argv[1];
       argc--;
       argv++;
       ok = True;
     }
    if ((ok == False) && (strcmp(argv[1], "-suffix") == 0)) {
       argc--;
       argv++;
       suffix_name = argv[1];
       argc--;
       argv++;
       ok = True;
     }
    if ((ok == False) && (strcmp(argv[1], "-epsilon") == 0)) {
      argc--;
      argv++;
      epsilon = atof(argv[1]);
      argc--;
      argv++;
      ok = True;
    }
    if (ok == False) {
      cerr << "Unknown argument: " << argv[1] << endl << endl;
      usage();
    }
  }

  if (textfile != NULL) {
    ifstream in(textfile);
    if (in.is_open()) {
      while (!in.eof()) {
        input_name[no] = new char[256];
        in >> input_name[no] >> input_value[no];
        if (strlen(input_name[no]) > 0) {
          input_weight[no] = 1.0 / sqrt(2.0) / sigma * exp(-pow((mean - input_value[no])/sigma, 2.0)/2);
          if (input_weight[no] > epsilon) {
            total_weight   += input_weight[no];
            cout << input_value[no] << " " << input_weight[no] << " " << total_weight << endl;
            no++;
          }
        }
      }
      in.close();
    } else {
      cout << "atlas: Unable to open file " << textfile << endl;
      exit(1);
    }
  }

  // Read and add one input image after the other
  n = 0;
  for (i = 0; i < no; i++) {
    char buffer[255];

    // Read input
    if (prefix_name != NULL) {
      sprintf(buffer, "%s%s", prefix_name, input_name[i]);
    } else {
      sprintf(buffer, "%s", input_name[i]);
    }
    input_name[i] = strdup(buffer);
    if (suffix_name != NULL) {
      sprintf(buffer, "%s%s",  input_name[i], suffix_name);
    } else {
      sprintf(buffer, "%s", input_name[i]);
    }
    input_name[i] = strdup(buffer);

    cout << "Reading input image " << input_name[i] << "... "; cout.flush();
    input.Read(input_name[i]);
    cout << "done" << endl;

    if (i == 0) {
      n = input.GetX()*input.GetY()*input.GetZ();
      output = input;
      ptr2 = output.GetPointerToVoxels();
      for (j = 0; j < n; j++) {
        *ptr2 = 0;
        ptr2++;
      }
    }

    tmp = input;
    if (norm == True) normalise(input, tmp);

    cerr << "Adding input to atlas..."; cout.flush();
    tmp *= input_weight[i];
    output += tmp;
    cerr << "done\n";

  }

  ptr1 = input.GetPointerToVoxels();
  ptr2 = output.GetPointerToVoxels();
  for (j = 0; j < n; j++) {
    *ptr1 = round(scale * *ptr2 / total_weight);
    ptr1++;
    ptr2++;
  }
  cerr << " done\n";

  // Write atlas
  cerr << "Writing atlas to " << output_name << " ... ";
  cout.flush();
  input.Write(output_name);
  cerr << "done\n";
}
<commit_msg>Allow user to calculate their own weights (i.e. can override default use of Gaussian function).<commit_after>/*=========================================================================

  Library   : Image Registration Toolkit (IRTK)
  Module    : $Id$
  Copyright : Imperial College, Department of Computing
              Visual Information Processing (VIP), 2008 onwards
  Date      : $Date$
  Version   : $Revision$
  Changes   : $Author$

=========================================================================*/

#include <irtkImage.h>

#include <irtkHistogram.h>

#include <irtkTransformation.h>

// Default filenames
char *output_name = NULL, *prefix_name = NULL, *suffix_name = NULL, *textfile = NULL;

#define MAX_IMAGES 10000
#define EPSILON    0.001

void usage()
{
  cerr << "Usage: atlas [output] <input1..inputN> <options>" << endl;
  cerr << "" << endl;
  cerr << "Make an atlas from a given set of input images. All input images must have the" << endl;
  cerr << "same voxel lattice. Names of input images can be given on the command line or" << endl;
  cerr << "in a file (see below)." << endl;
  cerr << "" << endl;
  cerr << "If they are named on the command line, images are given equal weighting." << endl;
  cerr << "Different weights can be given if a file with names is provided." << endl;
  cerr << "" << endl;
  cerr << "where <options> is one or more of the following:" << endl;
  cerr << "<-imagenames file>      File containing image names and values to use for weighting." << endl;
  cerr << "                        The format should be one line for each image with" << endl;
  cerr << "                          \"image_name value\"" << endl;
  cerr << "                        on each line. If a mean and sigma value are specified" << endl;
  cerr << "                        with the \'-gaussian\' flag (see below), then the values" << endl;
  cerr << "                        are converted to weights using the corresponding Gaussian" << endl;
  cerr << "                        function. Otherwise, the values in the file are used" << endl;
  cerr << "                        directly as weights." << endl;
  cerr << "<-prefix directory>     Directory in which to find the images." << endl;
  cerr << "<-gaussian mean sigma>  Use Gaussian with mean and sigma for kernel-based smoothing\n";
  cerr << "<-epsilon value>        Epsilon value for ignoring image in kernel-based smoothing " << endl;
  cerr << "                          (default = " << EPSILON << ")" << endl;
  cerr << "<-scaling value>        Scaling value for final atlas (default = 1)\n";
  cerr << "<-norm>                 Normalise intensities before atlas construction " << endl;
  cerr << "                          (default = off)\n";
  exit(1);
}

void normalise(irtkGreyImage &input, irtkRealImage &output)
{
  int j;
  double mean, std;
  irtkGreyPixel *ptr1;
  irtkRealPixel *ptr2;

  // Set up input histogram
  cerr << "Setting up input histogram..."; cout.flush();
  irtkGreyPixel min, max;
  input.GetMinMax(&min, &max);
  irtkHistogram histogram(max-min+1);
  histogram.PutMin(min-0.5);
  histogram.PutMax(max+0.5);

  ptr1 = input.GetPointerToVoxels();
  for (j = 0; j < input.GetNumberOfVoxels(); j++) {
    histogram.AddSample(*ptr1);
    ptr1++;
  }

  mean = histogram.Mean();
  std  = histogram.StandardDeviation();
  cout << "done" << endl;
  cerr << "Stats: Mean = " << mean << " SD = " << std << endl;

  ptr1 = input.GetPointerToVoxels();
  ptr2 = output.GetPointerToVoxels();
  for (j = 0; j < input.GetNumberOfVoxels(); j++) {
    *ptr2 = (*ptr1 - mean) / std;
    ptr1++;
    ptr2++;
  }
}

int main(int argc, char **argv)
{
  double scale, mean, sigma, epsilon;
  int i, j, n, padding, norm, no, ok;
  int useGaussianWeights;
  irtkGreyPixel *ptr1;
  irtkGreyImage input;
  irtkRealPixel *ptr2;
  irtkRealImage tmp, output;

  // Check command line
  if (argc < 5) {
    usage();
  }

  // Parse parameters
  output_name = argv[1];
  argc--;
  argv++;

  // Default: scaling factor
  scale = 1;

  // Default: Use weights directly. Alternatively, convert using Gaussian formula.
  useGaussianWeights = False;

  // Default values for kernel smoothing
  mean  = 0;
  sigma = 1;

  // Default: No intensity  normalisation
  norm  = False;

  // Default: Epsilon
  epsilon = EPSILON;

  // Default padding
  padding = MIN_GREY;

  // Parse input file names and values
  char  **input_name   = new char *[MAX_IMAGES];
  double *input_value  = new double[MAX_IMAGES];
  double *input_weight = new double[MAX_IMAGES];
  double  total_weight = 0;

  // Parse any remaining paramters
  no = 0;

  while ((argc > 1) && (argv[1][0] != '-' )) {
    input_name[no]   = argv[1];
    input_weight[no] = 1;
    total_weight    += 1;
    no++;
    argc--;
    argv++;
  }

  while (argc > 1) {
    ok = False;
    if ((ok == False) && (strcmp(argv[1], "-scaling") == 0)) {
      argc--;
      argv++;
      scale = atof(argv[1]);
      argc--;
      argv++;
      ok = True;
    }
    if ((ok == False) && (strcmp(argv[1], "-gaussian") == 0)) {
      argc--;
      argv++;
      useGaussianWeights = True;
      mean = atof(argv[1]);
      argc--;
      argv++;
      sigma = atof(argv[1]);
      argc--;
      argv++;
      ok = True;
    }
    if ((ok == False) && (strcmp(argv[1], "-norm") == 0)) {
      argc--;
      argv++;
      norm = True;
      ok = True;
    }
    if ((ok == False) && (strcmp(argv[1], "-imagenames") == 0)) {
      argc--;
      argv++;
      textfile = argv[1];
      argc--;
      argv++;
      ok = True;
    }
    if ((ok == False) && (strcmp(argv[1], "-padding") == 0)) {
      argc--;
      argv++;
      padding = atoi(argv[1]);
      argc--;
      argv++;
      ok = True;
    }
    if ((ok == False) && (strcmp(argv[1], "-prefix") == 0)) {
       argc--;
       argv++;
       prefix_name = argv[1];
       argc--;
       argv++;
       ok = True;
     }
    if ((ok == False) && (strcmp(argv[1], "-suffix") == 0)) {
       argc--;
       argv++;
       suffix_name = argv[1];
       argc--;
       argv++;
       ok = True;
     }
    if ((ok == False) && (strcmp(argv[1], "-epsilon") == 0)) {
      argc--;
      argv++;
      epsilon = atof(argv[1]);
      argc--;
      argv++;
      ok = True;
    }
    if (ok == False) {
      cerr << "Unknown argument: " << argv[1] << endl << endl;
      usage();
    }
  }

  if (textfile != NULL) {
    ifstream in(textfile);
    if (in.is_open()) {
      while (!in.eof()) {
        input_name[no] = new char[256];
        in >> input_name[no] >> input_value[no];
        if (strlen(input_name[no]) > 0) {

          if (useGaussianWeights == True){
            // Convert input value to weight based on Gaussian centred at above specified mean.
            input_weight[no] = 1.0 / sqrt(2.0) / sigma * exp(-pow((mean - input_value[no])/sigma, 2.0)/2);
          } else {
            // Use input value directly as a weight.
            input_weight[no] = input_value[no];
          }

          if (input_weight[no] > epsilon) {
            total_weight   += input_weight[no];
            cout << input_value[no] << " " << input_weight[no] << " " << total_weight << endl;
            no++;
          }
        }
      }
      in.close();
    } else {
      cout << "atlas: Unable to open file " << textfile << endl;
      exit(1);
    }
  }

  // Read and add one input image after the other
  n = 0;
  for (i = 0; i < no; i++) {
    char buffer[255];

    // Read input
    if (prefix_name != NULL) {
      sprintf(buffer, "%s%s", prefix_name, input_name[i]);
    } else {
      sprintf(buffer, "%s", input_name[i]);
    }
    input_name[i] = strdup(buffer);
    if (suffix_name != NULL) {
      sprintf(buffer, "%s%s",  input_name[i], suffix_name);
    } else {
      sprintf(buffer, "%s", input_name[i]);
    }
    input_name[i] = strdup(buffer);

    cout << "Reading input image " << input_name[i] << "... "; cout.flush();
    input.Read(input_name[i]);
    cout << "done" << endl;

    if (i == 0) {
      n = input.GetX()*input.GetY()*input.GetZ();
      output = input;
      ptr2 = output.GetPointerToVoxels();
      for (j = 0; j < n; j++) {
        *ptr2 = 0;
        ptr2++;
      }
    }

    tmp = input;
    if (norm == True) normalise(input, tmp);

    cerr << "Adding input to atlas..."; cout.flush();
    tmp *= input_weight[i];
    output += tmp;
    cerr << "done\n";

  }

  ptr1 = input.GetPointerToVoxels();
  ptr2 = output.GetPointerToVoxels();
  for (j = 0; j < n; j++) {
    *ptr1 = round(scale * *ptr2 / total_weight);
    ptr1++;
    ptr2++;
  }
  cerr << " done\n";

  // Write atlas
  cerr << "Writing atlas to " << output_name << " ... ";
  cout.flush();
  input.Write(output_name);
  cerr << "done\n";
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
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.

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 <osrm/RouteParameters.h>

#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/sequence/intrinsic.hpp>
#include <boost/fusion/include/at_c.hpp>

RouteParameters::RouteParameters()
    : zoom_level(18), print_instructions(false), alternate_route(true), geometry(true),
      compression(true), deprecatedAPI(false), check_sum(-1)
{
}

void RouteParameters::setZoomLevel(const short level)
{
    if (18 >= level && 0 <= level)
    {
        zoom_level = level;
    }
}

void RouteParameters::setAlternateRouteFlag(const bool flag) { alternate_route = flag; }

void RouteParameters::setDeprecatedAPIFlag(const std::string &) { deprecatedAPI = true; }

void RouteParameters::setChecksum(const unsigned sum) { check_sum = sum; }

void RouteParameters::setInstructionFlag(const bool flag) { print_instructions = flag; }

void RouteParameters::setService(const std::string &service_string) { service = service_string; }

void RouteParameters::setOutputFormat(const std::string &format) { output_format = format; }

void RouteParameters::setJSONpParameter(const std::string &parameter) { jsonp_parameter = parameter; }

void RouteParameters::addHint(const std::string &hint)
{
    hints.resize(coordinates.size());
    if (!hints.empty())
    {
        hints.back() = hint;
    }
}

void RouteParameters::setLanguage(const std::string &language_string) { language = language_string; }

void RouteParameters::setGeometryFlag(const bool flag) { geometry = flag; }

void RouteParameters::setCompressionFlag(const bool flag) { compression = flag; }

void RouteParameters::addCoordinate(const boost::fusion::vector<double, double> &transmitted_coordinates)
{
    coordinates.emplace_back(
        static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<0>(transmitted_coordinates)),
        static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<1>(transmitted_coordinates)));
}
<commit_msg>reformat to cut long line<commit_after>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
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.

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 <osrm/RouteParameters.h>

#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/sequence/intrinsic.hpp>
#include <boost/fusion/include/at_c.hpp>

RouteParameters::RouteParameters()
    : zoom_level(18), print_instructions(false), alternate_route(true), geometry(true),
      compression(true), deprecatedAPI(false), check_sum(-1)
{
}

void RouteParameters::setZoomLevel(const short level)
{
    if (18 >= level && 0 <= level)
    {
        zoom_level = level;
    }
}

void RouteParameters::setAlternateRouteFlag(const bool flag) { alternate_route = flag; }

void RouteParameters::setDeprecatedAPIFlag(const std::string &) { deprecatedAPI = true; }

void RouteParameters::setChecksum(const unsigned sum) { check_sum = sum; }

void RouteParameters::setInstructionFlag(const bool flag) { print_instructions = flag; }

void RouteParameters::setService(const std::string &service_string) { service = service_string; }

void RouteParameters::setOutputFormat(const std::string &format) { output_format = format; }

void RouteParameters::setJSONpParameter(const std::string &parameter)
{
    jsonp_parameter = parameter;
}

void RouteParameters::addHint(const std::string &hint)
{
    hints.resize(coordinates.size());
    if (!hints.empty())
    {
        hints.back() = hint;
    }
}

void RouteParameters::setLanguage(const std::string &language_string)
{
    language = language_string;
}

void RouteParameters::setGeometryFlag(const bool flag) { geometry = flag; }

void RouteParameters::setCompressionFlag(const bool flag) { compression = flag; }

void
RouteParameters::addCoordinate(const boost::fusion::vector<double, double> &transmitted_coordinates)
{
    coordinates.emplace_back(
        static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<0>(transmitted_coordinates)),
        static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<1>(transmitted_coordinates)));
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2008-2013 the Urho3D project.
//
// 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.
//

#include "Precompiled.h"
#include "Geometry.h"
#include "Graphics.h"
#include "IndexBuffer.h"
#include "Log.h"
#include "Ray.h"
#include "VertexBuffer.h"

#include "DebugNew.h"

namespace Urho3D
{

Geometry::Geometry(Context* context) :
    Object(context),
    primitiveType_(TRIANGLE_LIST),
    indexStart_(0),
    indexCount_(0),
    vertexStart_(0),
    vertexCount_(0),
    positionBufferIndex_(M_MAX_UNSIGNED),
    rawVertexSize_(0),
    rawElementMask_(0),
    rawIndexSize_(0),
    lodDistance_(0.0f)
{
    SetNumVertexBuffers(1);
}

Geometry::~Geometry()
{
}

bool Geometry::SetNumVertexBuffers(unsigned num)
{
    if (num >= MAX_VERTEX_STREAMS)
    {
        LOGERROR("Too many vertex streams");
        return false;
    }

    unsigned oldSize = vertexBuffers_.Size();
    vertexBuffers_.Resize(num);
    elementMasks_.Resize(num);

    for (unsigned i = oldSize; i < num; ++i)
        elementMasks_[i] = MASK_NONE;

    GetPositionBufferIndex();
    return true;
}

bool Geometry::SetVertexBuffer(unsigned index, VertexBuffer* buffer, unsigned elementMask)
{
    if (index >= vertexBuffers_.Size())
    {
        LOGERROR("Stream index out of bounds");
        return false;
    }

    vertexBuffers_[index] = buffer;

    if (buffer)
    {
        if (elementMask == MASK_DEFAULT)
            elementMasks_[index] = buffer->GetElementMask();
        else
            elementMasks_[index] = elementMask;
    }

    GetPositionBufferIndex();
    return true;
}

void Geometry::SetIndexBuffer(IndexBuffer* buffer)
{
    indexBuffer_ = buffer;
}

bool Geometry::SetDrawRange(PrimitiveType type, unsigned indexStart, unsigned indexCount, bool getUsedVertexRange)
{
    if (!indexBuffer_ && !rawIndexData_)
    {
        LOGERROR("Null index buffer and no raw index data, can not define indexed draw range");
        return false;
    }
    if (indexBuffer_ && indexStart + indexCount > indexBuffer_->GetIndexCount())
    {
        LOGERROR("Illegal draw range " + String(indexStart) + " to " + String(indexStart + indexCount - 1) + ", index buffer has " +
            String(indexBuffer_->GetIndexCount()) + " indices");
        return false;
    }

    primitiveType_ = type;
    indexStart_ = indexStart;
    indexCount_ = indexCount;

    // Get min.vertex index and num of vertices from index buffer. If it fails, use full range as fallback
    if (indexCount)
    {
        vertexStart_ = 0;
        vertexCount_ = vertexBuffers_[0] ? vertexBuffers_[0]->GetVertexCount() : 0;

        if (getUsedVertexRange && indexBuffer_)
            indexBuffer_->GetUsedVertexRange(indexStart_, indexCount_, vertexStart_, vertexCount_);
    }
    else
    {
        vertexStart_ = 0;
        vertexCount_ = 0;
    }

    return true;
}

bool Geometry::SetDrawRange(PrimitiveType type, unsigned indexStart, unsigned indexCount, unsigned minVertex, unsigned vertexCount)
{
    if (indexBuffer_)
    {
        if (indexStart + indexCount > indexBuffer_->GetIndexCount())
        {
            LOGERROR("Illegal draw range " + String(indexStart) + " to " + String(indexStart + indexCount - 1) +
                ", index buffer has " + String(indexBuffer_->GetIndexCount()) + " indices");
            return false;
        }
    }
    else if (!rawIndexData_)
    {
        indexStart = 0;
        indexCount = 0;
    }

    primitiveType_ = type;
    indexStart_ = indexStart;
    indexCount_ = indexCount;
    vertexStart_ = minVertex;
    vertexCount_ = vertexCount;

    return true;
}

void Geometry::SetLodDistance(float distance)
{
    if (distance < 0.0f)
        distance = 0.0f;

    lodDistance_ = distance;
}

void Geometry::SetRawVertexData(SharedArrayPtr<unsigned char> data, unsigned vertexSize, unsigned elementMask)
{
    rawVertexData_ = data;
    rawVertexSize_ = vertexSize;
    rawElementMask_ = elementMask;
}

void Geometry::SetRawIndexData(SharedArrayPtr<unsigned char> data, unsigned indexSize)
{
    rawIndexData_ = data;
    rawIndexSize_ = indexSize;
}

void Geometry::Draw(Graphics* graphics)
{
    if (indexBuffer_ && indexCount_ > 0)
    {
        graphics->SetIndexBuffer(indexBuffer_);
        graphics->SetVertexBuffers(vertexBuffers_, elementMasks_);
        graphics->Draw(primitiveType_, indexStart_, indexCount_, vertexStart_, vertexCount_);
    }
    else if (vertexCount_ > 0)
    {
        graphics->SetVertexBuffers(vertexBuffers_, elementMasks_);
        graphics->Draw(primitiveType_, vertexStart_, vertexCount_);
    }
}

VertexBuffer* Geometry::GetVertexBuffer(unsigned index) const
{
    return index < vertexBuffers_.Size() ? vertexBuffers_[index] : (VertexBuffer*)0;
}

unsigned Geometry::GetVertexElementMask(unsigned index) const
{
    return index < elementMasks_.Size() ? elementMasks_[index] : 0;
}

unsigned short Geometry::GetBufferHash() const
{
    unsigned short hash = 0;

    for (unsigned i = 0; i < vertexBuffers_.Size(); ++i)
    {
        VertexBuffer* vBuf = vertexBuffers_[i];
        hash += *((unsigned short*)&vBuf);
    }

    IndexBuffer* iBuf = indexBuffer_;
    hash += *((unsigned short*)&iBuf);

    return hash;
}

void Geometry::GetRawData(const unsigned char*& vertexData, unsigned& vertexSize, const unsigned char*& indexData,
    unsigned& indexSize, unsigned& elementMask) const
{
    // These shared arrays are held in the vertex/index buffers so it's safe to construct temporary shared pointers
    SharedArrayPtr<unsigned char> vertexDataShared;
    SharedArrayPtr<unsigned char> indexDataShared;
    GetRawDataShared(vertexDataShared, vertexSize, indexDataShared, indexSize, elementMask);
    vertexData = vertexDataShared.Get();
    indexData = indexDataShared.Get();
}

void Geometry::GetRawDataShared(SharedArrayPtr<unsigned char>& vertexData, unsigned& vertexSize,
    SharedArrayPtr<unsigned char>& indexData, unsigned& indexSize, unsigned& elementMask) const
{
    if (rawVertexData_)
    {
        vertexData = rawVertexData_;
        vertexSize = rawVertexSize_;
        elementMask = rawElementMask_;
    }
    else
    {
        if (positionBufferIndex_ < vertexBuffers_.Size() && vertexBuffers_[positionBufferIndex_])
        {
            vertexData = vertexBuffers_[positionBufferIndex_]->GetShadowDataShared();
            if (vertexData)
            {
                vertexSize = vertexBuffers_[positionBufferIndex_]->GetVertexSize();
                elementMask = vertexBuffers_[positionBufferIndex_]->GetElementMask();
            }
            else
            {
                vertexSize = 0;
                elementMask = 0;
            }
        }
        else
        {
            vertexData = 0;
            vertexSize = 0;
            elementMask = 0;
        }
    }

    if (rawIndexData_)
    {
        indexData = rawIndexData_;
        indexSize = rawIndexSize_;
    }
    else
    {
        if (indexBuffer_)
        {
            indexData = indexBuffer_->GetShadowDataShared();
            if (indexData)
                indexSize = indexBuffer_->GetIndexSize();
            else
                indexSize = 0;
        }
        else
        {
            indexData = 0;
            indexSize = 0;
        }
    }
}

float Geometry::GetHitDistance(const Ray& ray, Vector3* outNormal) const
{
    const unsigned char* vertexData;
    const unsigned char* indexData;
    unsigned vertexSize;
    unsigned indexSize;
    unsigned elementMask;

    GetRawData(vertexData, vertexSize, indexData, indexSize, elementMask);

    if (vertexData && indexData)
        return ray.HitDistance(vertexData, vertexSize, indexData, indexSize, indexStart_, indexCount_, outNormal);
    else if (vertexData)
        return ray.HitDistance(vertexData, vertexSize, vertexStart_, vertexCount_, outNormal);
    else
        return M_INFINITY;
}

bool Geometry::IsInside(const Ray& ray) const
{
    const unsigned char* vertexData;
    const unsigned char* indexData;
    unsigned vertexSize;
    unsigned indexSize;
    unsigned elementMask;

    GetRawData(vertexData, vertexSize, indexData, indexSize, elementMask);

    if (vertexData && indexData)
        return ray.InsideGeometry(vertexData, vertexSize, indexData, indexSize, indexStart_, indexCount_);
    else if (vertexData)
        return ray.InsideGeometry(vertexData, vertexSize, vertexStart_, vertexCount_);
    else
        return false;
}

void Geometry::GetPositionBufferIndex()
{
    for (unsigned i = 0; i < vertexBuffers_.Size(); ++i)
    {
        if (vertexBuffers_[i] && vertexBuffers_[i]->GetElementMask() & MASK_POSITION)
        {
            positionBufferIndex_ = i;
            return;
        }
    }

    // No vertex buffer with positions
    positionBufferIndex_ = M_MAX_UNSIGNED;
}

}
<commit_msg>Restored previous Geometry::GetRawData() function (though it leads to duplicated code) to prevent unnecessary copying of shared array pointers.<commit_after>//
// Copyright (c) 2008-2013 the Urho3D project.
//
// 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.
//

#include "Precompiled.h"
#include "Geometry.h"
#include "Graphics.h"
#include "IndexBuffer.h"
#include "Log.h"
#include "Ray.h"
#include "VertexBuffer.h"

#include "DebugNew.h"

namespace Urho3D
{

Geometry::Geometry(Context* context) :
    Object(context),
    primitiveType_(TRIANGLE_LIST),
    indexStart_(0),
    indexCount_(0),
    vertexStart_(0),
    vertexCount_(0),
    positionBufferIndex_(M_MAX_UNSIGNED),
    rawVertexSize_(0),
    rawElementMask_(0),
    rawIndexSize_(0),
    lodDistance_(0.0f)
{
    SetNumVertexBuffers(1);
}

Geometry::~Geometry()
{
}

bool Geometry::SetNumVertexBuffers(unsigned num)
{
    if (num >= MAX_VERTEX_STREAMS)
    {
        LOGERROR("Too many vertex streams");
        return false;
    }

    unsigned oldSize = vertexBuffers_.Size();
    vertexBuffers_.Resize(num);
    elementMasks_.Resize(num);

    for (unsigned i = oldSize; i < num; ++i)
        elementMasks_[i] = MASK_NONE;

    GetPositionBufferIndex();
    return true;
}

bool Geometry::SetVertexBuffer(unsigned index, VertexBuffer* buffer, unsigned elementMask)
{
    if (index >= vertexBuffers_.Size())
    {
        LOGERROR("Stream index out of bounds");
        return false;
    }

    vertexBuffers_[index] = buffer;

    if (buffer)
    {
        if (elementMask == MASK_DEFAULT)
            elementMasks_[index] = buffer->GetElementMask();
        else
            elementMasks_[index] = elementMask;
    }

    GetPositionBufferIndex();
    return true;
}

void Geometry::SetIndexBuffer(IndexBuffer* buffer)
{
    indexBuffer_ = buffer;
}

bool Geometry::SetDrawRange(PrimitiveType type, unsigned indexStart, unsigned indexCount, bool getUsedVertexRange)
{
    if (!indexBuffer_ && !rawIndexData_)
    {
        LOGERROR("Null index buffer and no raw index data, can not define indexed draw range");
        return false;
    }
    if (indexBuffer_ && indexStart + indexCount > indexBuffer_->GetIndexCount())
    {
        LOGERROR("Illegal draw range " + String(indexStart) + " to " + String(indexStart + indexCount - 1) + ", index buffer has " +
            String(indexBuffer_->GetIndexCount()) + " indices");
        return false;
    }

    primitiveType_ = type;
    indexStart_ = indexStart;
    indexCount_ = indexCount;

    // Get min.vertex index and num of vertices from index buffer. If it fails, use full range as fallback
    if (indexCount)
    {
        vertexStart_ = 0;
        vertexCount_ = vertexBuffers_[0] ? vertexBuffers_[0]->GetVertexCount() : 0;

        if (getUsedVertexRange && indexBuffer_)
            indexBuffer_->GetUsedVertexRange(indexStart_, indexCount_, vertexStart_, vertexCount_);
    }
    else
    {
        vertexStart_ = 0;
        vertexCount_ = 0;
    }

    return true;
}

bool Geometry::SetDrawRange(PrimitiveType type, unsigned indexStart, unsigned indexCount, unsigned minVertex, unsigned vertexCount)
{
    if (indexBuffer_)
    {
        if (indexStart + indexCount > indexBuffer_->GetIndexCount())
        {
            LOGERROR("Illegal draw range " + String(indexStart) + " to " + String(indexStart + indexCount - 1) +
                ", index buffer has " + String(indexBuffer_->GetIndexCount()) + " indices");
            return false;
        }
    }
    else if (!rawIndexData_)
    {
        indexStart = 0;
        indexCount = 0;
    }

    primitiveType_ = type;
    indexStart_ = indexStart;
    indexCount_ = indexCount;
    vertexStart_ = minVertex;
    vertexCount_ = vertexCount;

    return true;
}

void Geometry::SetLodDistance(float distance)
{
    if (distance < 0.0f)
        distance = 0.0f;

    lodDistance_ = distance;
}

void Geometry::SetRawVertexData(SharedArrayPtr<unsigned char> data, unsigned vertexSize, unsigned elementMask)
{
    rawVertexData_ = data;
    rawVertexSize_ = vertexSize;
    rawElementMask_ = elementMask;
}

void Geometry::SetRawIndexData(SharedArrayPtr<unsigned char> data, unsigned indexSize)
{
    rawIndexData_ = data;
    rawIndexSize_ = indexSize;
}

void Geometry::Draw(Graphics* graphics)
{
    if (indexBuffer_ && indexCount_ > 0)
    {
        graphics->SetIndexBuffer(indexBuffer_);
        graphics->SetVertexBuffers(vertexBuffers_, elementMasks_);
        graphics->Draw(primitiveType_, indexStart_, indexCount_, vertexStart_, vertexCount_);
    }
    else if (vertexCount_ > 0)
    {
        graphics->SetVertexBuffers(vertexBuffers_, elementMasks_);
        graphics->Draw(primitiveType_, vertexStart_, vertexCount_);
    }
}

VertexBuffer* Geometry::GetVertexBuffer(unsigned index) const
{
    return index < vertexBuffers_.Size() ? vertexBuffers_[index] : (VertexBuffer*)0;
}

unsigned Geometry::GetVertexElementMask(unsigned index) const
{
    return index < elementMasks_.Size() ? elementMasks_[index] : 0;
}

unsigned short Geometry::GetBufferHash() const
{
    unsigned short hash = 0;

    for (unsigned i = 0; i < vertexBuffers_.Size(); ++i)
    {
        VertexBuffer* vBuf = vertexBuffers_[i];
        hash += *((unsigned short*)&vBuf);
    }

    IndexBuffer* iBuf = indexBuffer_;
    hash += *((unsigned short*)&iBuf);

    return hash;
}

void Geometry::GetRawData(const unsigned char*& vertexData, unsigned& vertexSize, const unsigned char*& indexData,
    unsigned& indexSize, unsigned& elementMask) const
{
    if (rawVertexData_)
    {
        vertexData = rawVertexData_;
        vertexSize = rawVertexSize_;
        elementMask = rawElementMask_;
    }
    else
    {
        if (positionBufferIndex_ < vertexBuffers_.Size() && vertexBuffers_[positionBufferIndex_])
        {
            vertexData = vertexBuffers_[positionBufferIndex_]->GetShadowData();
            if (vertexData)
            {
                vertexSize = vertexBuffers_[positionBufferIndex_]->GetVertexSize();
                elementMask = vertexBuffers_[positionBufferIndex_]->GetElementMask();
            }
            else
            {
                vertexSize = 0;
                elementMask = 0;
            }
        }
        else
        {
            vertexData = 0;
            vertexSize = 0;
            elementMask = 0;
        }
    }

    if (rawIndexData_)
    {
        indexData = rawIndexData_;
        indexSize = rawIndexSize_;
    }
    else
    {
        if (indexBuffer_)
        {
            indexData = indexBuffer_->GetShadowData();
            if (indexData)
                indexSize = indexBuffer_->GetIndexSize();
            else
                indexSize = 0;
        }
        else
        {
            indexData = 0;
            indexSize = 0;
        }
    }
}

void Geometry::GetRawDataShared(SharedArrayPtr<unsigned char>& vertexData, unsigned& vertexSize,
    SharedArrayPtr<unsigned char>& indexData, unsigned& indexSize, unsigned& elementMask) const
{
    if (rawVertexData_)
    {
        vertexData = rawVertexData_;
        vertexSize = rawVertexSize_;
        elementMask = rawElementMask_;
    }
    else
    {
        if (positionBufferIndex_ < vertexBuffers_.Size() && vertexBuffers_[positionBufferIndex_])
        {
            vertexData = vertexBuffers_[positionBufferIndex_]->GetShadowDataShared();
            if (vertexData)
            {
                vertexSize = vertexBuffers_[positionBufferIndex_]->GetVertexSize();
                elementMask = vertexBuffers_[positionBufferIndex_]->GetElementMask();
            }
            else
            {
                vertexSize = 0;
                elementMask = 0;
            }
        }
        else
        {
            vertexData = 0;
            vertexSize = 0;
            elementMask = 0;
        }
    }

    if (rawIndexData_)
    {
        indexData = rawIndexData_;
        indexSize = rawIndexSize_;
    }
    else
    {
        if (indexBuffer_)
        {
            indexData = indexBuffer_->GetShadowDataShared();
            if (indexData)
                indexSize = indexBuffer_->GetIndexSize();
            else
                indexSize = 0;
        }
        else
        {
            indexData = 0;
            indexSize = 0;
        }
    }
}

float Geometry::GetHitDistance(const Ray& ray, Vector3* outNormal) const
{
    const unsigned char* vertexData;
    const unsigned char* indexData;
    unsigned vertexSize;
    unsigned indexSize;
    unsigned elementMask;

    GetRawData(vertexData, vertexSize, indexData, indexSize, elementMask);

    if (vertexData && indexData)
        return ray.HitDistance(vertexData, vertexSize, indexData, indexSize, indexStart_, indexCount_, outNormal);
    else if (vertexData)
        return ray.HitDistance(vertexData, vertexSize, vertexStart_, vertexCount_, outNormal);
    else
        return M_INFINITY;
}

bool Geometry::IsInside(const Ray& ray) const
{
    const unsigned char* vertexData;
    const unsigned char* indexData;
    unsigned vertexSize;
    unsigned indexSize;
    unsigned elementMask;

    GetRawData(vertexData, vertexSize, indexData, indexSize, elementMask);

    if (vertexData && indexData)
        return ray.InsideGeometry(vertexData, vertexSize, indexData, indexSize, indexStart_, indexCount_);
    else if (vertexData)
        return ray.InsideGeometry(vertexData, vertexSize, vertexStart_, vertexCount_);
    else
        return false;
}

void Geometry::GetPositionBufferIndex()
{
    for (unsigned i = 0; i < vertexBuffers_.Size(); ++i)
    {
        if (vertexBuffers_[i] && vertexBuffers_[i]->GetElementMask() & MASK_POSITION)
        {
            positionBufferIndex_ = i;
            return;
        }
    }

    // No vertex buffer with positions
    positionBufferIndex_ = M_MAX_UNSIGNED;
}

}
<|endoftext|>


<commit_before>#include "openmc/bank.h"

#include "openmc/capi.h"
#include "openmc/error.h"

#include <cstdint>

// Explicit template instantiation definition
template class std::vector<openmc::Particle::Bank>;

namespace openmc {

//==============================================================================
// Global variables
//==============================================================================

namespace simulation {

std::vector<Particle::Bank> source_bank;
std::vector<Particle::Bank> fission_bank;

Particle::Bank* shared_fission_bank;
int shared_fission_bank_length {0};
int shared_fission_bank_max;

} // namespace simulation

//==============================================================================
// Non-member functions
//==============================================================================

void free_memory_bank()
{
  simulation::source_bank.clear();
  simulation::fission_bank.clear();
	delete[] simulation::shared_fission_bank;
  simulation::shared_fission_bank_length = 0;
}

void init_shared_fission_bank(int max)
{
  simulation::shared_fission_bank_max = max;
  simulation::shared_fission_bank = new Particle::Bank[max];
  simulation::shared_fission_bank_length = 0;
}

//==============================================================================
// C API
//==============================================================================

extern "C" int openmc_source_bank(void** ptr, int64_t* n)
{
  if (simulation::source_bank.size() == 0) {
    set_errmsg("Source bank has not been allocated.");
    return OPENMC_E_ALLOCATE;
  } else {
    *ptr = simulation::source_bank.data();
    *n = simulation::source_bank.size();
    return 0;
  }
}

extern "C" int openmc_fission_bank(void** ptr, int64_t* n)
{
  if (simulation::fission_bank.size() == 0) {
    set_errmsg("Fission bank has not been allocated.");
    return OPENMC_E_ALLOCATE;
  } else {
    *ptr = simulation::fission_bank.data();
    *n = simulation::fission_bank.size();
    return 0;
  }
}

} // namespace openmc
<commit_msg>In some unit tests, OpenMC finalize is called twice in a row without re-initializing the whole simulation. This caused the shared fission bank to be freed twice. Fixed now to check if it is a null pointer, and only free if null. Also initializes this value to null and sets it to null after freeing.<commit_after>#include "openmc/bank.h"

#include "openmc/capi.h"
#include "openmc/error.h"

#include <cstdint>

// Explicit template instantiation definition
template class std::vector<openmc::Particle::Bank>;

namespace openmc {

//==============================================================================
// Global variables
//==============================================================================

namespace simulation {

std::vector<Particle::Bank> source_bank;
std::vector<Particle::Bank> fission_bank;

Particle::Bank* shared_fission_bank {nullptr};
int shared_fission_bank_length {0};
int shared_fission_bank_max;

} // namespace simulation

//==============================================================================
// Non-member functions
//==============================================================================

void free_memory_bank()
{
  simulation::source_bank.clear();
  simulation::fission_bank.clear();
  if( simulation::shared_fission_bank != nullptr )
	  delete[] simulation::shared_fission_bank;
  simulation::shared_fission_bank = nullptr;
  simulation::shared_fission_bank_length = 0;
}

void init_shared_fission_bank(int max)
{
  simulation::shared_fission_bank_max = max;
  simulation::shared_fission_bank = new Particle::Bank[max];
  simulation::shared_fission_bank_length = 0;
}

//==============================================================================
// C API
//==============================================================================

extern "C" int openmc_source_bank(void** ptr, int64_t* n)
{
  if (simulation::source_bank.size() == 0) {
    set_errmsg("Source bank has not been allocated.");
    return OPENMC_E_ALLOCATE;
  } else {
    *ptr = simulation::source_bank.data();
    *n = simulation::source_bank.size();
    return 0;
  }
}

extern "C" int openmc_fission_bank(void** ptr, int64_t* n)
{
  if (simulation::fission_bank.size() == 0) {
    set_errmsg("Fission bank has not been allocated.");
    return OPENMC_E_ALLOCATE;
  } else {
    *ptr = simulation::fission_bank.data();
    *n = simulation::fission_bank.size();
    return 0;
  }
}

} // namespace openmc
<|endoftext|>