void reverse_i(char s[], int lim, int i) { char tmp; if (i < lim) { reverse_i(s, lim - 1, i + 1); tmp = s[i]; s[i] = s[lim - 1]; s[lim - 1] = tmp; } }
void reverse(char s[], int lim) { reverse_i(s, lim, 0); }
SignedSize EmpiricalFormula::parseFormula_(Map<const Element *, SignedSize> & ef, const String & input_formula) const { SignedSize charge = 0; String formula(input_formula), symbol, number; // we start with the charge part, read until the begin of the formula or a element symbol occurs String suffix; for (SignedSize reverse_i(formula.size() - 1); reverse_i >= 0; --reverse_i) { if (!isalpha(formula[reverse_i])) { suffix = formula[reverse_i] + suffix; } else { break; } } // determine charge if (!suffix.empty()) { String charge_part; Size i = 1; for (; i < suffix.size(); ++i) { if (!isdigit(suffix[i])) { break; } } if (i != suffix.size()) { // we found the charge part String charge_str; for (Size j = i + 1; j < suffix.size(); ++j) { charge_str += suffix[j]; } SignedSize tmp_charge = 1; if (!charge_str.empty()) { tmp_charge = charge_str.toInt(); } if (suffix[i] == '-') { charge = -1 * tmp_charge; } else { if (suffix[i] == '+') { charge = tmp_charge; } else { throw Exception::ParseError(__FILE__, __LINE__, __PRETTY_FUNCTION__, formula, "Cannot parse charge part of formula!"); } } // now remove the charge part from the formula formula.resize(formula.size() - charge_str.size() - 1); } } if (suffix.size() == 1 && suffix[0] == '+') { charge = 1; formula.resize(formula.size() - 1); } else if (suffix.size() == formula.size()) { if (suffix.size() > 1) { if (suffix[0] == '-' || suffix[0] == '+') { charge = suffix.toInt(); return charge; } } else { if (suffix == "-") { charge = -1; return charge; } } } // split the formula vector<String> splitter; if (formula.size() > 0) { if (!isdigit(formula[0]) || formula[0] == '(') { bool is_isotope(false), is_symbol(false); String split; for (Size i = 0; i < formula.size(); ++i) { if ((isupper(formula[i]) && (!is_isotope || is_symbol)) || formula[i] == '(') { if (split != "") { splitter.push_back(split); is_isotope = false; is_symbol = false; } split = String(1, formula[i]); } else { split += String(1, formula[i]); } if (formula[i] == '(') { is_isotope = true; } if (isupper(formula[i])) { is_symbol = true; } } splitter.push_back(split); } else { throw Exception::ParseError(__FILE__, __LINE__, __PRETTY_FUNCTION__, formula, "This formula does not begin with an element!"); } } // add up the elements for (Size i = 0; i != splitter.size(); ++i) { String split = splitter[i]; String number; String symbol; bool had_symbol(false); for (SignedSize j = split.size() - 1; j >= 0; --j) { if (!had_symbol && (isdigit(split[j]) || split[j] == '-')) { number = split[j] + number; } else { symbol = split[j] + symbol; had_symbol = true; } } SignedSize num(1); if (number != "") { num = number.toInt(); } if (element_db_->hasElement(symbol)) { if (num != 0) { const Element * e = element_db_->getElement(symbol); if (ef.has(e)) { ef[e] += num; } else { ef[e] = num; } } } else { throw Exception::ParseError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "'" + split + "'", "'" + symbol + "'"); } } // remove elements with 0 counts Map<const Element *, SignedSize>::iterator it = ef.begin(); while (it != ef.end()) { if (it->second == 0) { ef.erase(it++); // Note: post increment needed! Otherwise iterator is invalidated } else { ++it; } } return charge; }