TEST_F(UnitsFixture,IddUnits_Grams) { IddUnitString iddString("g/m-s-K"); EXPECT_EQ("mkg/m*s*K",iddString.toStandardUnitString()); OptionalUnit unit = createUnit(iddString.toStandardUnitString()); ASSERT_TRUE(unit); EXPECT_TRUE(unit->system() == UnitSystem::SI); EXPECT_EQ(-3,unit->scale().exponent); }
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; }