aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2019-12-14 17:26:58 -0800
committerChris Robinson <[email protected]>2019-12-14 17:26:58 -0800
commitad9584acc32fb861824358d7df9a37ed5e7ae362 (patch)
treed44985c50f431744e116d4e7f61b6eeab7bc84e4
parentac7a5dcbfa7d913af9ef705a99e146bfcb290b41 (diff)
Avoid sscanf for parsing config lines
-rw-r--r--alc/alconfig.cpp73
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();
}