diff options
| author | Bent Bisballe Nyeng <deva@aasimon.org> | 2015-05-22 08:30:24 +0200 | 
|---|---|---|
| committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2015-05-22 08:30:24 +0200 | 
| commit | 6e3b53cd1b0fc6dcd721fac3beb699cb722e1e23 (patch) | |
| tree | 567ca7e5d3e4df0ccda74768967f5f8434a19666 /src | |
| parent | d7e31edc42e075567059c2ddcda6bb19b4c7bd69 (diff) | |
Add error handling in ConfigFile parser.
Diffstat (limited to 'src')
| -rw-r--r-- | src/configfile.cc | 287 | ||||
| -rw-r--r-- | src/configfile.h | 5 | 
2 files changed, 155 insertions, 137 deletions
| diff --git a/src/configfile.cc b/src/configfile.cc index e659a51..6b0d14f 100644 --- a/src/configfile.cc +++ b/src/configfile.cc @@ -108,10 +108,12 @@ ConfigFile::~ConfigFile()  {  } -void ConfigFile::load() +bool ConfigFile::load()  {    DEBUG(configfile, "Loading config file...\n"); -  if(!open("r")) return; +  if(!open("r")) { +    return false; +  }    values.clear(); @@ -120,150 +122,26 @@ void ConfigFile::load()      line = readLine();      if(line == "") break; - -    if(line[line.size() - 1] == '\n') { -      line = line.substr(0, line.size() - 1); // strip ending newline. -    } - -    std::string key; -    std::string value; -    enum { -      before_key, -      in_key, -      after_key, -      before_value, -      in_value, -      in_value_single_quoted, -      in_value_double_quoted, -      after_value, -    } state = before_key; - -    for(std::size_t p = 0; p < line.size(); ++p) { -      switch(state) { -      case before_key: -        if(line[p] == '#') { -          // Comment: Ignore line. -          p = line.size(); -          continue; -        } -        if(std::isspace(line[p])) { -          continue; -        } -        key += line[p]; -        state = in_key; -        break; - -      case in_key: -        if(std::isspace(line[p])) { -          state = after_key; -          continue; -        } -        if(line[p] == ':' || line[p] == '=') { -          state = before_value; -          continue; -        } -        key += line[p]; -        break; - -      case after_key: -        if(std::isspace(line[p])) { -          continue; -        } -        if(line[p] == ':' || line[p] == '=') { -          state = before_value; -          continue; -        } -        // ERROR: Bad symbol, expecting only whitespace or key/value seperator -        break; - -      case before_value: -        if(std::isspace(line[p])) { -          continue; -        } -        if(line[p] == '\'') { -          state = in_value_single_quoted; -          continue; -        } -        if(line[p] == '"') { -          state = in_value_double_quoted; -          continue; -        } -        value += line[p]; -        state = in_value; -        break; - -      case in_value: -        if(std::isspace(line[p])) { -          state = after_value; -          continue; -        } -        if(line[p] == '#') { -          // Comment: Ignore the rest of the line. -          p = line.size(); -          state = after_value; -          continue; -        } -        value += line[p]; -        break; - -      case in_value_single_quoted: -        if(line[p] == '\'') { -          state = after_value; -          continue; -        } -        value += line[p]; -        break; - -      case in_value_double_quoted: -        if(line[p] == '"') { -          state = after_value; -          continue; -        } -        value += line[p]; -        break; - -      case after_value: -        if(std::isspace(line[p])) { -          continue; -        } -        if(line[p] == '#') { -          // Comment: Ignore the rest of the line. -          p = line.size(); -          continue; -        } -        // ERROR: Bad symbol, expecting only whitespace or key/value seperator -        break; -      } -    } - -    if(state == before_key) { -      // Line did not contain any data (empty or comment) -      continue; -    } - -    // If state == in_value_XXX_quoted here, the string was not terminated. -    if(state != after_value && state != in_value) { -      // ERROR: Malformed line. -      break; -    } - -    DEBUG(configfile, "key['%s'] value['%s']\n", key.c_str(), value.c_str()); - -    if(key != "") { -      values[key] = value; +     +    if(!parseLine(line)) { +      return false;      }    }    close(); + +  return true;  } -void ConfigFile::save() +bool ConfigFile::save()  {    DEBUG(configfile, "Saving configuration...\n");    createConfigPath(); -  if(!open("w")) return; +  if(!open("w")) { +    return false; +  }    std::map<std::string, std::string>::iterator v = values.begin();    for(; v != values.end(); ++v) { @@ -271,6 +149,8 @@ void ConfigFile::save()    }    close(); + +  return true;  }  std::string ConfigFile::getValue(const std::string& key) @@ -328,3 +208,140 @@ std::string ConfigFile::readLine()    return line;  } + +bool ConfigFile::parseLine(const std::string& line) +{ +  std::string key; +  std::string value; +  enum { +    before_key, +    in_key, +    after_key, +    before_value, +    in_value, +    in_value_single_quoted, +    in_value_double_quoted, +    after_value, +  } state = before_key; + +  for(std::size_t p = 0; p < line.size(); ++p) { +    switch(state) { +    case before_key: +      if(line[p] == '#') { +        // Comment: Ignore line. +        p = line.size(); +        continue; +      } +      if(std::isspace(line[p])) { +        continue; +      } +      key += line[p]; +      state = in_key; +      break; + +    case in_key: +      if(std::isspace(line[p])) { +        state = after_key; +        continue; +      } +      if(line[p] == ':' || line[p] == '=') { +        state = before_value; +        continue; +      } +      key += line[p]; +      break; + +    case after_key: +      if(std::isspace(line[p])) { +        continue; +      } +      if(line[p] == ':' || line[p] == '=') { +        state = before_value; +        continue; +      } +      ERR(configfile, "Bad symbol." +            " Expecting only whitespace or key/value seperator: '%s'", +            line.c_str()); +      return false; + +    case before_value: +      if(std::isspace(line[p])) { +        continue; +      } +      if(line[p] == '\'') { +        state = in_value_single_quoted; +        continue; +      } +      if(line[p] == '"') { +        state = in_value_double_quoted; +        continue; +      } +      value += line[p]; +      state = in_value; +      break; + +    case in_value: +      if(std::isspace(line[p])) { +        state = after_value; +        continue; +      } +      if(line[p] == '#') { +        // Comment: Ignore the rest of the line. +        p = line.size(); +        state = after_value; +        continue; +      } +      value += line[p]; +      break; + +    case in_value_single_quoted: +      if(line[p] == '\'') { +        state = after_value; +        continue; +      } +      value += line[p]; +      break; + +    case in_value_double_quoted: +      if(line[p] == '"') { +        state = after_value; +        continue; +      } +      value += line[p]; +      break; + +    case after_value: +      if(std::isspace(line[p])) { +        continue; +      } +      if(line[p] == '#') { +        // Comment: Ignore the rest of the line. +        p = line.size(); +        continue; +      } +      ERR(configfile, "Bad symbol." +            " Expecting only whitespace or key/value seperator: '%s'", +            line.c_str()); +      return false; +    } +  } + +  if(state == before_key) { +    // Line did not contain any data (empty or comment) +    return true; +  } + +  // If state == in_value_XXX_quoted here, the string was not terminated. +  if(state != after_value && state != in_value) { +    ERR(configfile,"Malformed line: '%s'", line.c_str()); +    return false; +  } + +  DEBUG(configfile, "key['%s'] value['%s']\n", key.c_str(), value.c_str()); + +  if(key != "") { +    values[key] = value; +  } + +  return true; +} diff --git a/src/configfile.h b/src/configfile.h index a3fd588..a6c50bd 100644 --- a/src/configfile.h +++ b/src/configfile.h @@ -36,8 +36,8 @@ public:    ConfigFile(std::string filename);    virtual ~ConfigFile(); -  virtual void load(); -  virtual void save(); +  virtual bool load(); +  virtual bool save();    virtual std::string getValue(const std::string& key);    virtual void setValue(const std::string& key, const std::string& value); @@ -49,6 +49,7 @@ protected:    virtual bool open(std::string mode);    void close();    std::string readLine(); +  bool parseLine(const std::string& line);    FILE* fp;  }; | 
