<commit_before>#include <Control/Setting.hh>
#include <Control/ControlData.hh>

#include <iostream>
#include <QCoreApplication>
#include <QDir>
#include <QFont>
#include <QFile>
#include <QFileInfo>
#include <QStandardPaths>
#include <QTextStream>

Setting::Setting(){
  setDefaults();

  if (!configExists()) newConfigFile();

  setDefaults();

  overrideConfig();
}

void Setting::setDefaults(){
  setTessdataDefault();
  setTesseractDefaults();
  setInterfaceDefaults();
  setResourceDefaults();
}

bool Setting::configExists(){
  QString configFileName;
  QFileInfo configFile;

  configFileName = getConfigFile();

  configFile.setFile(configFileName);

  if(configFile.exists() && configFile.isFile()){
    return true;
  } else {
    return false;
  }
}

void Setting::newConfigFile(){
  QString configFolder, configFileName;
  QFile configFile;

  configFolder = getConfigDir();
  configFileName = getConfigFile();

  configFile.setFileName(configFileName);

  if(!QDir(configFolder).exists()){
    QDir().mkdir(configFolder);
  }

  if (configFile.open(QIODevice::WriteOnly)){
    QTextStream out(&configFile);

    out << getCurrentState();

    configFile.close();
  }

}

QString Setting::getConfigDir(){
  QString configFolder;
  configFolder = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation)[0];
  if(configFolder.indexOf(qApp->applicationName()) <= -1){
    configFolder += "/" + qApp->applicationName();
  }

  return configFolder;
}

QString Setting::getConfigFile(){
  return getConfigDir() + "/config";
}

void Setting::editConfigFile(QString label, QString value){
  QString configFileName, configDump;
  QFile configFile;

  configFileName = getConfigFile();

  configFile.setFileName(configFileName);

  if (configFile.open(QIODevice::ReadOnly)){
    QTextStream in(&configFile);
    while (!in.atEnd()){
      QString line = in.readLine();
      configDump += modifyArgument(label, value, line) + "\n";
    }
  }
  configFile.close();

  if (configFile.open(QIODevice::WriteOnly)){
    QTextStream out(&configFile);

    out << configDump;

    configFile.close();
  }
}

void Setting::overrideConfig(){
  //First we'd just implement reading everything line by line:
  QString configFileName;
  QFile configFile;

  configFileName = getConfigFile();

  configFile.setFileName(configFileName);

  if (configFile.open(QIODevice::ReadOnly)){
    QTextStream in(&configFile);
    while (!in.atEnd()){
      QString line = in.readLine();
      interpretConfig(line);
    }
  }
  configFile.close();
}

//Sorry for unusual arg name. Legacy var name I <3
void Setting::interpretConfig(QString textToPrint){
  QString cmmd, argument;
  int dlimPos;

  dlimPos = textToPrint.indexOf(":");
  cmmd = textToPrint.left(dlimPos).trimmed();
  argument = textToPrint.mid(dlimPos + 1).trimmed();

  if(cmmd == "tesseractPath"){
    setTesseractPath(argument);
  }else if(cmmd == "tessdataPath"){
    setTessdataPath(argument);
  }else if(cmmd == "appName"){
    setAppName(argument);
  }else if(cmmd == "interfaceLanguage"){
    setInterfaceLanguage(argument);
  }else if(cmmd == "fontFamily"){
    setFontFamily(argument);
  }else if(cmmd == "windowState"){
    setWindowState(argument.toInt());
  }else if(cmmd == "fontSize"){
    setFontSize(argument.toDouble());
  }else if(cmmd == "windowXPos"){
    setWindowXPos(argument.toInt());
  }else if(cmmd == "windowYPos"){
    setWindowYPos(argument.toInt());
  }else if(cmmd == "windowWidth"){
    setWindowWidth(argument.toInt());
  }else if(cmmd == "windowHeight"){
    setWindowHeight(argument.toInt());
  }else if(cmmd == "decipherDataPath"){
    setDecipherDataPath(argument);
  }else if(cmmd == "iconDir"){
    setIconDir(argument);
  }
}

QString Setting::modifyArgument(QString reqCmmd, QString reqArg, QString textToPrint){
  QString cmmd, argument;
  int dlimPos;

  dlimPos = textToPrint.indexOf(":");
  cmmd = textToPrint.left(dlimPos).trimmed();
  argument = textToPrint.mid(dlimPos + 1).trimmed();

  if(reqCmmd == cmmd){
    return reqCmmd + ": " + reqArg;
  } else {
    return textToPrint;
  }
}

QString Setting::getCurrentState(){
  QString state;

  state += "tesseractPath: "         + getTesseractPath();
  state += "\ntessdataPath: "        + getTessdataPath();
  state += "\nappName: "             + getAppName();
  state += "\ninterfaceLanguage: "   + getInterfaceLanguage();
  state += "\nfontFamily: "          + getFontFamily();
  state += "\nfontSize: "            + QString::number(getFontSize());
  state += "\nwindowState: "         + QString::number(getWindowState());
  state += "\nwindowXPos: "          + QString::number(getWindowXPos());
  state += "\nwindowYPos: "          + QString::number(getWindowYPos());
  state += "\nwindowWidth: "         + QString::number(getWindowWidth());
  state += "\nwindowHeight: "        + QString::number(getWindowHeight());
  state += "\ndecipherDataPath: "    + getDecipherDataPath();
  state += "\niconDir: "             + getIconDir();

  return state;
}

QString Setting::getDefaultState(){
  setDefaults();

  return getCurrentState();
}

void Setting::setInterfaceDefaults(){
  appName = "Decipher Text";
  interfaceLanguage = "en_US";
  windowState = false;
  windowXPos = 1;
  windowYPos = 1;
  windowWidth = 1280;
  windowHeight = 720;
  fontFamily = "NaN";
  fontSize = 16.0;
}

void Setting::setResourceDefaults(){
  binRoot = QCoreApplication::applicationDirPath();
  decipherDataPath = binRoot + "/../share/decipher_text";
  iconDir = decipherDataPath + "/icons";
}

void Setting::setTessdataDefault(){
  QString path, winPath;
  winPath = QCoreApplication::applicationDirPath() + "/../share/decipher_text/tessdata";

  if (QDir("/usr/share/tessdata").exists()){
    path = "/usr/share";
  } else if(QDir("/usr/local/share/tessdata").exists()){
    path = "/usr/local/share";
  } else {
    path = "";
  }

  #ifdef _WIN32
    if (QDir(winPath).exists()){
      path = winPath + "/..";
    } else if (QDir("C:\\Tesseract-OCR\\tessdata").exists()){
      path = "C:\\Tesseract-OCR";
    } else if(QDir("C:\\Tesseract\\tessdata").exists()){
      path = "C:\\Tesseract";
    } else if(QDir("C:\\Program Files\\Tesseract-OCR\\tessdata").exists()){
      path = "C:\\Program Files\\Tesseract-OCR";
    } else if(QDir("C:\\Program Files (x86)\\Tesseract-OCR\\tessdata").exists()){
      path = "C:\\Program Files (x86)\\Tesseract-OCR";
    } else if(QDir("C:\\Program Files\\Tesseract\\tessdata").exists()){
      path = "C:\\Program Files\\Tesseract";
    } else if(QDir("C:\\Program Files (x86)\\Tesseract\\tessdata").exists()){
      path = "C:\\Program Files (x86)\\Tesseract";
    } else {
      path = "";
    }
  #endif

  setTessdataPath(path);
}

void Setting::setTesseractDefaults(){
  QFileInfo location1;
  QFileInfo location2;
  QString path;

  #ifdef _WIN32
  location1.setFile("C:\\Program Files (x86)\\Tesseract-OCR\\tesseract.exe");
  location2.setFile("C:\\Tesseract-OCR\\tesseract.exe");
  #else
  location1.setFile("/usr/bin/tesseract");
  location2.setFile("/usr/local/bin/tesseract");
  #endif

  if(location1.exists() && location1.isFile()){
    path = location1.absoluteFilePath();
  } else if(location2.exists() && location2.isFile()) {
    path = location1.absoluteFilePath();
  } else {
    path = "";
  }

  setTesseractPath(path);
}

//Getters
QString Setting::getTesseractPath(){
  return tesseractPath;
}

QString Setting::getTessdataPath(){
  return tessdataPath;
}

QString Setting::getAppName(){
  return appName;
}

QString Setting::getInterfaceLanguage(){
  return interfaceLanguage;
}

bool Setting::getWindowState(){
  return windowState;
}

int Setting::getWindowXPos(){
  return windowXPos;
}

int Setting::getWindowYPos(){
  return windowYPos;
}

int Setting::getWindowWidth(){
  return windowWidth;
}

int Setting::getWindowHeight(){
  return windowHeight;
}

QString Setting::getFontFamily(){
  return fontFamily;
}

double Setting::getFontSize(){
  return fontSize;
}

QString Setting::getDecipherDataPath(){
  return decipherDataPath;
}

QString Setting::getIconDir(){
  return iconDir;
}

//Setters
void Setting::setTesseractPath(QString path){
  tesseractPath = path;
}

void Setting::setTessdataPath(QString path){
  tessdataPath = path;
}

void Setting::setAppName(QString name){
  appName = name;
}

void Setting::setInterfaceLanguage(QString lang){
  interfaceLanguage = lang;
}

void Setting::setWindowState(bool state){
  windowState = state;
}

void Setting::setWindowXPos(int pos){
  windowXPos = pos;
}

void Setting::setWindowYPos(int pos){
  windowYPos = pos;
}

void Setting::setWindowWidth(int width){
  windowWidth = width;
}

void Setting::setWindowHeight(int height){
  windowHeight = height;
}

void Setting::setFontFamily(QString family){
  fontFamily = family;
}

void Setting::setFontSize(double sz){
  fontSize = sz;
}

void Setting::setDecipherDataPath(QString path){
  decipherDataPath = path;
}

void Setting::setIconDir(QString path){
  iconDir = path;
}
<commit_msg>Added distribution specific tessdata inclusion for all platforms.<commit_after>#include <Control/Setting.hh>
#include <Control/ControlData.hh>

#include <iostream>
#include <QCoreApplication>
#include <QDir>
#include <QFont>
#include <QFile>
#include <QFileInfo>
#include <QStandardPaths>
#include <QTextStream>

Setting::Setting(){
  setDefaults();

  if (!configExists()) newConfigFile();

  setDefaults();

  overrideConfig();
}

void Setting::setDefaults(){
  setTessdataDefault();
  setTesseractDefaults();
  setInterfaceDefaults();
  setResourceDefaults();
}

bool Setting::configExists(){
  QString configFileName;
  QFileInfo configFile;

  configFileName = getConfigFile();

  configFile.setFile(configFileName);

  if(configFile.exists() && configFile.isFile()){
    return true;
  } else {
    return false;
  }
}

void Setting::newConfigFile(){
  QString configFolder, configFileName;
  QFile configFile;

  configFolder = getConfigDir();
  configFileName = getConfigFile();

  configFile.setFileName(configFileName);

  if(!QDir(configFolder).exists()){
    QDir().mkdir(configFolder);
  }

  if (configFile.open(QIODevice::WriteOnly)){
    QTextStream out(&configFile);

    out << getCurrentState();

    configFile.close();
  }

}

QString Setting::getConfigDir(){
  QString configFolder;
  configFolder = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation)[0];
  if(configFolder.indexOf(qApp->applicationName()) <= -1){
    configFolder += "/" + qApp->applicationName();
  }

  return configFolder;
}

QString Setting::getConfigFile(){
  return getConfigDir() + "/config";
}

void Setting::editConfigFile(QString label, QString value){
  QString configFileName, configDump;
  QFile configFile;

  configFileName = getConfigFile();

  configFile.setFileName(configFileName);

  if (configFile.open(QIODevice::ReadOnly)){
    QTextStream in(&configFile);
    while (!in.atEnd()){
      QString line = in.readLine();
      configDump += modifyArgument(label, value, line) + "\n";
    }
  }
  configFile.close();

  if (configFile.open(QIODevice::WriteOnly)){
    QTextStream out(&configFile);

    out << configDump;

    configFile.close();
  }
}

void Setting::overrideConfig(){
  //First we'd just implement reading everything line by line:
  QString configFileName;
  QFile configFile;

  configFileName = getConfigFile();

  configFile.setFileName(configFileName);

  if (configFile.open(QIODevice::ReadOnly)){
    QTextStream in(&configFile);
    while (!in.atEnd()){
      QString line = in.readLine();
      interpretConfig(line);
    }
  }
  configFile.close();
}

//Sorry for unusual arg name. Legacy var name I <3
void Setting::interpretConfig(QString textToPrint){
  QString cmmd, argument;
  int dlimPos;

  dlimPos = textToPrint.indexOf(":");
  cmmd = textToPrint.left(dlimPos).trimmed();
  argument = textToPrint.mid(dlimPos + 1).trimmed();

  if(cmmd == "tesseractPath"){
    setTesseractPath(argument);
  }else if(cmmd == "tessdataPath"){
    setTessdataPath(argument);
  }else if(cmmd == "appName"){
    setAppName(argument);
  }else if(cmmd == "interfaceLanguage"){
    setInterfaceLanguage(argument);
  }else if(cmmd == "fontFamily"){
    setFontFamily(argument);
  }else if(cmmd == "windowState"){
    setWindowState(argument.toInt());
  }else if(cmmd == "fontSize"){
    setFontSize(argument.toDouble());
  }else if(cmmd == "windowXPos"){
    setWindowXPos(argument.toInt());
  }else if(cmmd == "windowYPos"){
    setWindowYPos(argument.toInt());
  }else if(cmmd == "windowWidth"){
    setWindowWidth(argument.toInt());
  }else if(cmmd == "windowHeight"){
    setWindowHeight(argument.toInt());
  }else if(cmmd == "decipherDataPath"){
    setDecipherDataPath(argument);
  }else if(cmmd == "iconDir"){
    setIconDir(argument);
  }
}

QString Setting::modifyArgument(QString reqCmmd, QString reqArg, QString textToPrint){
  QString cmmd, argument;
  int dlimPos;

  dlimPos = textToPrint.indexOf(":");
  cmmd = textToPrint.left(dlimPos).trimmed();
  argument = textToPrint.mid(dlimPos + 1).trimmed();

  if(reqCmmd == cmmd){
    return reqCmmd + ": " + reqArg;
  } else {
    return textToPrint;
  }
}

QString Setting::getCurrentState(){
  QString state;

  state += "tesseractPath: "         + getTesseractPath();
  state += "\ntessdataPath: "        + getTessdataPath();
  state += "\nappName: "             + getAppName();
  state += "\ninterfaceLanguage: "   + getInterfaceLanguage();
  state += "\nfontFamily: "          + getFontFamily();
  state += "\nfontSize: "            + QString::number(getFontSize());
  state += "\nwindowState: "         + QString::number(getWindowState());
  state += "\nwindowXPos: "          + QString::number(getWindowXPos());
  state += "\nwindowYPos: "          + QString::number(getWindowYPos());
  state += "\nwindowWidth: "         + QString::number(getWindowWidth());
  state += "\nwindowHeight: "        + QString::number(getWindowHeight());
  state += "\ndecipherDataPath: "    + getDecipherDataPath();
  state += "\niconDir: "             + getIconDir();

  return state;
}

QString Setting::getDefaultState(){
  setDefaults();

  return getCurrentState();
}

void Setting::setInterfaceDefaults(){
  appName = "Decipher Text";
  interfaceLanguage = "en_US";
  windowState = false;
  windowXPos = 1;
  windowYPos = 1;
  windowWidth = 1280;
  windowHeight = 720;
  fontFamily = "NaN";
  fontSize = 16.0;
}

void Setting::setResourceDefaults(){
  binRoot = QCoreApplication::applicationDirPath();
  decipherDataPath = binRoot + "/../share/decipher_text";
  iconDir = decipherDataPath + "/icons";
}

void Setting::setTessdataDefault(){
  QString path, distPath;
  distPath = QCoreApplication::applicationDirPath() + "/../share/decipher_text/tessdata";

  if (QDir(distPath).exists()){
    path = distPath + "/..";
  } else if (QDir("/usr/share/tessdata").exists()){
    path = "/usr/share";
  } else if(QDir("/usr/local/share/tessdata").exists()){
    path = "/usr/local/share";
  } else {
    path = "";
  }

  #ifdef _WIN32
    if (QDir(distPath).exists()){
      path = distPath + "/..";
    } else if (QDir("C:\\Tesseract-OCR\\tessdata").exists()){
      path = "C:\\Tesseract-OCR";
    } else if(QDir("C:\\Tesseract\\tessdata").exists()){
      path = "C:\\Tesseract";
    } else if(QDir("C:\\Program Files\\Tesseract-OCR\\tessdata").exists()){
      path = "C:\\Program Files\\Tesseract-OCR";
    } else if(QDir("C:\\Program Files (x86)\\Tesseract-OCR\\tessdata").exists()){
      path = "C:\\Program Files (x86)\\Tesseract-OCR";
    } else if(QDir("C:\\Program Files\\Tesseract\\tessdata").exists()){
      path = "C:\\Program Files\\Tesseract";
    } else if(QDir("C:\\Program Files (x86)\\Tesseract\\tessdata").exists()){
      path = "C:\\Program Files (x86)\\Tesseract";
    } else {
      path = "";
    }
  #endif

  setTessdataPath(path);
}

void Setting::setTesseractDefaults(){
  QFileInfo location1;
  QFileInfo location2;
  QString path;

  #ifdef _WIN32
  location1.setFile("C:\\Program Files (x86)\\Tesseract-OCR\\tesseract.exe");
  location2.setFile("C:\\Tesseract-OCR\\tesseract.exe");
  #else
  location1.setFile("/usr/bin/tesseract");
  location2.setFile("/usr/local/bin/tesseract");
  #endif

  if(location1.exists() && location1.isFile()){
    path = location1.absoluteFilePath();
  } else if(location2.exists() && location2.isFile()) {
    path = location1.absoluteFilePath();
  } else {
    path = "";
  }

  setTesseractPath(path);
}

//Getters
QString Setting::getTesseractPath(){
  return tesseractPath;
}

QString Setting::getTessdataPath(){
  return tessdataPath;
}

QString Setting::getAppName(){
  return appName;
}

QString Setting::getInterfaceLanguage(){
  return interfaceLanguage;
}

bool Setting::getWindowState(){
  return windowState;
}

int Setting::getWindowXPos(){
  return windowXPos;
}

int Setting::getWindowYPos(){
  return windowYPos;
}

int Setting::getWindowWidth(){
  return windowWidth;
}

int Setting::getWindowHeight(){
  return windowHeight;
}

QString Setting::getFontFamily(){
  return fontFamily;
}

double Setting::getFontSize(){
  return fontSize;
}

QString Setting::getDecipherDataPath(){
  return decipherDataPath;
}

QString Setting::getIconDir(){
  return iconDir;
}

//Setters
void Setting::setTesseractPath(QString path){
  tesseractPath = path;
}

void Setting::setTessdataPath(QString path){
  tessdataPath = path;
}

void Setting::setAppName(QString name){
  appName = name;
}

void Setting::setInterfaceLanguage(QString lang){
  interfaceLanguage = lang;
}

void Setting::setWindowState(bool state){
  windowState = state;
}

void Setting::setWindowXPos(int pos){
  windowXPos = pos;
}

void Setting::setWindowYPos(int pos){
  windowYPos = pos;
}

void Setting::setWindowWidth(int width){
  windowWidth = width;
}

void Setting::setWindowHeight(int height){
  windowHeight = height;
}

void Setting::setFontFamily(QString family){
  fontFamily = family;
}

void Setting::setFontSize(double sz){
  fontSize = sz;
}

void Setting::setDecipherDataPath(QString path){
  decipherDataPath = path;
}

void Setting::setIconDir(QString path){
  iconDir = path;
}
<|endoftext|>


<commit_before>/*
 * ConcreteGraph.hpp
 *
 *  Created on: Nov 18, 2014
 *      Author: Pimenta
 */

#ifndef CONCRETEGRAPH_HPP_
#define CONCRETEGRAPH_HPP_

#include <map>

#include "Graph.hpp"

namespace graph {

template <typename Weight, Weight INFINITE, typename Vertex = int, Vertex nullvertex = 0, typename Size = int>
class ArrayNeighbourhood : public Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size> {
  public:
    class Iterator : public Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator {
      private:
        Edge<Weight, INFINITE, Vertex, nullvertex>* ptr;
      public:
        Iterator(Edge<Weight, INFINITE, Vertex, nullvertex>* ptr);
        bool operator!=(const typename Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator& other) const;
        Edge<Weight, INFINITE, Vertex, nullvertex> operator*();
        typename Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator& operator++();
    };
  private:
    Size size_;
    Edge<Weight, INFINITE, Vertex, nullvertex>* data;
    Size degree_;
  public:
    ArrayNeighbourhood();
    ~ArrayNeighbourhood();
    typename Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator begin() const;
    typename Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator end() const;
    Edge<Weight, INFINITE, Vertex, nullvertex> operator[](Vertex v) const;
    Size degree() const;
    void resize(Size new_size);
    void edge(Vertex v, Vertex w);
};

template <typename Weight, Weight INFINITE, typename Vertex = int, Vertex nullvertex = 0, typename Size = int>
class MapNeighbourhood : public Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size> {
  public:
    class Iterator : public Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator {
      private:
        typename std::map<Vertex, Edge<Weight, INFINITE, Vertex, nullvertex>>::const_iterator mapit;
      public:
        Iterator(typename std::map<Vertex, Edge<Weight, INFINITE, Vertex, nullvertex>>::const_iterator mapit);
        bool operator!=(const typename Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator& other) const;
        Edge<Weight, INFINITE, Vertex, nullvertex> operator*();
        typename Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator& operator++();
    };
  private:
    std::map<Vertex, Edge<Weight, INFINITE, Vertex, nullvertex>> data;
  public:
    typename Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator begin() const;
    typename Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator end() const;
    Edge<Weight, INFINITE, Vertex, nullvertex> operator[](Vertex v) const;
    Size degree() const;
    void resize(Size new_size);
    void edge(Vertex v, Vertex w);
};

template <class NeighbourhoodType, typename Weight, Weight INFINITE, typename Vertex = int, Vertex nullvertex = 0, typename Size = int>
class ArrayGraph : public Graph<Weight, INFINITE, Vertex, nullvertex, Size> {
  public:
    class Iterator : public Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator {
      private:
        NeighbourhoodType* ptr;
      public:
        Iterator(NeighbourhoodType* ptr);
        bool operator!=(const typename Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator& other) const;
        Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>& operator*();
        typename Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator& operator++();
    };
  private:
    Size order_;
    NeighbourhoodType* data;
  public:
    ArrayGraph();
    ~ArrayGraph();
    typename Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator begin() const;
    typename Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator end() const;
    Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>& operator[](Vertex v) const;
    Size order() const;
    void order(Size new_order);
};

template <class NeighbourhoodType, typename Weight, Weight INFINITE, typename Vertex = int, Vertex nullvertex = 0, typename Size = int>
class MapGraph : public Graph<Weight, INFINITE, Vertex, nullvertex, Size> {
  public:
    class Iterator : public Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator {
      private:
        typename std::map<Vertex, NeighbourhoodType>::const_iterator mapit;
      public:
        Iterator(typename std::map<Vertex, NeighbourhoodType>::const_iterator mapit);
        bool operator!=(const typename Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator& other) const;
        Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>& operator*();
        typename Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator& operator++();
    };
  private:
    std::map<Vertex, NeighbourhoodType> data;
  public:
    typename Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator begin() const;
    typename Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator end() const;
    Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>& operator[](Vertex v) const;
    Size order() const;
    void order(Size new_order);
};

typedef ArrayNeighbourhood<int, 0x7fffffff>                 IntArrayNeighbourhood;
typedef MapNeighbourhood<int, 0x7fffffff>                   IntMapNeighbourhood;
typedef ArrayGraph<IntArrayNeighbourhood, int, 0x7fffffff>  IntArrayGraphArrayNeighbourHood;
typedef ArrayGraph<IntMapNeighbourhood, int, 0x7fffffff>    IntArrayGraphMapNeighbourHood;
typedef MapGraph<IntArrayNeighbourhood, int, 0x7fffffff>    IntMapGraphArrayNeighbourHood;
typedef MapGraph<IntMapNeighbourhood, int, 0x7fffffff>      IntMapGraphMapNeighbourHood;

} // namespace graph

#include "ConcreteGraph.inl.hpp"

#endif /* CONCRETEGRAPH_HPP_ */
<commit_msg>Removing include<commit_after>/*
 * ConcreteGraph.hpp
 *
 *  Created on: Nov 18, 2014
 *      Author: Pimenta
 */

#ifndef CONCRETEGRAPH_HPP_
#define CONCRETEGRAPH_HPP_

#include "Graph.hpp"

namespace graph {

template <typename Weight, Weight INFINITE, typename Vertex = int, Vertex nullvertex = 0, typename Size = int>
class ArrayNeighbourhood : public Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size> {
  public:
    class Iterator : public Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator {
      private:
        Edge<Weight, INFINITE, Vertex, nullvertex>* ptr;
      public:
        Iterator(Edge<Weight, INFINITE, Vertex, nullvertex>* ptr);
        bool operator!=(const typename Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator& other) const;
        Edge<Weight, INFINITE, Vertex, nullvertex> operator*();
        typename Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator& operator++();
    };
  private:
    Size size_;
    Edge<Weight, INFINITE, Vertex, nullvertex>* data;
    Size degree_;
  public:
    ArrayNeighbourhood();
    ~ArrayNeighbourhood();
    typename Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator begin() const;
    typename Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator end() const;
    Edge<Weight, INFINITE, Vertex, nullvertex> operator[](Vertex v) const;
    Size degree() const;
    void resize(Size new_size);
    void edge(Vertex v, Vertex w);
};

template <typename Weight, Weight INFINITE, typename Vertex = int, Vertex nullvertex = 0, typename Size = int>
class MapNeighbourhood : public Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size> {
  public:
    class Iterator : public Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator {
      private:
        typename std::map<Vertex, Edge<Weight, INFINITE, Vertex, nullvertex>>::const_iterator mapit;
      public:
        Iterator(typename std::map<Vertex, Edge<Weight, INFINITE, Vertex, nullvertex>>::const_iterator mapit);
        bool operator!=(const typename Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator& other) const;
        Edge<Weight, INFINITE, Vertex, nullvertex> operator*();
        typename Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator& operator++();
    };
  private:
    std::map<Vertex, Edge<Weight, INFINITE, Vertex, nullvertex>> data;
  public:
    typename Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator begin() const;
    typename Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator end() const;
    Edge<Weight, INFINITE, Vertex, nullvertex> operator[](Vertex v) const;
    Size degree() const;
    void resize(Size new_size);
    void edge(Vertex v, Vertex w);
};

template <class NeighbourhoodType, typename Weight, Weight INFINITE, typename Vertex = int, Vertex nullvertex = 0, typename Size = int>
class ArrayGraph : public Graph<Weight, INFINITE, Vertex, nullvertex, Size> {
  public:
    class Iterator : public Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator {
      private:
        NeighbourhoodType* ptr;
      public:
        Iterator(NeighbourhoodType* ptr);
        bool operator!=(const typename Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator& other) const;
        Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>& operator*();
        typename Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator& operator++();
    };
  private:
    Size order_;
    NeighbourhoodType* data;
  public:
    ArrayGraph();
    ~ArrayGraph();
    typename Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator begin() const;
    typename Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator end() const;
    Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>& operator[](Vertex v) const;
    Size order() const;
    void order(Size new_order);
};

template <class NeighbourhoodType, typename Weight, Weight INFINITE, typename Vertex = int, Vertex nullvertex = 0, typename Size = int>
class MapGraph : public Graph<Weight, INFINITE, Vertex, nullvertex, Size> {
  public:
    class Iterator : public Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator {
      private:
        typename std::map<Vertex, NeighbourhoodType>::const_iterator mapit;
      public:
        Iterator(typename std::map<Vertex, NeighbourhoodType>::const_iterator mapit);
        bool operator!=(const typename Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator& other) const;
        Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>& operator*();
        typename Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator& operator++();
    };
  private:
    std::map<Vertex, NeighbourhoodType> data;
  public:
    typename Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator begin() const;
    typename Graph<Weight, INFINITE, Vertex, nullvertex, Size>::Iterator end() const;
    Neighbourhood<Weight, INFINITE, Vertex, nullvertex, Size>& operator[](Vertex v) const;
    Size order() const;
    void order(Size new_order);
};

typedef ArrayNeighbourhood<int, 0x7fffffff>                 IntArrayNeighbourhood;
typedef MapNeighbourhood<int, 0x7fffffff>                   IntMapNeighbourhood;
typedef ArrayGraph<IntArrayNeighbourhood, int, 0x7fffffff>  IntArrayGraphArrayNeighbourHood;
typedef ArrayGraph<IntMapNeighbourhood, int, 0x7fffffff>    IntArrayGraphMapNeighbourHood;
typedef MapGraph<IntArrayNeighbourhood, int, 0x7fffffff>    IntMapGraphArrayNeighbourHood;
typedef MapGraph<IntMapNeighbourhood, int, 0x7fffffff>      IntMapGraphMapNeighbourHood;

} // namespace graph

#include "ConcreteGraph.inl.hpp"

#endif /* CONCRETEGRAPH_HPP_ */
<|endoftext|>


<commit_before>#include <common.h>
#include <Configuration.h>

#define RAPIDJSON_ASSERT debug_check_logic
#include <rapidjson/rapidjson.h>
#include <rapidjson/schema.h>
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/istreamwrapper.h>

using namespace Lspl::Text;

namespace Lspl {
namespace Configuration {

///////////////////////////////////////////////////////////////////////////////

static const char* WordSignTypeString( const TWordSignType type )
{
	switch( type ) {
		case WST_None:
			break;
		case WST_Main:
			return "main";
		case WST_Enum:
			return "enum";
		case WST_String:
			return "string";
	}
	return "none";
}

///////////////////////////////////////////////////////////////////////////////

void CWordAttribute::Print( ostream& out ) const
{
	out << ( Consistent ? "consistent " : "" )
		<< WordSignTypeString( Type )
		<< " word sign"
		<< endl;

	if( !Names.IsEmpty() ) {
		out << "  names: ";
		Names.Print( out, ", " );
		out << endl;
	}
	if( !Values.IsEmpty() ) {
		out << "  values: ";
		Values.Print( out, ", " );
		out << endl;
	}
}

///////////////////////////////////////////////////////////////////////////////

bool CWordAttributes::IsEmpty() const
{
	return data.empty();
}

Text::TAttribute CWordAttributes::Size() const
{
	return Cast<Text::TAttribute>( data.size() );
}

const CWordAttribute& CWordAttributes::Main() const
{
	debug_check_logic( !IsEmpty() );
	return data[Text::MainAttribute];
}

const CWordAttribute& CWordAttributes::operator[]( Text::TAttribute index ) const
{
	debug_check_logic( index < data.size() );
	return data[index];
}

bool CWordAttributes::Find( const string& name, Text::TAttribute& index ) const
{
	auto i = nameIndices.find( name );
	if( i != nameIndices.cend() ) {
		index = i->second;
		return true;
	}
	return false;
}

void CWordAttributes::Print( ostream& out ) const
{
	for( const CWordAttribute& wordAttribute : data ) {
		wordAttribute.Print( out );
		out << endl;
	}
}

///////////////////////////////////////////////////////////////////////////////

CWordAttributesBuilder::CWordAttributesBuilder( const Text::TAttribute count )
{
	mains.reserve( count );
	consistents.reserve( count );
	notConsistents.reserve( count );
}

void CWordAttributesBuilder::Add( CWordAttribute&& wordAttribute )
{
	if( wordAttribute.Type == WST_Main ) {
		mains.push_back( wordAttribute );
	} else if( wordAttribute.Consistent ) {
		consistents.push_back( wordAttribute );
	} else {
		notConsistents.push_back( wordAttribute );
	}
}

bool CWordAttributesBuilder::Build( ostream& errorStream, CWordAttributes& dest )
{
	// MUST be exactly one main word sign
	// All word sign names MUST be unique
	bool success = true;

	if( mains.size() != 1 ) {
		success = false;
		errorStream << "Configuration error: MUST be exactly one main word sign!" << endl;
	}

	vector<CWordAttribute> data = move( mains );
	data.insert( data.end(), notConsistents.cbegin(), notConsistents.cend() );
	data.insert( data.end(), consistents.cbegin(), consistents.cend() );

	CWordAttributes::CNameIndices nameIndices;
	for( Text::TAttribute index = 0; index < data.size(); index++ ) {
		const CWordAttribute& attribute = data[index];

		check_logic( attribute.Type == WST_Enum
			|| attribute.Type == WST_String
			|| attribute.Type == WST_Main );
		check_logic( !attribute.Names.IsEmpty() );
		check_logic( attribute.Type != WST_String || attribute.Values.IsEmpty() );
		check_logic( attribute.Type != WST_Main || !attribute.Consistent );

		for( COrderedStrings::SizeType i = 0; i < attribute.Names.Size(); i++ ) {
			auto pair = nameIndices.insert(
				make_pair( attribute.Names.Value( i ), index ) );
			if( !pair.second ) {
				success = false;
				errorStream
					<< "Configuration error: redefinition of word sign name '"
					<< pair.first->first << "'!" << endl;
			}
		}
	}

	if( success ) {
		dest.data = move( data );
		dest.nameIndices = move( nameIndices );
	}
	return success;
}

///////////////////////////////////////////////////////////////////////////////

void CConfiguration::SetAttributes( CWordAttributes&& attributes )
{
	wordAttributes = move( attributes );
}

///////////////////////////////////////////////////////////////////////////////

static TWordSignType ParseWordSignType( const string& typeStr )
{
	if( typeStr == "enum" ) {
		return WST_Enum;
	} else if( typeStr == "string" ) {
		return WST_String;
	} else if( typeStr == "main" ) {
		return WST_Main;
	}
	return WST_None;
}

const char* JsonConfigurationSchemeText()
{
	static const char* const SchemeText = "\
{                                                                          \n\
  \"type\": \"object\",                                                    \n\
  \"properties\": {                                                        \n\
    \"word_signs\": {                                                      \n\
      \"type\": \"array\",                                                 \n\
      \"minItems\": 1,                                                     \n\
      \"items\": { \"$ref\": \"#/definitions/word_sign\" }                 \n\
    }                                                                      \n\
  },                                                                       \n\
  \"required\": [\"word_signs\"],                                          \n\
  \"additionalProperties\": false,                                         \n\
  \"definitions\": {                                                       \n\
    \"word_sign\": {                                                       \n\
      \"type\": \"object\",                                                \n\
      \"oneOf\": [                                                         \n\
        { \"$ref\": \"#/definitions/main_type\" },                         \n\
        { \"$ref\": \"#/definitions/enum_type\" },                         \n\
        { \"$ref\": \"#/definitions/string_type\" }                        \n\
      ]                                                                    \n\
    },                                                                     \n\
    \"main_type\": {                                                       \n\
      \"type\": \"object\",                                                \n\
      \"properties\": {                                                    \n\
        \"names\": { \"$ref\": \"#/definitions/string_array\" },           \n\
        \"values\": { \"$ref\": \"#/definitions/string_array\" },          \n\
        \"type\": {                                                        \n\
          \"type\": \"string\",                                            \n\
          \"pattern\": \"^main$\"                                          \n\
        }                                                                  \n\
      },                                                                   \n\
      \"required\": [\"names\", \"type\", \"values\"],                     \n\
      \"additionalProperties\": false                                      \n\
    },                                                                     \n\
    \"enum_type\": {                                                       \n\
      \"type\": \"object\",                                                \n\
      \"properties\": {                                                    \n\
        \"names\": { \"$ref\": \"#/definitions/string_array\" },           \n\
        \"values\": { \"$ref\": \"#/definitions/string_array\" },          \n\
        \"type\": {                                                        \n\
          \"type\": \"string\",                                            \n\
          \"pattern\": \"^enum$\"                                          \n\
        },                                                                 \n\
        \"consistent\": { \"type\": \"boolean\" }                          \n\
      },                                                                   \n\
      \"required\": [\"names\", \"type\", \"values\"],                     \n\
      \"additionalProperties\": false                                      \n\
    },                                                                     \n\
    \"string_type\": {                                                     \n\
      \"type\": \"object\",                                                \n\
      \"properties\": {                                                    \n\
        \"names\": { \"$ref\": \"#/definitions/string_array\" },           \n\
        \"type\": {                                                        \n\
          \"type\": \"string\",                                            \n\
          \"pattern\": \"^string$\"                                        \n\
        },                                                                 \n\
        \"consistent\": { \"type\": \"boolean\" }                          \n\
      },                                                                   \n\
      \"required\": [\"names\", \"type\"],                                 \n\
      \"additionalProperties\": false                                      \n\
    },                                                                     \n\
    \"string_array\": {                                                    \n\
      \"type\": \"array\",                                                 \n\
      \"minItems\": 1,                                                     \n\
      \"uniqueItems\": true,                                               \n\
      \"items\": {                                                         \n\
        \"type\": \"string\",                                              \n\
        \"pattern\": \"^[a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z_-])?$\"             \n\
      }                                                                    \n\
    }                                                                      \n\
  }                                                                        \n\
}                                                                          \n";
	return SchemeText;
}

CConfigurationPtr LoadConfigurationFromFile( const char* filename,
	ostream& errorStream, ostream& logStream )
{
	using namespace rapidjson;

	logStream << "Loading configuration validation scheme..." << endl;

	Document schemeDocument;
	schemeDocument.Parse( JsonConfigurationSchemeText() );
	check_logic( !schemeDocument.HasParseError() );
	SchemaDocument scheme( schemeDocument );

	logStream << "Loading configuration from file '" << filename << "'..." << endl;

	ifstream ifs1( filename );
	IStreamWrapper isw1( ifs1 );

	Document configDocument;
	configDocument.ParseStream( isw1 );

	if( configDocument.HasParseError() ) {
		errorStream << "Parse config '" << filename << "' error at char "
			<< configDocument.GetErrorOffset() << ": "
			<< GetParseError_En( configDocument.GetParseError() ) << endl;
		return CConfigurationPtr();
	}

	logStream << "Validating configuration by scheme..." << endl;

	SchemaValidator schemeValidator( scheme );
	if( !configDocument.Accept( schemeValidator ) ) {
		StringBuffer sb;
		schemeValidator.GetInvalidSchemaPointer().StringifyUriFragment( sb );
		errorStream << "Invalid schema: " << sb.GetString() << endl;
		errorStream << "Invalid keyword: "
			<< schemeValidator.GetInvalidSchemaKeyword() << endl;
		sb.Clear();
		schemeValidator.GetInvalidDocumentPointer().StringifyUriFragment( sb );
		errorStream << "Invalid document: " << sb.GetString() << endl;
		return CConfigurationPtr();
	}

	logStream << "Building configuration..." << endl;

	Value wordSignArray = configDocument["word_signs"].GetArray();
	CWordAttributesBuilder attributesBuilder( Cast<TAttribute>( wordSignArray.Size() ) );
	for( rapidjson::SizeType i = 0; i < wordSignArray.Size(); i++ ) {
		CWordAttribute attribute;
		Value wordSignObject = wordSignArray[i].GetObject();
		attribute.Type = ParseWordSignType( wordSignObject["type"].GetString() );
		debug_check_logic( attribute.Type != WST_None );

		Value nameArray = wordSignObject["names"].GetArray();
		for( rapidjson::SizeType ni = 0; ni < nameArray.Size(); ni++ ) {
			const bool added = attribute.Names.Add( nameArray[ni].GetString() );
			debug_check_logic( added );
		}
		if( wordSignObject.HasMember( "values" ) ) {
			attribute.Values.Add( "null" );
			Value valueArray = wordSignObject["values"].GetArray();
			for( rapidjson::SizeType vi = 0; vi < valueArray.Size(); vi++ ) {
				const bool added = attribute.Values.Add( valueArray[vi].GetString() );
				debug_check_logic( added );
			}
		}
		if( wordSignObject.HasMember( "consistent" ) ) {
			attribute.Consistent = wordSignObject["consistent"].GetBool();
		}
		attributesBuilder.Add( move( attribute ) );
	}

	CWordAttributes wordAttributes;
	if( !attributesBuilder.Build( errorStream, wordAttributes ) ) {
		return CConfigurationPtr();
	}

	logStream << endl;
	CConfigurationPtr configuration( new CConfiguration );
	configuration->SetAttributes( move( wordAttributes ) );
	configuration->Attributes().Print( logStream );
	logStream << "Configuration was successfully built!" << endl << endl;
	return configuration;
}

///////////////////////////////////////////////////////////////////////////////

} // end of Configuration namespace
} // end of Lspl namespace
<commit_msg>fix null value error<commit_after>#include <common.h>
#include <Configuration.h>

#define RAPIDJSON_ASSERT debug_check_logic
#include <rapidjson/rapidjson.h>
#include <rapidjson/schema.h>
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/istreamwrapper.h>

using namespace Lspl::Text;

namespace Lspl {
namespace Configuration {

///////////////////////////////////////////////////////////////////////////////

static const char* WordSignTypeString( const TWordSignType type )
{
	switch( type ) {
		case WST_None:
			break;
		case WST_Main:
			return "main";
		case WST_Enum:
			return "enum";
		case WST_String:
			return "string";
	}
	return "none";
}

///////////////////////////////////////////////////////////////////////////////

void CWordAttribute::Print( ostream& out ) const
{
	out << ( Consistent ? "consistent " : "" )
		<< WordSignTypeString( Type )
		<< " word sign"
		<< endl;

	if( !Names.IsEmpty() ) {
		out << "  names: ";
		Names.Print( out, ", " );
		out << endl;
	}
	if( !Values.IsEmpty() ) {
		out << "  values: ";
		Values.Print( out, ", " );
		out << endl;
	}
}

///////////////////////////////////////////////////////////////////////////////

bool CWordAttributes::IsEmpty() const
{
	return data.empty();
}

Text::TAttribute CWordAttributes::Size() const
{
	return Cast<Text::TAttribute>( data.size() );
}

const CWordAttribute& CWordAttributes::Main() const
{
	debug_check_logic( !IsEmpty() );
	return data[Text::MainAttribute];
}

const CWordAttribute& CWordAttributes::operator[]( Text::TAttribute index ) const
{
	debug_check_logic( index < data.size() );
	return data[index];
}

bool CWordAttributes::Find( const string& name, Text::TAttribute& index ) const
{
	auto i = nameIndices.find( name );
	if( i != nameIndices.cend() ) {
		index = i->second;
		return true;
	}
	return false;
}

void CWordAttributes::Print( ostream& out ) const
{
	for( const CWordAttribute& wordAttribute : data ) {
		wordAttribute.Print( out );
		out << endl;
	}
}

///////////////////////////////////////////////////////////////////////////////

CWordAttributesBuilder::CWordAttributesBuilder( const Text::TAttribute count )
{
	mains.reserve( count );
	consistents.reserve( count );
	notConsistents.reserve( count );
}

void CWordAttributesBuilder::Add( CWordAttribute&& wordAttribute )
{
	if( wordAttribute.Type == WST_Main ) {
		mains.push_back( wordAttribute );
	} else if( wordAttribute.Consistent ) {
		consistents.push_back( wordAttribute );
	} else {
		notConsistents.push_back( wordAttribute );
	}
}

bool CWordAttributesBuilder::Build( ostream& errorStream, CWordAttributes& dest )
{
	// MUST be exactly one main word sign
	// All word sign names MUST be unique
	bool success = true;

	if( mains.size() != 1 ) {
		success = false;
		errorStream << "Configuration error: MUST be exactly one main word sign!" << endl;
	}

	vector<CWordAttribute> data = move( mains );
	data.insert( data.end(), notConsistents.cbegin(), notConsistents.cend() );
	data.insert( data.end(), consistents.cbegin(), consistents.cend() );

	CWordAttributes::CNameIndices nameIndices;
	for( Text::TAttribute index = 0; index < data.size(); index++ ) {
		const CWordAttribute& attribute = data[index];

		check_logic( attribute.Type == WST_Enum
			|| attribute.Type == WST_String
			|| attribute.Type == WST_Main );
		check_logic( !attribute.Names.IsEmpty() );
		check_logic( attribute.Type != WST_String || attribute.Values.IsEmpty() );
		check_logic( attribute.Type != WST_Main || !attribute.Consistent );

		for( COrderedStrings::SizeType i = 0; i < attribute.Names.Size(); i++ ) {
			auto pair = nameIndices.insert(
				make_pair( attribute.Names.Value( i ), index ) );
			if( !pair.second ) {
				success = false;
				errorStream
					<< "Configuration error: redefinition of word sign name '"
					<< pair.first->first << "'!" << endl;
			}
		}
	}

	if( success ) {
		dest.data = move( data );
		dest.nameIndices = move( nameIndices );
	}
	return success;
}

///////////////////////////////////////////////////////////////////////////////

void CConfiguration::SetAttributes( CWordAttributes&& attributes )
{
	wordAttributes = move( attributes );
}

///////////////////////////////////////////////////////////////////////////////

static TWordSignType ParseWordSignType( const string& typeStr )
{
	if( typeStr == "enum" ) {
		return WST_Enum;
	} else if( typeStr == "string" ) {
		return WST_String;
	} else if( typeStr == "main" ) {
		return WST_Main;
	}
	return WST_None;
}

const char* JsonConfigurationSchemeText()
{
	static const char* const SchemeText = "\
{                                                                          \n\
  \"type\": \"object\",                                                    \n\
  \"properties\": {                                                        \n\
    \"word_signs\": {                                                      \n\
      \"type\": \"array\",                                                 \n\
      \"minItems\": 1,                                                     \n\
      \"items\": { \"$ref\": \"#/definitions/word_sign\" }                 \n\
    }                                                                      \n\
  },                                                                       \n\
  \"required\": [\"word_signs\"],                                          \n\
  \"additionalProperties\": false,                                         \n\
  \"definitions\": {                                                       \n\
    \"word_sign\": {                                                       \n\
      \"type\": \"object\",                                                \n\
      \"oneOf\": [                                                         \n\
        { \"$ref\": \"#/definitions/main_type\" },                         \n\
        { \"$ref\": \"#/definitions/enum_type\" },                         \n\
        { \"$ref\": \"#/definitions/string_type\" }                        \n\
      ]                                                                    \n\
    },                                                                     \n\
    \"main_type\": {                                                       \n\
      \"type\": \"object\",                                                \n\
      \"properties\": {                                                    \n\
        \"names\": { \"$ref\": \"#/definitions/string_array\" },           \n\
        \"values\": { \"$ref\": \"#/definitions/string_array\" },          \n\
        \"type\": {                                                        \n\
          \"type\": \"string\",                                            \n\
          \"pattern\": \"^main$\"                                          \n\
        }                                                                  \n\
      },                                                                   \n\
      \"required\": [\"names\", \"type\", \"values\"],                     \n\
      \"additionalProperties\": false                                      \n\
    },                                                                     \n\
    \"enum_type\": {                                                       \n\
      \"type\": \"object\",                                                \n\
      \"properties\": {                                                    \n\
        \"names\": { \"$ref\": \"#/definitions/string_array\" },           \n\
        \"values\": { \"$ref\": \"#/definitions/string_array\" },          \n\
        \"type\": {                                                        \n\
          \"type\": \"string\",                                            \n\
          \"pattern\": \"^enum$\"                                          \n\
        },                                                                 \n\
        \"consistent\": { \"type\": \"boolean\" }                          \n\
      },                                                                   \n\
      \"required\": [\"names\", \"type\", \"values\"],                     \n\
      \"additionalProperties\": false                                      \n\
    },                                                                     \n\
    \"string_type\": {                                                     \n\
      \"type\": \"object\",                                                \n\
      \"properties\": {                                                    \n\
        \"names\": { \"$ref\": \"#/definitions/string_array\" },           \n\
        \"type\": {                                                        \n\
          \"type\": \"string\",                                            \n\
          \"pattern\": \"^string$\"                                        \n\
        },                                                                 \n\
        \"consistent\": { \"type\": \"boolean\" }                          \n\
      },                                                                   \n\
      \"required\": [\"names\", \"type\"],                                 \n\
      \"additionalProperties\": false                                      \n\
    },                                                                     \n\
    \"string_array\": {                                                    \n\
      \"type\": \"array\",                                                 \n\
      \"minItems\": 1,                                                     \n\
      \"uniqueItems\": true,                                               \n\
      \"items\": {                                                         \n\
        \"type\": \"string\",                                              \n\
        \"pattern\": \"^[a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z_-])?$\"             \n\
      }                                                                    \n\
    }                                                                      \n\
  }                                                                        \n\
}                                                                          \n";
	return SchemeText;
}

CConfigurationPtr LoadConfigurationFromFile( const char* filename,
	ostream& errorStream, ostream& logStream )
{
	using namespace rapidjson;

	logStream << "Loading configuration validation scheme..." << endl;

	Document schemeDocument;
	schemeDocument.Parse( JsonConfigurationSchemeText() );
	check_logic( !schemeDocument.HasParseError() );
	SchemaDocument scheme( schemeDocument );

	logStream << "Loading configuration from file '" << filename << "'..." << endl;

	ifstream ifs1( filename );
	IStreamWrapper isw1( ifs1 );

	Document configDocument;
	configDocument.ParseStream( isw1 );

	if( configDocument.HasParseError() ) {
		errorStream << "Parse config '" << filename << "' error at char "
			<< configDocument.GetErrorOffset() << ": "
			<< GetParseError_En( configDocument.GetParseError() ) << endl;
		return CConfigurationPtr();
	}

	logStream << "Validating configuration by scheme..." << endl;

	SchemaValidator schemeValidator( scheme );
	if( !configDocument.Accept( schemeValidator ) ) {
		StringBuffer sb;
		schemeValidator.GetInvalidSchemaPointer().StringifyUriFragment( sb );
		errorStream << "Invalid schema: " << sb.GetString() << endl;
		errorStream << "Invalid keyword: "
			<< schemeValidator.GetInvalidSchemaKeyword() << endl;
		sb.Clear();
		schemeValidator.GetInvalidDocumentPointer().StringifyUriFragment( sb );
		errorStream << "Invalid document: " << sb.GetString() << endl;
		return CConfigurationPtr();
	}

	logStream << "Building configuration..." << endl;

	Value wordSignArray = configDocument["word_signs"].GetArray();
	CWordAttributesBuilder attributesBuilder( Cast<TAttribute>( wordSignArray.Size() ) );
	for( rapidjson::SizeType i = 0; i < wordSignArray.Size(); i++ ) {
		CWordAttribute attribute;
		Value wordSignObject = wordSignArray[i].GetObject();
		attribute.Type = ParseWordSignType( wordSignObject["type"].GetString() );
		debug_check_logic( attribute.Type != WST_None );

		Value nameArray = wordSignObject["names"].GetArray();
		for( rapidjson::SizeType ni = 0; ni < nameArray.Size(); ni++ ) {
			const bool added = attribute.Names.Add( nameArray[ni].GetString() );
			debug_check_logic( added );
		}
		if( wordSignObject.HasMember( "values" ) ) {
			if( attribute.Type == WST_Enum ) {
				attribute.Values.Add( "" );
			}
			Value valueArray = wordSignObject["values"].GetArray();
			for( rapidjson::SizeType vi = 0; vi < valueArray.Size(); vi++ ) {
				const bool added = attribute.Values.Add( valueArray[vi].GetString() );
				debug_check_logic( added );
			}
		}
		if( wordSignObject.HasMember( "consistent" ) ) {
			attribute.Consistent = wordSignObject["consistent"].GetBool();
		}
		attributesBuilder.Add( move( attribute ) );
	}

	CWordAttributes wordAttributes;
	if( !attributesBuilder.Build( errorStream, wordAttributes ) ) {
		return CConfigurationPtr();
	}

	logStream << endl;
	CConfigurationPtr configuration( new CConfiguration );
	configuration->SetAttributes( move( wordAttributes ) );
	configuration->Attributes().Print( logStream );
	logStream << "Configuration was successfully built!" << endl << endl;
	return configuration;
}

///////////////////////////////////////////////////////////////////////////////

} // end of Configuration namespace
} // end of Lspl namespace
<|endoftext|>


<commit_before>/*
 * Copyright 2004 Sandia Corporation.
 * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
 * license for use of this work by or on behalf of the
 * U.S. Government. Redistribution and use in source and binary forms, with
 * or without modification, are permitted provided that this Notice and any
 * statement of authorship are reproduced on all copies.
 */
#include "vtkSESAMEReader.h"

#include <vtkFloatArray.h>
#include <vtkIntArray.h>
#include <vtkObjectFactory.h>
#include <vtkPointData.h>
#include <vtkRectilinearGrid.h>
#include <vtkstd/vector>
#include <vtkstd/string>

vtkStandardNewMacro(vtkSESAMEReader);
vtkCxxRevisionMacro(vtkSESAMEReader, "1.4");

static const int SESAME_NUM_CHARS = 512;
static const char* TableLineFormat = "%2i%6i%6i";

class vtkSESAMEReader::MyInternal
{
public:
  vtkstd::string FileName;
  FILE* File;
  vtkstd::vector<int> TableIds;
  vtkstd::vector<long> TableLocations;
  vtkIdType TableId;
  vtkstd::vector<vtkstd::string> TableArrays;
  vtkstd::vector<int> TableArrayStatus;
  vtkIntArray* TableIdsArray;

  void ClearTables()
    {
    this->TableIds.clear();
    this->TableId = -1;
    this->TableIdsArray->Initialize();
    this->ClearArrays();
    }
  void ClearArrays()
    {
    this->TableArrays.clear();
    this->TableArrayStatus.clear();
    }

  MyInternal()
    {
    this->File = NULL;
    this->TableId = -1;
    this->TableIdsArray = vtkIntArray::New();
    }
  ~MyInternal()
    {
    this->TableIdsArray->Delete();
    }
};

// structures to hold information about SESAME files
static const int MaxTableArrays = 10;
struct vtkSESAMETableDef
{
  int TableId;
  const char* Arrays[MaxTableArrays];
};

static const vtkSESAMETableDef TableDefs[] =
{
    {301,
      {"301: Total EOS (Pressure)",
       "301: Total EOS (Energy)",
       "301: Total EOS (Free Energy)",
      0}  // keep 0 last
    },

    {304,
      {"304: Electron EOS (Pressure)",
       "304: Electron EOS (Energy)",
       "304: Electron EOS (Free Energy)",
       0}  // keep 0 last
    },

    {502,
      {"502: Rosseland Mean Opacity",
       0}  // keep 0 last
    },

    {503,
      {"503: Electron Conductive Opacity1",
       0}  // keep 0 last
    },

    {504,
      {"504: Mean Ion Charge1",
       0}  // keep 0 last
    },

    {505,
      {"505: Planck Mean Opacity",
       0}  // keep 0 last
    },

    {602,
      {"602: Electrical Conductivity",
       0}  // keep 0 last
    }
};

static int TableIndex(int tableId)
{
  // check that we got a valid table id
  for(unsigned int i=0; i<sizeof(TableDefs); i++)
    {
    if(tableId == TableDefs[i].TableId)
      {
      return i;
      }
    }
  return -1;
}

vtkSESAMEReader::vtkSESAMEReader() : vtkRectilinearGridSource()
{
  this->Internal = new MyInternal();
}

vtkSESAMEReader::~vtkSESAMEReader()
{
  this->CloseFile();
  delete this->Internal;
}

int vtkSESAMEReader::IsValidFile()
{
  if(this->Internal->FileName.empty())
    {
    return 0;
    }

  // open the file
  FILE* f = fopen(this->GetFileName(), "rb");
  if(!f)
    {
    return 0;
    }

  // check that it is valid
  int a,b,c;
  int ret = fscanf(f, TableLineFormat, &a,&b,&c);
  fclose(f);
  if(ret != 3)
    {
    return 0;
    }
  return 1;
}

void vtkSESAMEReader::SetFileName(const char* file)
{
  if(this->Internal->FileName == file)
    {
    return;
    }

  this->Internal->FileName = file;

  // clean out possible data from last file
  this->Internal->ClearTables();
  this->CloseFile();
}

const char* vtkSESAMEReader::GetFileName()
{
  return this->Internal->FileName.c_str();
}

int vtkSESAMEReader::OpenFile()
{
  //already open
  if(this->Internal->File)
    {
    return 1;
    }

  if(this->Internal->FileName.empty())
    {
    return 0;
    }

  // open the file
  this->Internal->File = fopen(this->GetFileName(), "rb");
  if(!this->Internal->File)
    {
    vtkErrorMacro(<<"Unable to open file " << this->GetFileName());
    return 0;
    }

  // check that it is valid
  int a,b,c;
  int ret = fscanf(this->Internal->File, TableLineFormat, &a,&b,&c);
  rewind(this->Internal->File);
  if(ret != 3)
    {
    vtkErrorMacro(<<this->GetFileName() << " is not a valid SESAME file");
    fclose(this->Internal->File);
    this->Internal->File = NULL;
    return 0;
    }
  return 1;
}

void vtkSESAMEReader::CloseFile()
{
  if(this->Internal->File)
    {
    fclose(this->Internal->File);
    this->Internal->File = NULL;
    }
}

int vtkSESAMEReader::GetNumberOfTableIds()
{
  this->ExecuteInformation();
  return this->Internal->TableIds.size();
}

int* vtkSESAMEReader::GetTableIds()
{
  this->ExecuteInformation();
  return &this->Internal->TableIds[0];
}

vtkIntArray* vtkSESAMEReader::GetTableIdsAsArray()
{
  this->Internal->TableIdsArray->Initialize();
  this->Internal->TableIdsArray->SetNumberOfComponents(1);
  this->ExecuteInformation();
  int numTableIds = this->Internal->TableIds.size();
  for (int i=0; i < numTableIds; ++i)
    {
    this->Internal->TableIdsArray->InsertNextValue(
      this->Internal->TableIds[i]);
    }
  return this->Internal->TableIdsArray;
}

void vtkSESAMEReader::SetTable(int tableId)
{
  if(this->Internal->TableId != tableId)
    {
    if(TableIndex(tableId) != -1)
      {
      this->Internal->TableId = tableId;

      // clean out info about the previous table
      this->Internal->ClearArrays();
      this->Modified();
      }
    }
}

int vtkSESAMEReader::GetTable()
{
  this->ExecuteInformation();
  return this->Internal->TableId;
}

int vtkSESAMEReader::GetNumberOfTableArrayNames()
{
  this->ExecuteInformation();
  return this->Internal->TableArrays.size();
}

const char* vtkSESAMEReader::GetTableArrayName(int index)
{
  this->ExecuteInformation();
  int s = this->Internal->TableArrays.size();
  if(s > index)
    {
    return this->Internal->TableArrays[index].c_str();
    }
  return NULL;
}

void vtkSESAMEReader::SetTableArrayStatus(const char* name, int flag)
{
  int i, numArrays;
  numArrays = this->Internal->TableArrays.size();
  for(i=0; i<numArrays; i++)
    {
    if(this->Internal->TableArrays[i] == name)
      {
      this->Internal->TableArrayStatus[i] = flag;
      this->Modified();
      }
    }
}

int vtkSESAMEReader::GetTableArrayStatus(const char* name)
{
  this->ExecuteInformation();
  int i, numArrays;
  numArrays = this->Internal->TableArrays.size();
  for(i=0; i<numArrays; i++)
    {
    if(this->Internal->TableArrays[i], name)
      {
      return this->Internal->TableArrayStatus[i];
      }
    }
  return 0;
}

void vtkSESAMEReader::ExecuteInformation()
{
  // open the file
  if(!this->OpenFile())
    {
    return;
    }

  if(this->Internal->TableIds.empty())
    {
    this->Internal->TableLocations.clear();

    // get the table ids

    char buffer[SESAME_NUM_CHARS];
    int dummy;
    int internalId;
    int tableId;

    // read lines from the file the whole file
    while( fgets(buffer, SESAME_NUM_CHARS, this->Internal->File) != NULL )
      {
      // see if the line matches the  " 0 9999 602" format
      if(sscanf(buffer, TableLineFormat, &dummy, &internalId, &tableId) == 3)
        {
        if(TableIndex(tableId) != -1)
          {
          this->Internal->TableIds.push_back(tableId);
          long loc = ftell(this->Internal->File);
          this->Internal->TableLocations.push_back(loc);
          }
        }
      }
    }

  if(this->Internal->TableId == -1 &&
     !this->Internal->TableIds.empty())
    {
    this->Internal->TableId = this->Internal->TableIds[0];
    }

  if(this->Internal->TableId != -1)
    {
    JumpToTable(this->Internal->TableId);
    float v[5] = { 0.0, 0.0, 0.0, 0.0, 0.0 };
    if ( ReadTableValueLine( &(v[0]), &(v[1]),
                             &(v[2]), &(v[3]), &(v[4]) ) != 0)
      {
      // first two values are dimensions of
      // grid
      this->GetOutput()->SetWholeExtent(0, (int)(v[0]) - 1,
                                        0, (int)(v[1]) - 1, 0, 0 );
      }
    }

  if(this->Internal->TableId != -1 &&
     this->Internal->TableArrays.empty())
    {
    // get the names of the arrays in the table
    int tableIndex = TableIndex(this->Internal->TableId);
    for(int j=0; TableDefs[tableIndex].Arrays[j] != 0; j++)
      {
      this->Internal->TableArrays.push_back(
                TableDefs[tableIndex].Arrays[j]);
      this->Internal->TableArrayStatus.push_back(1);  // all arrays are on
                                                      // by default
      }
    }
}

int vtkSESAMEReader::JumpToTable( int toTable )
{
  int numIds = this->Internal->TableIds.size();
  for(int i=0; i<numIds; i++)
    {
    if(this->Internal->TableIds[i] == toTable)
      {
      fseek(this->Internal->File, this->Internal->TableLocations[i], SEEK_SET);
      return 1;
      }
    }

  return 0;
}

void vtkSESAMEReader::Execute()
{
  // read the file
  JumpToTable(this->Internal->TableId);
  this->ReadTable();
}

void vtkSESAMEReader::ReadTable()
{
  vtkFloatArray *xCoords = vtkFloatArray::New();
  vtkFloatArray *yCoords = vtkFloatArray::New();
  vtkFloatArray *zCoords = vtkFloatArray::New();

  vtkRectilinearGrid *output = this->GetOutput();

  float v[5] = { 0.0, 0.0, 0.0, 0.0, 0.0 };
  int datadims[2] = { 0, 0 };
  int numRead = 0;

  // get the table header
  if ( ReadTableValueLine( &(v[0]), &(v[1]), &(v[2]), &(v[3]), &(v[4]) ) != 0)
    {
    // dimensions of grid
    datadims[0] = (int)(v[0]);
    datadims[1] = (int)(v[1]);
    output->SetDimensions( datadims[0], datadims[1], 1 );

    // allocate space
    xCoords->Allocate( datadims[0] );
    yCoords->Allocate( datadims[1] );
    zCoords->Allocate( 1 );
    zCoords->InsertNextTuple1( 0.0 );

    // the first three values are x samples ...
    xCoords->InsertNextTuple1( v[2] );
    xCoords->InsertNextTuple1( v[3] );
    xCoords->InsertNextTuple1( v[4] );
    numRead = 3;
    }

  vtkstd::vector<vtkFloatArray*> scalars;
  for(unsigned int i=0; i<this->Internal->TableArrayStatus.size(); i++)
    {
    vtkFloatArray* newArray = this->Internal->TableArrayStatus[i] ?
                      vtkFloatArray::New() : NULL;
    scalars.push_back(newArray);
    if(newArray)
      {
      newArray->Allocate(datadims[0] * datadims[1]);
      newArray->SetName(this->Internal->TableArrays[i].c_str());
      }
    }

  unsigned int scalarIndex = 0;
  int scalarCount = 0;
  int readFromTable = 0;

  while ( (readFromTable = ReadTableValueLine( &(v[0]), &(v[1]), &(v[2]), &(v[3]),
      &(v[4])  )) != 0)
    {
    for (int i=0;i<readFromTable;i++)
      {
      if ( numRead < datadims[0] )
        {
        xCoords->InsertNextTuple1(  v[i] );
        }
      else if ( numRead < (datadims[0] + datadims[1]) )
        {
        yCoords->InsertNextTuple1(  v[i] );
        }
      else
        {
        scalarCount++;
        if(scalarCount > datadims[0] * datadims[1])
          {
          scalarCount = 0;
          scalarIndex++;
          }
        if(this->Internal->TableArrayStatus.size() > scalarIndex &&
           this->Internal->TableArrayStatus[scalarIndex])
          {
          scalars[scalarIndex]->InsertNextTuple1(v[i]);
          }
        }
      numRead++;
      }
    }

  output->SetXCoordinates( xCoords );
  output->SetYCoordinates( yCoords );
  output->SetZCoordinates( zCoords );

  output->GetPointData()->Reset();

  for(unsigned int j=0; j<scalars.size(); j++)
    {
    if(scalars[j])
      {
      output->GetPointData()->AddArray(scalars[j]);
      scalars[j]->Delete();
      }
    }

  xCoords->Delete();
  yCoords->Delete();
  zCoords->Delete();

  output->Squeeze();
}

int vtkSESAMEReader::ReadTableValueLine ( float *v1, float *v2,
  float *v3, float *v4, float *v5)
{
  // by definition, a line of this file is 80 characters long
  // when we start reading the data values, the end of the line is a tag
  // (see note below), which we have to ignore in order to read the data
  // properly.
  //
  char buffer[SESAME_NUM_CHARS + 1];
  buffer[SESAME_NUM_CHARS] = '\0';
  int numRead = 0;
  if ( fgets(buffer, SESAME_NUM_CHARS, this->Internal->File) != NULL )
    {
    int dummy;
    int internalId;
    int tableId;

    // see if the line matches the  " 0 9999 602" format
    if(sscanf(buffer, TableLineFormat, &dummy, &internalId, &tableId) == 3)
      {
      // this is the start of a new table
      numRead = 0;
      }
    else
      {
      // ignore the last 5 characters of the line (see notes above)
      buffer[75] = '\0';
      numRead = sscanf( buffer, "%e%e%e%e%e", v1, v2, v3, v4, v5);
      }
    }

  return numRead;
}

void vtkSESAMEReader::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "FileName: " << this->GetFileName() << "\n";
  os << indent << "Table: " << this->GetTable() << "\n";
}

<commit_msg><commit_after>/*
 * Copyright 2004 Sandia Corporation.
 * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
 * license for use of this work by or on behalf of the
 * U.S. Government. Redistribution and use in source and binary forms, with
 * or without modification, are permitted provided that this Notice and any
 * statement of authorship are reproduced on all copies.
 */
#include "vtkSESAMEReader.h"

#include <vtkFloatArray.h>
#include <vtkIntArray.h>
#include <vtkObjectFactory.h>
#include <vtkPointData.h>
#include <vtkRectilinearGrid.h>
#include <vtkstd/vector>
#include <vtkstd/string>

vtkStandardNewMacro(vtkSESAMEReader);
vtkCxxRevisionMacro(vtkSESAMEReader, "1.5");

static const int SESAME_NUM_CHARS = 512;
static const char* TableLineFormat = "%2i%6i%6i";

class vtkSESAMEReader::MyInternal
{
public:
  vtkstd::string FileName;
  FILE* File;
  vtkstd::vector<int> TableIds;
  vtkstd::vector<long> TableLocations;
  vtkIdType TableId;
  vtkstd::vector<vtkstd::string> TableArrays;
  vtkstd::vector<int> TableArrayStatus;
  vtkIntArray* TableIdsArray;

  void ClearTables()
    {
    this->TableIds.clear();
    this->TableId = -1;
    this->TableIdsArray->Initialize();
    this->ClearArrays();
    }
  void ClearArrays()
    {
    this->TableArrays.clear();
    this->TableArrayStatus.clear();
    }

  MyInternal()
    {
    this->File = NULL;
    this->TableId = -1;
    this->TableIdsArray = vtkIntArray::New();
    }
  ~MyInternal()
    {
    this->TableIdsArray->Delete();
    }
};

// structures to hold information about SESAME files
static const int MaxTableArrays = 10;
struct vtkSESAMETableDef
{
  int TableId;
  const char* Arrays[MaxTableArrays];
};

static const vtkSESAMETableDef TableDefs[] =
{
    {301,
      {"301: Total EOS (Pressure)",
       "301: Total EOS (Energy)",
       "301: Total EOS (Free Energy)",
      0}  // keep 0 last
    },

    {304,
      {"304: Electron EOS (Pressure)",
       "304: Electron EOS (Energy)",
       "304: Electron EOS (Free Energy)",
       0}  // keep 0 last
    },

    {502,
      {"502: Rosseland Mean Opacity",
       0}  // keep 0 last
    },

    {503,
      {"503: Electron Conductive Opacity1",
       0}  // keep 0 last
    },

    {504,
      {"504: Mean Ion Charge1",
       0}  // keep 0 last
    },

    {505,
      {"505: Planck Mean Opacity",
       0}  // keep 0 last
    },

    {602,
      {"602: Electrical Conductivity",
       0}  // keep 0 last
    }
};

static int TableIndex(int tableId)
{
  // check that we got a valid table id
  for(unsigned int i=0; i<sizeof(TableDefs); i++)
    {
    if(tableId == TableDefs[i].TableId)
      {
      return i;
      }
    }
  return -1;
}

vtkSESAMEReader::vtkSESAMEReader() : vtkRectilinearGridSource()
{
  this->Internal = new MyInternal();
}

vtkSESAMEReader::~vtkSESAMEReader()
{
  this->CloseFile();
  delete this->Internal;
}

int vtkSESAMEReader::IsValidFile()
{
  if(this->Internal->FileName.empty())
    {
    return 0;
    }

  // open the file
  FILE* f = fopen(this->GetFileName(), "rb");
  if(!f)
    {
    return 0;
    }

  // check that it is valid
  int a,b,c;
  int ret = fscanf(f, TableLineFormat, &a,&b,&c);
  fclose(f);
  if(ret != 3)
    {
    return 0;
    }
  return 1;
}

void vtkSESAMEReader::SetFileName(const char* file)
{
  if(this->Internal->FileName == file)
    {
    return;
    }

  this->Internal->FileName = file;

  // clean out possible data from last file
  this->Internal->ClearTables();
  this->CloseFile();
}

const char* vtkSESAMEReader::GetFileName()
{
  return this->Internal->FileName.c_str();
}

int vtkSESAMEReader::OpenFile()
{
  //already open
  if(this->Internal->File)
    {
    return 1;
    }

  if(this->Internal->FileName.empty())
    {
    return 0;
    }

  // open the file
  this->Internal->File = fopen(this->GetFileName(), "rb");
  if(!this->Internal->File)
    {
    vtkErrorMacro(<<"Unable to open file " << this->GetFileName());
    return 0;
    }

  // check that it is valid
  int a,b,c;
  int ret = fscanf(this->Internal->File, TableLineFormat, &a,&b,&c);
  rewind(this->Internal->File);
  if(ret != 3)
    {
    vtkErrorMacro(<<this->GetFileName() << " is not a valid SESAME file");
    fclose(this->Internal->File);
    this->Internal->File = NULL;
    return 0;
    }
  return 1;
}

void vtkSESAMEReader::CloseFile()
{
  if(this->Internal->File)
    {
    fclose(this->Internal->File);
    this->Internal->File = NULL;
    }
}

int vtkSESAMEReader::GetNumberOfTableIds()
{
  this->ExecuteInformation();
  return this->Internal->TableIds.size();
}

int* vtkSESAMEReader::GetTableIds()
{
  this->ExecuteInformation();
  return &this->Internal->TableIds[0];
}

vtkIntArray* vtkSESAMEReader::GetTableIdsAsArray()
{
  this->Internal->TableIdsArray->Initialize();
  this->Internal->TableIdsArray->SetNumberOfComponents(1);
  this->ExecuteInformation();
  int numTableIds = this->Internal->TableIds.size();
  for (int i=0; i < numTableIds; ++i)
    {
    this->Internal->TableIdsArray->InsertNextValue(
      this->Internal->TableIds[i]);
    }
  return this->Internal->TableIdsArray;
}

void vtkSESAMEReader::SetTable(int tableId)
{
  if(this->Internal->TableId != tableId)
    {
    if(TableIndex(tableId) != -1)
      {
      this->Internal->TableId = tableId;

      // clean out info about the previous table
      this->Internal->ClearArrays();
      this->Modified();
      }
    }
}

int vtkSESAMEReader::GetTable()
{
  this->ExecuteInformation();
  return this->Internal->TableId;
}

int vtkSESAMEReader::GetNumberOfTableArrayNames()
{
  this->ExecuteInformation();
  return this->Internal->TableArrays.size();
}

const char* vtkSESAMEReader::GetTableArrayName(int index)
{
  this->ExecuteInformation();
  int s = this->Internal->TableArrays.size();
  if(s > index)
    {
    return this->Internal->TableArrays[index].c_str();
    }
  return NULL;
}

void vtkSESAMEReader::SetTableArrayStatus(const char* name, int flag)
{
  int i, numArrays;
  numArrays = this->Internal->TableArrays.size();
  for(i=0; i<numArrays; i++)
    {
    if(this->Internal->TableArrays[i] == name)
      {
      this->Internal->TableArrayStatus[i] = flag;
      this->Modified();
      }
    }
}

int vtkSESAMEReader::GetTableArrayStatus(const char* name)
{
  this->ExecuteInformation();
  int i, numArrays;
  numArrays = this->Internal->TableArrays.size();
  for(i=0; i<numArrays; i++)
    {
    if(this->Internal->TableArrays[i], name)
      {
      return this->Internal->TableArrayStatus[i];
      }
    }
  return 0;
}

void vtkSESAMEReader::ExecuteInformation()
{
  // open the file
  if(!this->OpenFile())
    {
    return;
    }

  if(this->Internal->TableIds.empty())
    {
    this->Internal->TableLocations.clear();

    // get the table ids

    char buffer[SESAME_NUM_CHARS];
    int dummy;
    int internalId;
    int tableId;

    // read lines from the file the whole file
    while( fgets(buffer, SESAME_NUM_CHARS, this->Internal->File) != NULL )
      {
      // see if the line matches the  " 0 9999 602" format
      if(sscanf(buffer, TableLineFormat, &dummy, &internalId, &tableId) == 3)
        {
        if(TableIndex(tableId) != -1)
          {
          this->Internal->TableIds.push_back(tableId);
          long loc = ftell(this->Internal->File);
          this->Internal->TableLocations.push_back(loc);
          }
        }
      }
    }

  if(this->Internal->TableId == -1 &&
     !this->Internal->TableIds.empty())
    {
    this->Internal->TableId = this->Internal->TableIds[0];
    }

  if(this->Internal->TableId != -1)
    {
    JumpToTable(this->Internal->TableId);
    float v[5] = { 0.0, 0.0, 0.0, 0.0, 0.0 };
    if ( ReadTableValueLine( &(v[0]), &(v[1]),
                             &(v[2]), &(v[3]), &(v[4]) ) != 0)
      {
      // first two values are dimensions of
      // grid
      this->GetOutput()->SetWholeExtent(0, (int)(v[0]) - 1,
                                        0, (int)(v[1]) - 1, 0, 0 );
      }
    }

  if(this->Internal->TableId != -1 &&
     this->Internal->TableArrays.empty())
    {
    // get the names of the arrays in the table
    int tableIndex = TableIndex(this->Internal->TableId);
    for(int j=0; TableDefs[tableIndex].Arrays[j] != 0; j++)
      {
      this->Internal->TableArrays.push_back(
                TableDefs[tableIndex].Arrays[j]);
      this->Internal->TableArrayStatus.push_back(1);  // all arrays are on
                                                      // by default
      }
    }
}

int vtkSESAMEReader::JumpToTable( int toTable )
{
  int numIds = this->Internal->TableIds.size();
  for(int i=0; i<numIds; i++)
    {
    if(this->Internal->TableIds[i] == toTable)
      {
      fseek(this->Internal->File, this->Internal->TableLocations[i], SEEK_SET);
      return 1;
      }
    }

  return 0;
}

void vtkSESAMEReader::Execute()
{
  // read the file
  JumpToTable(this->Internal->TableId);
  this->ReadTable();
}

void vtkSESAMEReader::ReadTable()
{
  vtkFloatArray *xCoords = vtkFloatArray::New();
  vtkFloatArray *yCoords = vtkFloatArray::New();
  vtkFloatArray *zCoords = vtkFloatArray::New();

  vtkRectilinearGrid *output = this->GetOutput();

  float v[5] = { 0.0, 0.0, 0.0, 0.0, 0.0 };
  int datadims[2] = { 0, 0 };
  int numRead = 0;

  // get the table header
  if ( ReadTableValueLine( &(v[0]), &(v[1]), &(v[2]), &(v[3]), &(v[4]) ) != 0)
    {
    // dimensions of grid
    datadims[0] = (int)(v[0]);
    datadims[1] = (int)(v[1]);
    output->SetDimensions( datadims[0], datadims[1], 1 );

    // allocate space
    xCoords->Allocate( datadims[0] );
    yCoords->Allocate( datadims[1] );
    zCoords->Allocate( 1 );
    zCoords->InsertNextTuple1( 0.0 );

    // the first three values are x samples ...
    xCoords->InsertNextTuple1( v[2] );
    xCoords->InsertNextTuple1( v[3] );
    xCoords->InsertNextTuple1( v[4] );
    numRead = 3;
    }

  vtkstd::vector<vtkFloatArray*> scalars;
  for(unsigned int i=0; i<this->Internal->TableArrayStatus.size(); i++)
    {
    vtkFloatArray* newArray = this->Internal->TableArrayStatus[i] ?
                      vtkFloatArray::New() : NULL;
    scalars.push_back(newArray);
    if(newArray)
      {
      newArray->Allocate(datadims[0] * datadims[1]);
      newArray->SetName(this->Internal->TableArrays[i].c_str());
      }
    }

  unsigned int scalarIndex = 0;
  int scalarCount = 0;
  int readFromTable = 0;

  while ( (readFromTable = ReadTableValueLine( &(v[0]), &(v[1]), &(v[2]), &(v[3]),
      &(v[4])  )) != 0)
    {
    for (int i=0;i<readFromTable;i++)
      {
      if ( numRead < datadims[0] )
        {
        xCoords->InsertNextTuple1(  v[i] );
        }
      else if ( numRead < (datadims[0] + datadims[1]) )
        {
        yCoords->InsertNextTuple1(  v[i] );
        }
      else
        {
        scalarCount++;
        if(scalarCount > datadims[0] * datadims[1])
          {
          scalarCount = 1;
          scalarIndex++;
          }
        if(this->Internal->TableArrayStatus.size() > scalarIndex &&
           this->Internal->TableArrayStatus[scalarIndex])
          {
          scalars[scalarIndex]->InsertNextTuple1(v[i]);
          }
        }
      numRead++;
      }
    }

  for(int i=scalarIndex+1;
      i<this->Internal->TableArrayStatus.size();
      i++)
    {
    // fill in the empty scalars with zeros
    int max = datadims[0] * datadims[1];
    for(int j=0; j<max; j++)
      {
      scalars[i]->InsertNextTuple1(0.0);
      }
    }

  output->SetXCoordinates( xCoords );
  output->SetYCoordinates( yCoords );
  output->SetZCoordinates( zCoords );

  output->GetPointData()->Reset();

  for(unsigned int j=0; j<scalars.size(); j++)
    {
    if(scalars[j])
      {
      if(scalars[j]->GetNumberOfTuples())
        {
        output->GetPointData()->AddArray(scalars[j]);
        }
      scalars[j]->Delete();
      }
    }

  xCoords->Delete();
  yCoords->Delete();
  zCoords->Delete();

  output->Squeeze();
}

int vtkSESAMEReader::ReadTableValueLine ( float *v1, float *v2,
  float *v3, float *v4, float *v5)
{
  // by definition, a line of this file is 80 characters long
  // when we start reading the data values, the end of the line is a tag
  // (see note below), which we have to ignore in order to read the data
  // properly.
  //
  char buffer[SESAME_NUM_CHARS + 1];
  buffer[SESAME_NUM_CHARS] = '\0';
  int numRead = 0;
  if ( fgets(buffer, SESAME_NUM_CHARS, this->Internal->File) != NULL )
    {
    int dummy;
    int internalId;
    int tableId;

    // see if the line matches the  " 0 9999 602" format
    if(sscanf(buffer, TableLineFormat, &dummy, &internalId, &tableId) == 3)
      {
      // this is the start of a new table
      numRead = 0;
      }
    else
      {
      // ignore the last 5 characters of the line (see notes above)
      buffer[75] = '\0';
      numRead = sscanf( buffer, "%e%e%e%e%e", v1, v2, v3, v4, v5);
      }
    }

  return numRead;
}

void vtkSESAMEReader::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "FileName: " << this->GetFileName() << "\n";
  os << indent << "Table: " << this->GetTable() << "\n";
}

<|endoftext|>