fp@1826: /***************************************************************************** fp@1826: * fp@1826: * $Id$ fp@1826: * fp@1826: * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH fp@1826: * fp@1826: * This file is part of the IgH EtherCAT Master. fp@1826: * fp@1826: * The IgH EtherCAT Master is free software; you can redistribute it and/or fp@1826: * modify it under the terms of the GNU General Public License version 2, as fp@1826: * published by the Free Software Foundation. fp@1826: * fp@1826: * The IgH EtherCAT Master is distributed in the hope that it will be useful, fp@1826: * but WITHOUT ANY WARRANTY; without even the implied warranty of fp@1826: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General fp@1826: * Public License for more details. fp@1826: * fp@1826: * You should have received a copy of the GNU General Public License along fp@1826: * with the IgH EtherCAT Master; if not, write to the Free Software fp@1826: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA fp@1826: * fp@1826: * --- fp@1826: * fp@1826: * The license mentioned above concerns the source code only. Using the fp@1826: * EtherCAT technology and brand is only permitted in compliance with the fp@1826: * industrial property and similar rights of Beckhoff Automation GmbH. fp@1826: * fp@1826: ****************************************************************************/ fp@1826: fp@1826: #include fp@1826: #include fp@1826: #include fp@1826: using namespace std; fp@1826: fp@1826: #include "NumberListParser.h" fp@1826: fp@1826: /*****************************************************************************/ fp@1826: fp@1826: NumberListParser::NumberListParser(): fp@1826: max(0U), fp@1826: hasMax(false) fp@1826: { fp@1826: } fp@1826: fp@1826: /*****************************************************************************/ fp@1826: fp@1826: NumberListParser::~NumberListParser() fp@1826: { fp@1826: } fp@1826: fp@1826: /*****************************************************************************/ fp@1826: fp@2010: NumberListParser::List NumberListParser::parse(const char *data) fp@2010: { fp@2010: List ret; fp@1826: unsigned int i = 0, size = strlen(data), firstNum = 0U, secondNum = 0U; fp@1826: typedef enum { fp@1826: SectionStart, fp@1826: FirstNumber, fp@1826: Range, fp@1826: SecondNumber, fp@1826: Finished fp@1826: } State; fp@1826: State state = SectionStart; fp@1826: fp@1826: while (state != Finished) { fp@1826: switch (state) { fp@1826: case SectionStart: fp@1826: if (i >= size) { fp@1826: state = Finished; fp@1826: } else if (isNumeric(data[i])) { fp@1826: firstNum = parseNumber(data, &i, size); fp@1826: state = FirstNumber; fp@1826: } else if (data[i] == '-') { fp@1826: firstNum = 0U; fp@1826: i++; fp@1826: state = Range; fp@1826: } else if (data[i] == ',') { fp@1826: i++; fp@1826: } else { fp@1826: stringstream err; fp@1826: err << "Invalid character " << data[i] fp@1826: << " at position " << i << "in state " fp@1826: << state << "." << endl; fp@1826: throw runtime_error(err.str()); fp@1826: } fp@1826: break; fp@1826: fp@1826: case FirstNumber: fp@1826: if (i >= size) { fp@1826: ret.push_back(firstNum); fp@1826: state = Finished; fp@1826: } else if (data[i] == '-') { fp@1826: i++; fp@1826: state = Range; fp@1826: } else if (data[i] == ',') { fp@1826: i++; fp@1826: ret.push_back(firstNum); fp@1826: state = SectionStart; fp@1826: } else { fp@1826: stringstream err; fp@1826: err << "Invalid character " << data[i] fp@1826: << " at position " << i << "in state " fp@1826: << state << "." << endl; fp@1826: throw runtime_error(err.str()); fp@1826: } fp@1826: break; fp@1826: fp@1826: case Range: fp@1826: if (i >= size) { fp@2010: int max = maximum(); fp@2012: // only increasing ranges if second number omitted fp@2012: if (max >= 0 && firstNum <= (unsigned int) max) { fp@2010: List r = range(firstNum, max); fp@2010: ret.splice(ret.end(), r); fp@2010: } fp@1826: state = Finished; fp@1826: } else if (isNumeric(data[i])) { fp@1826: secondNum = parseNumber(data, &i, size); fp@1826: state = SecondNumber; fp@1826: } else if (data[i] == ',') { fp@2010: int max = maximum(); fp@2010: i++; fp@2010: if (max >= 0) { fp@2010: List r = range(firstNum, max); fp@2010: ret.splice(ret.end(), r); fp@2010: } fp@2010: state = SectionStart; fp@2010: } else { fp@2010: stringstream err; fp@2010: err << "Invalid character " << data[i] fp@2010: << " at position " << i << "in state " fp@2010: << state << "." << endl; fp@2010: throw runtime_error(err.str()); fp@2010: } fp@2010: break; fp@2010: fp@2010: case SecondNumber: fp@2010: if (i >= size) { fp@2010: List r = range(firstNum, secondNum); fp@2010: ret.splice(ret.end(), r); fp@2010: state = Finished; fp@2010: } else if (data[i] == ',') { fp@2010: i++; fp@2010: List r = range(firstNum, secondNum); fp@1826: ret.splice(ret.end(), r); fp@1826: state = SectionStart; fp@1826: } else { fp@1826: stringstream err; fp@1826: err << "Invalid character " << data[i] fp@1826: << " at position " << i << "in state " fp@1826: << state << "." << endl; fp@1826: throw runtime_error(err.str()); fp@1826: } fp@1826: break; fp@1826: fp@1826: default: fp@1826: { fp@1826: stringstream err; fp@1826: err << "Invalid state " << state << "."; fp@1826: throw runtime_error(err.str()); fp@1826: } fp@1826: } fp@1826: } fp@1826: fp@1826: return ret; fp@1826: } fp@1826: fp@1826: /*****************************************************************************/ fp@1826: fp@2010: int NumberListParser::maximum() fp@1826: { fp@1826: if (!hasMax) { fp@1826: max = getMax(); fp@1826: } fp@1826: fp@1826: return max; fp@1826: } fp@1826: fp@1826: /*****************************************************************************/ fp@1826: fp@1826: bool NumberListParser::isNumeric(char c) fp@1826: { fp@1826: return c >= '0' && c <= '9'; fp@1826: } fp@1826: fp@1826: /*****************************************************************************/ fp@1826: fp@1826: unsigned int NumberListParser::parseNumber( fp@1826: const char *data, fp@1826: unsigned int *i, fp@1826: unsigned int size fp@1826: ) fp@1826: { fp@1826: unsigned int numSize = 0U, ret; fp@1826: fp@1826: while (*i + numSize < size && isNumeric(data[*i + numSize])) { fp@1826: numSize++; fp@1826: } fp@1826: fp@1826: if (numSize) { fp@1826: stringstream str; fp@1826: str << string(data + *i, numSize); fp@1826: str >> ret; fp@1826: } else { fp@1826: throw runtime_error("EOF"); fp@1826: } fp@1826: fp@1826: *i = *i + numSize; fp@1826: return ret; fp@1826: } fp@1826: fp@1826: /****************************************************************************/ fp@1826: fp@2010: NumberListParser::List NumberListParser::range( fp@1826: unsigned int i, fp@1826: unsigned int j fp@1826: ) fp@1826: { fp@2010: List ret; fp@1826: fp@1826: if (i <= j) { fp@1826: for (; i <= j; i++) { fp@1826: ret.push_back(i); fp@1826: } fp@1826: } else { fp@1828: for (; j <= i; j++) { fp@1828: ret.push_front(j); fp@1826: } fp@1826: } fp@1826: fp@1826: return ret; fp@1826: } fp@1826: fp@1826: /****************************************************************************/