tool/NumberListParser.cpp
changeset 1826 ec6223c3b7ec
child 1828 651e9cfb244b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/NumberListParser.cpp	Wed Feb 24 16:27:11 2010 +0100
@@ -0,0 +1,230 @@
+/*****************************************************************************
+ *
+ *  $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::NumberList NumberListParser::parse(const char *data)
+{
+    NumberList 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) {
+                    secondNum = maximum();
+                    NumberList r = range(firstNum, secondNum);
+                    ret.splice(ret.end(), r);
+                    state = Finished;
+                } else if (isNumeric(data[i])) {
+                    secondNum = parseNumber(data, &i, size);
+                    state = SecondNumber;
+                } else if (data[i] == ',') {
+                    i++;
+                    secondNum = maximum();
+                    NumberList 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;
+
+            case SecondNumber:
+                if (i >= size) {
+                    NumberList r = range(firstNum, secondNum);
+                    ret.splice(ret.end(), r);
+                    state = Finished;
+                } else if (data[i] == ',') {
+                    i++;
+                    NumberList 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;
+}
+
+/*****************************************************************************/
+
+unsigned 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::NumberList NumberListParser::range(
+        unsigned int i,
+        unsigned int j
+        )
+{
+    NumberList ret;
+
+    if (i <= j) {
+        for (; i <= j; i++) {
+            ret.push_back(i);
+        }
+    } else {
+        for (; i >= j; i--) {
+            ret.push_back(i);
+        }
+    }
+
+    return ret;
+}
+
+/****************************************************************************/