Avoid sscanf for parsing config lines
This commit is contained in:
+38
-37
@@ -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;
|
||||
auto cmtpos = std::min(buffer.find('#'), buffer.size());
|
||||
while(cmtpos > 0 && std::isspace(buffer[cmtpos-1]))
|
||||
--cmtpos;
|
||||
if(!cmtpos) continue;
|
||||
buffer.erase(cmtpos);
|
||||
|
||||
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 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;
|
||||
}
|
||||
else if(std::sscanf(line, "%255[^=] %255[=]", key, value) == 2)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
auto keyend = sep++;
|
||||
while(keyend > 0 && std::isspace(buffer[keyend-1]))
|
||||
--keyend;
|
||||
if(!keyend)
|
||||
{
|
||||
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);
|
||||
|
||||
TRACE(" found '%s' = '%s'\n", fullKey.c_str(), value);
|
||||
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.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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user