boost::optional<Unit> UnitFactorySingleton::createUnitSimple(const std::string& unitString, UnitSystem system) const { if (unitString.empty()) { Unit result = createDimensionlessUnit(system); if (OptionalTemperatureUnit T = result.optionalCast<TemperatureUnit>()) { T->setAsRelative(); } return result; } OptionalUnit candidate; StandardStringLookupMap::const_iterator lookupPair; StandardStringLookupMap::const_iterator standardStringMapEnd = m_standardStringLookupMap.end(); lookupPair = m_standardStringLookupMap.find(unitString); if (lookupPair != standardStringMapEnd) { // unitString is registered BOOST_FOREACH(const std::string& standardString, lookupPair->second) { // instantiate the standardString CallbackMapMap::const_iterator callbackMap; StandardStringCallbackMap::const_iterator callbackPair; OptionalUnit temp; // try base map callbackMap = m_callbackMaps.find(UnitSystem(UnitSystem::Mixed)); BOOST_ASSERT(callbackMap != m_callbackMaps.end()); callbackPair = callbackMap->second.find(standardString); if ((callbackPair != callbackMap->second.end()) && (callbackPair->second != NULL)) { temp = callbackPair->second(); } else { // try system map callbackMap = m_callbackMaps.find(system); if (callbackMap != m_callbackMaps.end()) { callbackPair = callbackMap->second.find(standardString); if ((callbackPair != callbackMap->second.end()) && (callbackPair->second != NULL)) { temp = callbackPair->second(); } } // try all other maps if (!temp) { BOOST_FOREACH(int sysValue, UnitSystem::getValues()) { UnitSystem tempSystem(sysValue); if ((tempSystem == UnitSystem::Mixed) || (tempSystem == system)) { continue; } callbackMap = m_callbackMaps.find(tempSystem); if (callbackMap != m_callbackMaps.end()) { callbackPair = callbackMap->second.find(standardString); if ((callbackPair != callbackMap->second.end()) && (callbackPair->second != NULL)) { temp = callbackPair->second(); break; } } } } }
boost::optional<Quantity> QuantityConverterSingleton::m_convertToSI(const Quantity &original) const { // create a working copy of the original Quantity working(original); // Make sure to work unscaled: 10^0 int scaleExponent = working.scale().exponent; if (working.scale().exponent != 0) { working.setScale(0); } // build a result quantity with SI units and value equal to original Quantity result(working.value(), UnitSystem(UnitSystem::SI)); // Get the base units of original std::vector<std::string> baseOfOriginal = original.baseUnits(); // Loop over base units in original and apply conversions found in m_toSImap std::vector<std::string>::const_iterator it = baseOfOriginal.begin(); std::vector<std::string>::const_iterator end = baseOfOriginal.end(); while( it != end ) { int baseExponent = working.baseUnitExponent(*it); // apply conversion factor BaseUnitConversionMap::const_iterator mapItr = m_toSImap.find(*it); if (mapItr == m_toSImap.end()) { LOG(Error,"Cannot convert base unit '" << *it << "' to SI because it is not " << "registered with the QuantityConverter."); return boost::none; } baseUnitConversionFactor factor = mapItr->second; if (factor.offset != 0.0) { for( int i = 0; i < std::abs(baseExponent); ++i) { if( baseExponent > 0 ){ result.setValue( (result.value() * factor.factor) + factor.offset); }else { result.setValue( (result.value() / factor.factor) + factor.offset); } } } else { result.setValue( result.value() * std::pow(factor.factor,baseExponent) ); } // Parse the conversion string in case the original converts to more than one SI base unit Unit targetBase = parseUnitString(factor.targetUnit); std::vector<std::string> targetStrings = targetBase.baseUnits(); std::vector<std::string>::const_iterator targetItr = targetStrings.begin(); std::vector<std::string>::const_iterator targetEnd = targetStrings.end(); while( targetItr != targetEnd ) { int exp = targetBase.baseUnitExponent( *targetItr ); if( exp != 0 ) { result.setBaseUnitExponent(*targetItr,result.baseUnitExponent(*targetItr) + baseExponent*exp); } ++targetItr; }//End while( convItr != convEnd ) ++it; }//End while( it != end ) // Set result scale to match original scale if( scaleExponent != 0 ) { result.setScale(scaleExponent); } // Check if there is a pretty string for the result std::string pretty = UnitFactory::instance().lookupPrettyString( result.standardUnitsString(false) ); if( !(pretty.empty()) ) { result.setPrettyUnitsString( pretty ); } return result; }