tool/NumberListParser.cpp
changeset 1826 ec6223c3b7ec
child 1828 651e9cfb244b
equal deleted inserted replaced
1825:65781b048a47 1826:ec6223c3b7ec
       
     1 /*****************************************************************************
       
     2  *
       
     3  *  $Id$
       
     4  *
       
     5  *  Copyright (C) 2006-2009  Florian Pose, Ingenieurgemeinschaft IgH
       
     6  *
       
     7  *  This file is part of the IgH EtherCAT Master.
       
     8  *
       
     9  *  The IgH EtherCAT Master is free software; you can redistribute it and/or
       
    10  *  modify it under the terms of the GNU General Public License version 2, as
       
    11  *  published by the Free Software Foundation.
       
    12  *
       
    13  *  The IgH EtherCAT Master is distributed in the hope that it will be useful,
       
    14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
       
    16  *  Public License for more details.
       
    17  *
       
    18  *  You should have received a copy of the GNU General Public License along
       
    19  *  with the IgH EtherCAT Master; if not, write to the Free Software
       
    20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    21  *
       
    22  *  ---
       
    23  *
       
    24  *  The license mentioned above concerns the source code only. Using the
       
    25  *  EtherCAT technology and brand is only permitted in compliance with the
       
    26  *  industrial property and similar rights of Beckhoff Automation GmbH.
       
    27  *
       
    28  ****************************************************************************/
       
    29 
       
    30 #include <cstring>
       
    31 #include <sstream>
       
    32 #include <stdexcept>
       
    33 using namespace std;
       
    34 
       
    35 #include "NumberListParser.h"
       
    36 
       
    37 /*****************************************************************************/
       
    38 
       
    39 NumberListParser::NumberListParser():
       
    40     max(0U),
       
    41     hasMax(false)
       
    42 {
       
    43 }
       
    44 
       
    45 /*****************************************************************************/
       
    46 
       
    47 NumberListParser::~NumberListParser()
       
    48 {
       
    49 }
       
    50 
       
    51 /*****************************************************************************/
       
    52 
       
    53 NumberListParser::NumberList NumberListParser::parse(const char *data)
       
    54 {
       
    55     NumberList ret;
       
    56     unsigned int i = 0, size = strlen(data), firstNum = 0U, secondNum = 0U;
       
    57     typedef enum {
       
    58         SectionStart,
       
    59         FirstNumber,
       
    60         Range,
       
    61         SecondNumber,
       
    62         Finished
       
    63     } State;
       
    64     State state = SectionStart;
       
    65 
       
    66     while (state != Finished) {
       
    67         switch (state) {
       
    68             case SectionStart:
       
    69                 if (i >= size) {
       
    70                     state = Finished;
       
    71                 } else if (isNumeric(data[i])) {
       
    72                     firstNum = parseNumber(data, &i, size);
       
    73                     state = FirstNumber;
       
    74                 } else if (data[i] == '-') {
       
    75                     firstNum = 0U;
       
    76                     i++;
       
    77                     state = Range;
       
    78                 } else if (data[i] == ',') {
       
    79                     i++;
       
    80                 } else {
       
    81                     stringstream err;
       
    82                     err << "Invalid character " << data[i]
       
    83                         << " at position " << i << "in state "
       
    84                         << state << "." << endl;
       
    85                     throw runtime_error(err.str());
       
    86                 }
       
    87                 break;
       
    88 
       
    89             case FirstNumber:
       
    90                 if (i >= size) {
       
    91                     ret.push_back(firstNum);
       
    92                     state = Finished;
       
    93                 } else if (data[i] == '-') {
       
    94                     i++;
       
    95                     state = Range;
       
    96                 } else if (data[i] == ',') {
       
    97                     i++;
       
    98                     ret.push_back(firstNum);
       
    99                     state = SectionStart;
       
   100                 } else {
       
   101                     stringstream err;
       
   102                     err << "Invalid character " << data[i]
       
   103                         << " at position " << i << "in state "
       
   104                         << state << "." << endl;
       
   105                     throw runtime_error(err.str());
       
   106                 }
       
   107                 break;
       
   108 
       
   109             case Range:
       
   110                 if (i >= size) {
       
   111                     secondNum = maximum();
       
   112                     NumberList r = range(firstNum, secondNum);
       
   113                     ret.splice(ret.end(), r);
       
   114                     state = Finished;
       
   115                 } else if (isNumeric(data[i])) {
       
   116                     secondNum = parseNumber(data, &i, size);
       
   117                     state = SecondNumber;
       
   118                 } else if (data[i] == ',') {
       
   119                     i++;
       
   120                     secondNum = maximum();
       
   121                     NumberList r = range(firstNum, secondNum);
       
   122                     ret.splice(ret.end(), r);
       
   123                     state = SectionStart;
       
   124                 } else {
       
   125                     stringstream err;
       
   126                     err << "Invalid character " << data[i]
       
   127                         << " at position " << i << "in state "
       
   128                         << state << "." << endl;
       
   129                     throw runtime_error(err.str());
       
   130                 }
       
   131                 break;
       
   132 
       
   133             case SecondNumber:
       
   134                 if (i >= size) {
       
   135                     NumberList r = range(firstNum, secondNum);
       
   136                     ret.splice(ret.end(), r);
       
   137                     state = Finished;
       
   138                 } else if (data[i] == ',') {
       
   139                     i++;
       
   140                     NumberList r = range(firstNum, secondNum);
       
   141                     ret.splice(ret.end(), r);
       
   142                     state = SectionStart;
       
   143                 } else {
       
   144                     stringstream err;
       
   145                     err << "Invalid character " << data[i]
       
   146                         << " at position " << i << "in state "
       
   147                         << state << "." << endl;
       
   148                     throw runtime_error(err.str());
       
   149                 }
       
   150                 break;
       
   151 
       
   152             default:
       
   153                 {
       
   154                     stringstream err;
       
   155                     err << "Invalid state " << state << ".";
       
   156                     throw runtime_error(err.str());
       
   157                 }
       
   158         }
       
   159     }
       
   160 
       
   161     return ret;
       
   162 }
       
   163 
       
   164 /*****************************************************************************/
       
   165 
       
   166 unsigned int NumberListParser::maximum()
       
   167 {
       
   168     if (!hasMax) {
       
   169         max = getMax();
       
   170     }
       
   171 
       
   172     return max;
       
   173 }
       
   174 
       
   175 /*****************************************************************************/
       
   176 
       
   177 bool NumberListParser::isNumeric(char c)
       
   178 {
       
   179     return c >= '0' && c <= '9';
       
   180 }
       
   181 
       
   182 /*****************************************************************************/
       
   183 
       
   184 unsigned int NumberListParser::parseNumber(
       
   185         const char *data,
       
   186         unsigned int *i,
       
   187         unsigned int size
       
   188         )
       
   189 {
       
   190     unsigned int numSize = 0U, ret;
       
   191 
       
   192     while (*i + numSize < size && isNumeric(data[*i + numSize])) {
       
   193         numSize++;
       
   194     }
       
   195 
       
   196     if (numSize) {
       
   197         stringstream str;
       
   198         str << string(data + *i, numSize);
       
   199         str >> ret;
       
   200     } else {
       
   201         throw runtime_error("EOF");
       
   202     }
       
   203 
       
   204     *i = *i + numSize;
       
   205     return ret;
       
   206 }
       
   207 
       
   208 /****************************************************************************/
       
   209 
       
   210 NumberListParser::NumberList NumberListParser::range(
       
   211         unsigned int i,
       
   212         unsigned int j
       
   213         )
       
   214 {
       
   215     NumberList ret;
       
   216 
       
   217     if (i <= j) {
       
   218         for (; i <= j; i++) {
       
   219             ret.push_back(i);
       
   220         }
       
   221     } else {
       
   222         for (; i >= j; i--) {
       
   223             ret.push_back(i);
       
   224         }
       
   225     }
       
   226 
       
   227     return ret;
       
   228 }
       
   229 
       
   230 /****************************************************************************/