| 125 | } |
| 126 | |
| 127 | boost::optional<Unit> UnitFactory::createUnit(const std::string& unitString, UnitSystem system) const { |
| 128 | if (m_callbackMaps.empty()) { |
| 129 | LOG(Warn, "UnitFactory::createUnit called, but the maps appear to be empty."); |
| 130 | } |
| 131 | |
| 132 | std::string resultCacheKey = unitString + " in unit system " + system.valueName(); |
| 133 | auto findIt = m_resultCacheMap.find(resultCacheKey); |
| 134 | if (findIt != m_resultCacheMap.end()) { |
| 135 | return findIt->second; |
| 136 | } |
| 137 | |
| 138 | if (!unitString.empty() && !isUnit(unitString)) { |
| 139 | LOG(Error, unitString << " is not properly formatted."); |
| 140 | m_resultCacheMap[resultCacheKey] = boost::none; |
| 141 | return boost::none; |
| 142 | } |
| 143 | |
| 144 | OptionalUnit result = createUnitSimple(unitString, system); |
| 145 | if (result) { |
| 146 | m_resultCacheMap[resultCacheKey] = result; |
| 147 | return *result; |
| 148 | } |
| 149 | |
| 150 | // no luck--start parsing |
| 151 | std::string wUnitString(unitString); |
| 152 | ScaleConstant scale = ScaleFactory::instance().createScale(0); |
| 153 | |
| 154 | if (isScaledUnit(wUnitString)) { |
| 155 | std::pair<std::string, std::string> scaleAndUnit = decomposeScaledUnitString(wUnitString); |
| 156 | scale = ScaleFactory::instance().createScale(scaleAndUnit.first); |
| 157 | if (scale().value == 0.0) { |
| 158 | LOG(Error, "Scaled unit string " << wUnitString << " uses invalid scale abbreviation " << scaleAndUnit.first << "."); |
| 159 | m_resultCacheMap[resultCacheKey] = boost::none; |
| 160 | return boost::none; |
| 161 | } |
| 162 | wUnitString = scaleAndUnit.second; |
| 163 | } |
| 164 | |
| 165 | // wUnitString should now be compound unit |
| 166 | std::pair<std::vector<std::string>, std::vector<std::string>> atomicUnits = decomposeCompoundUnitString(wUnitString); |
| 167 | // loop through numerator |
| 168 | std::vector<std::string>::const_iterator atomicUnitIter; |
| 169 | auto vectorEnd = atomicUnits.first.end(); |
| 170 | std::pair<std::string, int> atomicUnit; |
| 171 | for (atomicUnitIter = atomicUnits.first.begin(); atomicUnitIter != vectorEnd; ++atomicUnitIter) { |
| 172 | // decompose into baseUnit and exponent |
| 173 | atomicUnit = decomposeAtomicUnitString(*atomicUnitIter); |
| 174 | // look for baseUnit |
| 175 | OptionalUnit baseUnit = createUnitSimple(atomicUnit.first, system); |
| 176 | if (!baseUnit) { |
| 177 | // decompose into scale, baseUnit |
| 178 | std::pair<std::string, std::string> scaleAndBaseUnit = extractScaleAbbreviation(atomicUnit.first); |
| 179 | if (!scaleAndBaseUnit.first.empty()) { |
| 180 | baseUnit = createUnitSimple(scaleAndBaseUnit.second, system); |
| 181 | if (!baseUnit) { |
| 182 | baseUnit = Unit(); |
| 183 | baseUnit->setBaseUnitExponent(scaleAndBaseUnit.second, 1); |
| 184 | } |