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