Skip to content

File NPOptionManager.cxx

File List > core > NPOptionManager.cxx

Go to the documentation of this file

#include "NPOptionManager.h"
#include "NPException.h"
#include "NPFunction.h"
#include "NPInputParser.h"
#include "NPTerminalColor.h"
#include <cstdlib>
#include <cstring>
#include <filesystem>
#include <fstream>
#include <sstream>
#include <vector>
namespace fs = std::filesystem;

using namespace nptool;

void OptionManager::ReadProjectConfigFile(std::string app_name) {
  m_app_name = app_name;
  if (app_name == "nptool")
    return;

  // find where is the project base directory
  bool found_project_base = false;
  fs::path root = ("/");
  fs::path project_base = fs::current_path();
  fs::path project_yaml("project.yaml");
  fs::path project_install("install");
  while (!(fs::exists(project_base / project_yaml) && fs::exists(project_base / project_yaml))) {
    project_base = project_base.parent_path();
    if (project_base == root) {
      break;
    }
  }
  if (project_base == root) {
    nptool::message("yellow", "core", "OptionManager::ReadProjectConfigFile", "No project base directory found");
    return;
  }

  nptool::message("green", "core", "OptionManager::ReadProjectConfigFile",
                  "Found project base directory: " + project_base.string());
  // check if the file exist
  std::string project_file = (project_base / project_yaml).string();
  std::ifstream ProjectFile;
  ProjectFile.open(project_file);

  if (ProjectFile.is_open()) {
    std::cout << "///// Loading Project Configuration: " << std::endl;
    ProjectFile.close();
    nptool::InputParser parser(project_file);
    std::vector<BlockPtr> blocks = parser.GetAllBlocksWithToken("project");
    unsigned int size = blocks.size();
    for (unsigned int i = 0; i < size; i++) {
      if (blocks[i]->HasToken("default flag")) {
        ReadArgument(blocks[i]->GetString("default flag"));
      }

      if (app_name == "npconversion") {
        if (blocks[i]->HasToken("conversion output")) {
          m_ConversionOutputPath = blocks[i]->GetString("conversion output");
          if (m_ConversionOutputPath.back() != '/')
            m_ConversionOutputPath += "/";
        }

        if (blocks[i]->HasToken("default convertion flag")) {
          ReadArgument(blocks[i]->GetString("default simulation flag"));
        }
      }

      else if (app_name == "npanalysis") {
        if (blocks[i]->HasToken("analysis output")) {
          m_AnalysisOutputPath = blocks[i]->GetString("analysis output");
          if (m_AnalysisOutputPath.back() != '/')
            m_AnalysisOutputPath += "/";
        }

        if (blocks[i]->HasToken("default analysis flag")) {
          ReadArgument(blocks[i]->GetString("default analysis flag"));
        }
      }

      else if (app_name == "npsimulation") {
        if (blocks[i]->HasToken("default simulation flag"))
          ReadArgument(blocks[i]->GetString("default simulation flag"));

        if (blocks[i]->HasToken("simulation output")) {
          m_SimulationOutputPath = blocks[i]->GetString("simulation output");
          if (m_SimulationOutputPath.back() != '/')
            m_SimulationOutputPath += "/";
        }

        if (blocks[i]->HasToken("energy loss")) {
          m_EnergyLossPath = blocks[i]->GetString("energy loss");
          if (m_EnergyLossPath.back() != '/')
            m_EnergyLossPath += "/";
        }
      }

      else if (app_name == "nponline") {
        if (blocks[i]->HasToken("default online flag")) {
          ReadArgument(blocks[i]->GetString("default online flag"));
        }
        else if (blocks[i]->HasToken("online macro")) {
          m_OnlineMacroPath = blocks[i]->GetString("online macro");
        }
      }

      else {
        if (blocks[i]->HasToken("default output")) {
          m_DefaultOutputPath = blocks[i]->GetString("default output");
          if (m_DefaultOutputPath.back() != '/')
            m_DefaultOutputPath += "/";
        }
      }
    }
  }
}
void OptionManager::ReadArgument(int argc, char** argv) {

  m_argc = argc;
  m_argv = argv;

  for (int i = 1; i < argc; i++) {
    // argument start with a "-"
    if (strncmp(argv[i], "-", 1) == 0) {

      if (i == argc - 1) { // last element of argv
        m_option[argv[i]] = "_void_";
        m_used[argv[i]] = 0;
      }

      else if (strncmp(argv[i + 1], "-", 1) == 0) { // next argv element is a flag
        m_option[argv[i]] = "_void_";
        m_used[argv[i]] = 0;
      }

      else { // next argv element is an arg
        m_option[argv[i]] = argv[i + 1];
        m_used[argv[i]] = 0;
      }
    }
  }
}

OptionManager::OptionManager(int argc, char** argv) {
  // Start by reading the project configuration
  ReadArgument(argc, argv);
}
OptionManager::OptionManager(std::string arg) { ReadArgument(arg); }

void OptionManager::ReadArgument(std::string arg) {

  // add dummy string in front of arg string
  arg.insert(0, "ignore ");

  std::vector<char*> args;
  std::stringstream iss(arg);

  std::string token;
  while (iss >> token) {
    char* argument = new char[token.size() + 1];
    copy(token.begin(), token.end(), argument);
    argument[token.size()] = '\0';
    args.push_back(argument);
  }
  args.push_back(0);

  ReadArgument(args.size() - 1, &args[0]);
}

void OptionManager::DisplayHelp() {
  // exit current program
  exit(0);
}

bool nptool::OptionManager::HasFlag(std::string flag) {
  auto it = m_option.find(flag);
  if (it != m_option.end()) {
    m_used[it->first] = 1;
    return true;
  }
  else
    return false;
}

std::string nptool::OptionManager::GetArg(std::string flag) {
  auto it = m_option.find(flag);
  if (it != m_option.end()) {
    if (strcmp(it->second.c_str(), "_void_")) {
      m_used[it->first] = 1;
      return it->second;
    }
    else {
      std::string msg = "Flag \"" + flag + "\" was provided with no <arg> ";
      throw(nptool::Error("OptionManager", msg));
    }
  }
  else {
    std::string msg = "Requesting unvailable flag \"" + flag + "\"";
    throw(nptool::Error("OptionManager", msg));
  }
}

std::vector<std::string> nptool::OptionManager::GetVectorArg(std::string flag) {
  auto it = m_option.find(flag);
  std::vector<std::string> res;

  if (it != m_option.end()) {
    m_used[it->first] = 1;
    while (auto pos = it->second.find_first_of(",")) {
      // get the element
      std::string element = it->second.substr(0, pos);
      if (strcmp(element.c_str(), "_void_") == 0) {
        std::string msg = "Flag " + flag + " was provided with no <arg> ";
        throw(nptool::Error("OptionManager", msg));
      }

      // remove the element and "," separator
      it->second.erase(0, pos + 1);
      res.push_back(element);
      if (it->second.empty() || pos == std::string::npos)
        break;
    }
  }
  else {
    std::string msg = "Requesting unvailable flag " + flag;
    throw(nptool::Error("OptionManager", msg));
  }

  return res;
}

int nptool::OptionManager::GetIntArg(std::string flag) { return atoi(GetArg(flag).c_str()); }
std::vector<std::string> nptool::OptionManager::ListIgnoredFlag() {
  std::vector<std::string> res;
  for (auto it = m_used.begin(); it != m_used.end(); it++) {
    if (it->second == 0)
      res.push_back(it->first);
  }
  return res;
}
unsigned int nptool::OptionManager::NumberOfFlags() { return m_option.size(); }

void nptool::OptionManager::PrintIgnoredFlag() {
  std::vector<std::string> ignored = ListIgnoredFlag();
  std::string msg = "list of ignored flag: ";
  unsigned int size = ignored.size();
  if (size) {
    for (unsigned int i = 0; i < size; i++) {
      msg += ignored[i] + " ";
    }
  }
  if (size)
    message("yellow", "core", "nptool::OptionManager", msg);
}