diff options
author | Chris Robinson <[email protected]> | 2019-12-14 17:26:58 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2019-12-14 17:26:58 -0800 |
commit | ad9584acc32fb861824358d7df9a37ed5e7ae362 (patch) | |
tree | d44985c50f431744e116d4e7f61b6eeab7bc84e4 | |
parent | ac7a5dcbfa7d913af9ef705a99e146bfcb290b41 (diff) |
Avoid sscanf for parsing config lines
-rw-r--r-- | alc/alconfig.cpp | 73 |
1 files changed, 37 insertions, 36 deletions
diff --git a/alc/alconfig.cpp b/alc/alconfig.cpp index ede39156..dfafa231 100644 --- a/alc/alconfig.cpp +++ b/alc/alconfig.cpp @@ -224,35 +224,28 @@ void LoadConfigFromFile(std::istream &f) continue; } - auto cmtpos = buffer.find('#'); - if(cmtpos != std::string::npos) - buffer.resize(cmtpos); - while(!buffer.empty() && std::isspace(buffer.back())) - buffer.pop_back(); - if(buffer.empty()) continue; - - const char *line{&buffer[0]}; - char key[256]{}; - char value[256]{}; - if(std::sscanf(line, "%255[^=] = \"%255[^\"]\"", key, value) == 2 || - std::sscanf(line, "%255[^=] = '%255[^\']'", key, value) == 2 || - std::sscanf(line, "%255[^=] = %255[^\n]", key, value) == 2) + auto cmtpos = std::min(buffer.find('#'), buffer.size()); + while(cmtpos > 0 && std::isspace(buffer[cmtpos-1])) + --cmtpos; + if(!cmtpos) continue; + buffer.erase(cmtpos); + + auto sep = buffer.find('='); + if(sep == std::string::npos) { - /* sscanf doesn't handle '' or "" as empty values, so clip it - * manually. */ - if(std::strcmp(value, "\"\"") == 0 || std::strcmp(value, "''") == 0) - value[0] = 0; + ERR(" config parse error: malformed option line: \"%s\"\n", buffer.c_str()); + continue; } - else if(std::sscanf(line, "%255[^=] %255[=]", key, value) == 2) + auto keyend = sep++; + while(keyend > 0 && std::isspace(buffer[keyend-1])) + --keyend; + if(!keyend) { - /* Special case for 'key =' */ - value[0] = 0; - } - else - { - ERR(" config parse error: malformed option line: \"%s\"\n\n", line); + ERR(" config parse error: malformed option line: \"%s\"\n", buffer.c_str()); continue; } + while(sep < buffer.size() && std::isspace(buffer[sep])) + sep++; std::string fullKey; if(!curSection.empty()) @@ -260,26 +253,34 @@ void LoadConfigFromFile(std::istream &f) fullKey += curSection; fullKey += '/'; } - fullKey += key; - while(!fullKey.empty() && std::isspace(fullKey.back())) - fullKey.pop_back(); + fullKey += buffer.substr(0u, keyend); + + std::string value{(sep < buffer.size()) ? buffer.substr(sep) : std::string{}}; + if(value.size() > 1) + { + if((value.front() == '"' && value.back() == '"') + || (value.front() == '\'' && value.back() == '\'')) + { + value.pop_back(); + value.erase(value.begin()); + } + } - TRACE(" found '%s' = '%s'\n", fullKey.c_str(), value); + TRACE(" found '%s' = '%s'\n", fullKey.c_str(), value.c_str()); /* Check if we already have this option set */ - auto ent = std::find_if(ConfOpts.begin(), ConfOpts.end(), - [&fullKey](const ConfigEntry &entry) -> bool - { return entry.key == fullKey; } - ); + auto find_key = [&fullKey](const ConfigEntry &entry) -> bool + { return entry.key == fullKey; }; + auto ent = std::find_if(ConfOpts.begin(), ConfOpts.end(), find_key); if(ent != ConfOpts.end()) { - if(value[0]) - ent->value = expdup(value); + if(!value.empty()) + ent->value = expdup(value.c_str()); else ConfOpts.erase(ent); } - else if(value[0]) - ConfOpts.emplace_back(ConfigEntry{std::move(fullKey), expdup(value)}); + else if(!value.empty()) + ConfOpts.emplace_back(ConfigEntry{std::move(fullKey), expdup(value.c_str())}); } ConfOpts.shrink_to_fit(); } |