Example #1
0
std::pair<std::string,std::string> decomposeScaledUnitString(const std::string& s) {
  if (!isScaledUnit(s)) {
    LOG_FREE_AND_THROW("openstudio.QuantityRegex","Cannot decompose " << s
      << " into a scale and a compound unit because it is not a scaled unit.");
  }

  std::pair<std::string,std::string> result;
  boost::match_results<std::string::const_iterator> match;
  boost::regex scaleRegex("(\\\\?[\\l\\u]{1,5})\\(");
  // pull out scale
  if (!boost::regex_search(s,match,scaleRegex,boost::match_continuous)) {
    LOG_FREE_AND_THROW("openstudio.QuantityRegex","Could not extract a scale from the scaled unit "
      << s << ".");
  }
  result.first = std::string(match[1].first,match[1].second);

  // pull out compound unit
  if (!boost::regex_search(s,match,regexEmbeddedCompoundUnit())) {
    LOG_FREE_AND_THROW("openstudio.QuantityRegex","Could not extract a compound unit from " << s << ".");
  }
  int i = 1;
  while (!match[i].matched) {++i;}
  result.second = std::string(match[1].first,match[1].second);

  return result;
}
Example #2
0
boost::optional<Unit> UnitFactorySingleton::createUnit(const std::string& unitString,
                                                       UnitSystem system) const
{
  if (m_callbackMaps.size() == 0) {
    LOG(Warn,"UnitFactorySingleton::createUnit called, but the maps appear to be empty.");
  }

  if (!unitString.empty() && !isUnit(unitString)) {
    LOG(Error,unitString << " is not properly formatted.");
    return boost::none;
  }

  OptionalUnit result = createUnitSimple(unitString,system);
  if (result) {
    return *result;
  }

  // no luck--start parsing
  std::string wUnitString(unitString);
  ScaleConstant scale = ScaleFactory::instance().createScale(0);

  if (isScaledUnit(wUnitString)) {
    std::pair<std::string,std::string> scaleAndUnit = decomposeScaledUnitString(wUnitString);
    scale = ScaleFactory::instance().createScale(scaleAndUnit.first);
    if (scale().value == 0.0) {
      LOG(Error,"Scaled unit string " << wUnitString << " uses invalid scale abbreviation "
          << scaleAndUnit.first << ".");
      return boost::none;
    }
    wUnitString = scaleAndUnit.second;
  }

  // wUnitString should now be compound unit
  std::pair< std::vector<std::string>,std::vector<std::string> > atomicUnits =
      decomposeCompoundUnitString(wUnitString);
  // loop through numerator
  std::vector<std::string>::const_iterator atomicUnitIter;
  std::vector<std::string>::const_iterator vectorEnd = atomicUnits.first.end();
  std::pair<std::string,int> atomicUnit;
  for (atomicUnitIter = atomicUnits.first.begin(); atomicUnitIter != vectorEnd; ++atomicUnitIter) {
    // decompose into baseUnit and exponent
    atomicUnit = decomposeAtomicUnitString(*atomicUnitIter);
    // look for baseUnit
    OptionalUnit baseUnit = createUnitSimple(atomicUnit.first,system);
    if (!baseUnit) {
      // decompose into scale, baseUnit
      std::pair<std::string,std::string> scaleAndBaseUnit = extractScaleAbbreviation(atomicUnit.first);
      if (!scaleAndBaseUnit.first.empty()) {
        baseUnit = createUnitSimple(scaleAndBaseUnit.second,system);
        if (!baseUnit) {
          baseUnit = Unit();
          baseUnit->setBaseUnitExponent(scaleAndBaseUnit.second,1);
        }
        baseUnit->setScale(scaleAndBaseUnit.first);
      }
      else {
        baseUnit = Unit();
        baseUnit->setBaseUnitExponent(atomicUnit.first,1);
      }
    }
    baseUnit->pow(atomicUnit.second);
    if (!result) {
      result = baseUnit;
    }
    else {
      result = (*result) * (*baseUnit);
    }
  }
  // loop through denominator
  vectorEnd = atomicUnits.second.end();
  for (atomicUnitIter = atomicUnits.second.begin(); atomicUnitIter != vectorEnd; ++atomicUnitIter) {
    // decompose into baseUnit and exponent
    atomicUnit = decomposeAtomicUnitString(*atomicUnitIter);
    // look for baseUnit
    OptionalUnit baseUnit = createUnitSimple(atomicUnit.first,system);
    if (!baseUnit) {
      // decompose into scale, baseUnit
      std::pair<std::string,std::string> scaleAndBaseUnit = extractScaleAbbreviation(atomicUnit.first);
      if (!scaleAndBaseUnit.first.empty()) {
        baseUnit = createUnitSimple(scaleAndBaseUnit.second,system);
        if (!baseUnit) {
          LOG(Info,scaleAndBaseUnit.second << " is not a registered baseUnit (in the selected system). "
              << "Returning it as-is in a mixed Unit (not SI, IP, etc.).");
          baseUnit = Unit();
          baseUnit->setBaseUnitExponent(scaleAndBaseUnit.second,1);
        }
        baseUnit->setScale(scaleAndBaseUnit.first);
      }
      else {
        LOG(Info,scaleAndBaseUnit.second << " is not a registered baseUnit (in the selected system). "
              << "Returning it as-is in a mixed Unit (not SI, IP, etc.).");
        baseUnit = Unit();
        baseUnit->setBaseUnitExponent(atomicUnit.first,1);
      }
    }
    baseUnit->pow(atomicUnit.second);
    if (!result) {
      baseUnit->pow(-1);
      result = baseUnit;
    }
    else {
      result = (*result) / (*baseUnit);
    }
  }

  BOOST_ASSERT(result);

  // impose overall scale
  if (scale().exponent != 0) {
    ScaleOpReturnType resultScale = scale()*result->scale();
    result->setScale(resultScale.first().exponent);
  }

  return result;
}