<commit_before>// Copyright (C) 2014 - 2016 by <NAME>, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

#include <math.h>
#include <string.h>
#include <algorithm>

#include "copasi/report/CCopasiRootContainer.h"
#include "copasi/utilities/CUnitDefinition.h"
#include "copasi/utilities/CUnit.h"
#include "copasi/utilities/CUnitParser.h"
#include "copasi/model/CModel.h"
#include "copasi/xml/CCopasiXMLInterface.h"
#include "copasi/utilities/CUnitParser.h"

#include "CCopasiException.h"

// static
C_FLOAT64 CUnit::Avogadro(6.022140857e23); // http://physics.nist.gov/cgi-bin/cuu/Value?na (Thu Feb 11 09:57:27 EST 2016)

const char * CUnit::VolumeUnitNames[] =
{"dimensionless", "m\xc2\xb3", "l", "ml", "\xc2\xb5l", "nl", "pl", "fl", NULL};

const char * CUnit::AreaUnitNames[] =
{"dimensionless", "m\xc2\xb2", "dm\xc2\xb2", "cm\xc2\xb2", "mm\xc2\xb2", "\xc2\xb5m\xc2\xb2", "nm\xc2\xb2", "pm\xc2\xb2", "fm\xc2\xb2", NULL};

const char * CUnit::LengthUnitNames[] =
{"dimensionless", "m", "dm", "cm", "mm", "\xc2\xb5m", "nm", "pm", "fm", NULL};

const char * CUnit::TimeUnitNames[] =
{"dimensionless", "d", "h", "min", "s", "ms", "\xc2\xb5s", "ns", "ps", "fs", NULL};

// "mol" is the correct name, however in the COPASI XML files "Mol" is used
// up to build 18

const char * CUnit::QuantityUnitOldXMLNames[] =
{"dimensionless", "Mol", "mMol", "\xc2\xb5Mol", "nMol", "pMol", "fMol", "#", NULL};

const char * CUnit::QuantityUnitNames[] =
{"dimensionless", "mol", "mmol", "\xc2\xb5mol", "nmol", "pmol", "fmol", "#", NULL};

// static
std::string CUnit::replaceSymbol(const std::string & expression,
                                 const std::string & oldSymbol,
                                 const std::string & newSymbol)
{
  if (oldSymbol == newSymbol)
    return expression;

  std::istringstream buffer(expression);

  CUnitParser Parser(&buffer);
  Parser.setAvogadro(CUnit::Avogadro);
  Parser.replaceSymbol(oldSymbol, newSymbol);

  return (Parser.yyparse() == 0) ? Parser.getReplacedExpression() : expression;
}

// constructors
// default
CUnit::CUnit():
  mExpression(""),
  mComponents(),
  mUsedSymbols()
{
}

// expression
CUnit::CUnit(std::string expression,
             const C_FLOAT64 & avogadro):
  mExpression(""),
  mComponents(),
  mUsedSymbols()
{
  setExpression(expression, avogadro);
}

// kind
CUnit::CUnit(const CBaseUnit::Kind & kind):
  mExpression(CBaseUnit::getSymbol(kind)),
  mComponents(),
  mUsedSymbols()
{
  mComponents.insert(CUnitComponent(kind));
  consolidateDimensionless();
}

// copy constructor
CUnit::CUnit(const CUnit & src):
  mExpression(src.mExpression),
  mComponents(src.mComponents),
  mUsedSymbols(src.mUsedSymbols)
{
  consolidateDimensionless();
}

CUnit::~CUnit()
{}

bool CUnit::setExpression(const std::string & expression,
                          const C_FLOAT64 & avogadro)
{
  mExpression = expression;

  if (expression.empty())
    {
      mComponents.clear();
      return true;
    }

  return compile(avogadro);
}

bool CUnit::compile(const C_FLOAT64 & avogadro)
{
  mComponents.clear();
  mUsedSymbols.clear();

  std::istringstream buffer(mExpression);
  CUnitParser Parser(&buffer);
  Parser.setAvogadro(avogadro);

  bool success = (Parser.yyparse() == 0);

  if (success)
    {
      mComponents = Parser.getComponents();
      mUsedSymbols = Parser.getSymbols();
    }

  return success;
}

std::string CUnit::getExpression() const
{
  return mExpression;
}

const std::set< std::string > & CUnit::getUsedSymbols() const
{
  return mUsedSymbols;
}

bool CUnit::isDimensionless() const
{
  // Components are a set of unique Kinds.
  // consolodateDimensionless() should ensure any zero-exponent
  // components are integrated into a single, dimensionless, one.
  // So the following should work to retrieve if a unit is dimensionless,
  // but not undefined (no components).
  if (mComponents.size() == 1 &&
      (*mComponents.begin()).getKind() == CBaseUnit::dimensionless)
    return true;
  else
    return false;
}
<commit_msg>Handle parser exceptions in CUnit::compile (short circuit return false). Otherwise ok to update mComponents, mUsedSymbols, and return true.<commit_after>// Copyright (C) 2014 - 2016 by <NAME>, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

#include <math.h>
#include <string.h>
#include <algorithm>

#include "copasi/report/CCopasiRootContainer.h"
#include "copasi/utilities/CUnitDefinition.h"
#include "copasi/utilities/CUnit.h"
#include "copasi/utilities/CUnitParser.h"
#include "copasi/model/CModel.h"
#include "copasi/xml/CCopasiXMLInterface.h"
#include "copasi/utilities/CUnitParser.h"

#include "CCopasiException.h"

// static
C_FLOAT64 CUnit::Avogadro(6.022140857e23); // http://physics.nist.gov/cgi-bin/cuu/Value?na (Thu Feb 11 09:57:27 EST 2016)

const char * CUnit::VolumeUnitNames[] =
{"dimensionless", "m\xc2\xb3", "l", "ml", "\xc2\xb5l", "nl", "pl", "fl", NULL};

const char * CUnit::AreaUnitNames[] =
{"dimensionless", "m\xc2\xb2", "dm\xc2\xb2", "cm\xc2\xb2", "mm\xc2\xb2", "\xc2\xb5m\xc2\xb2", "nm\xc2\xb2", "pm\xc2\xb2", "fm\xc2\xb2", NULL};

const char * CUnit::LengthUnitNames[] =
{"dimensionless", "m", "dm", "cm", "mm", "\xc2\xb5m", "nm", "pm", "fm", NULL};

const char * CUnit::TimeUnitNames[] =
{"dimensionless", "d", "h", "min", "s", "ms", "\xc2\xb5s", "ns", "ps", "fs", NULL};

// "mol" is the correct name, however in the COPASI XML files "Mol" is used
// up to build 18

const char * CUnit::QuantityUnitOldXMLNames[] =
{"dimensionless", "Mol", "mMol", "\xc2\xb5Mol", "nMol", "pMol", "fMol", "#", NULL};

const char * CUnit::QuantityUnitNames[] =
{"dimensionless", "mol", "mmol", "\xc2\xb5mol", "nmol", "pmol", "fmol", "#", NULL};

// static
std::string CUnit::replaceSymbol(const std::string & expression,
                                 const std::string & oldSymbol,
                                 const std::string & newSymbol)
{
  if (oldSymbol == newSymbol)
    return expression;

  std::istringstream buffer(expression);

  CUnitParser Parser(&buffer);
  Parser.setAvogadro(CUnit::Avogadro);
  Parser.replaceSymbol(oldSymbol, newSymbol);

  return (Parser.yyparse() == 0) ? Parser.getReplacedExpression() : expression;
}

// constructors
// default
CUnit::CUnit():
  mExpression(""),
  mComponents(),
  mUsedSymbols()
{
}

// expression
CUnit::CUnit(std::string expression,
             const C_FLOAT64 & avogadro):
  mExpression(""),
  mComponents(),
  mUsedSymbols()
{
  setExpression(expression, avogadro);
}

// kind
CUnit::CUnit(const CBaseUnit::Kind & kind):
  mExpression(CBaseUnit::getSymbol(kind)),
  mComponents(),
  mUsedSymbols()
{
  mComponents.insert(CUnitComponent(kind));
  consolidateDimensionless();
}

// copy constructor
CUnit::CUnit(const CUnit & src):
  mExpression(src.mExpression),
  mComponents(src.mComponents),
  mUsedSymbols(src.mUsedSymbols)
{
  consolidateDimensionless();
}

CUnit::~CUnit()
{}

bool CUnit::setExpression(const std::string & expression,
                          const C_FLOAT64 & avogadro)
{
  mExpression = expression;

  if (expression.empty())
    {
      mComponents.clear();
      return true;
    }

  return compile(avogadro);
}

bool CUnit::compile(const C_FLOAT64 & avogadro)
{
  mComponents.clear();
  mUsedSymbols.clear();

  std::istringstream buffer(mExpression);
  CUnitParser Parser(&buffer);
  Parser.setAvogadro(avogadro);

  try
    {
      Parser.yyparse();
    }
  catch (CCopasiException & /*exception*/)
    {
      return false;
    }

  mComponents = Parser.getComponents();
  mUsedSymbols = Parser.getSymbols();

  return true;
}

std::string CUnit::getExpression() const
{
  return mExpression;
}

const std::set< std::string > & CUnit::getUsedSymbols() const
{
  return mUsedSymbols;
}

bool CUnit::isDimensionless() const
{
  // Components are a set of unique Kinds.
  // consolodateDimensionless() should ensure any zero-exponent
  // components are integrated into a single, dimensionless, one.
  // So the following should work to retrieve if a unit is dimensionless,
  // but not undefined (no components).
  if (mComponents.size() == 1 &&
      (*mComponents.begin()).getKind() == CBaseUnit::dimensionless)
    return true;
  else
    return false;
}

{'fraction_non_alphanumeric': 0.1641719554544366, 'fraction_numerical': 0.017842174589869475, 'mean_word_length': 4.1113831089351285, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4792426', 'n_tokens_mistral': 3007, 'n_tokens_neox': 2882, 'n_words': 642}