char * construct_next_attribute( char * (*get_attribute)(char *, unsigned int ) ) { unsigned int start_position = eat_whitespaces( current_position ); if ( start_position == strlen( attributes_line ) ) return NULL; current_position = eat_not_whitespaces( start_position ); return get_attribute( attributes_line + start_position, current_position - start_position ); }
// Try to consume characters from the input stream and match the // pattern string. Leading whitespaces from the input are ignored if // ignore_ws is true. bool match(const std::string& pattern, std::istream& input, bool ignore_ws) { if (ignore_ws) { eat_whitespaces(input); } std::string::const_iterator cur(pattern.begin()); char ch(0); while(input && !input.eof() && cur != pattern.end()) { input.get(ch); if (ch != *cur) { input.putback(ch); return false; } else { cur++; } } return cur == pattern.end(); }
bool parse_number(std::istream& input, long* value) { eat_whitespaces(input); char ch; std::string value_str; std::string exp_str; // whole exp part std::string exp_value_str; // value of exp part int sign = 1; int e_sign = 1; bool correct = true; long e_value; enum { p_number, p_e, p_enumber } p_state = p_number; if (match("-", input)) { sign = -1; } else { match("+", input); } while(input && !input.eof()) { input.get(ch); switch (p_state) { case p_number: { // DBG("st = p_number, ch=%c\n",ch); if (ch == 'E' || ch == 'e') { exp_str.push_back(ch); p_state = p_e; continue; } if (!isdigit(ch)) { input.putback(ch); correct = false; break; } value_str.push_back(ch); } break; case p_e: { // DBG("st = p_e, ch=%c\n",ch); if (ch == '+') { exp_str.push_back(ch); p_state = p_enumber; } else if (ch == '-') { e_sign = -1; exp_str.push_back(ch); p_state = p_enumber; } else if (isdigit(ch)) { exp_value_str.push_back(ch); exp_str.push_back(ch); p_state = p_enumber; } else { input.putback(ch); correct = false; } } break; case p_enumber: { // DBG("st = p_enumber, ch=%c\n",ch); if (isdigit(ch)) { exp_value_str.push_back(ch); exp_str.push_back(ch); } else { input.putback(ch); correct = false; } } break; } if (!correct) break; } if (p_state == p_e) { // todo: check also some other error states for (std::string::reverse_iterator r_it= exp_str.rbegin(); r_it != exp_str.rend(); r_it++) input.putback(*r_it); for (std::string::reverse_iterator r_it= value_str.rbegin(); r_it != value_str.rend(); r_it++) input.putback(*r_it); return false; } if (value_str.size() > 0) { std::istringstream(value_str) >> *value; *value*=sign; if (exp_value_str.size()) { std::istringstream(exp_value_str) >> e_value; if (e_value && e_sign==-1) { // should have been catched by parse_float for (std::string::reverse_iterator r_it= exp_str.rbegin(); r_it != exp_str.rend(); r_it++) input.putback(*r_it); for (std::string::reverse_iterator r_it= value_str.rbegin(); r_it != value_str.rend(); r_it++) input.putback(*r_it); return false; } *value *= pow(10, e_value); }