Merge pull request #8191 from lioncash/ini

Common/IniFile: Use std::string_view where applicable
This commit is contained in:
Léo Lam 2019-06-20 13:44:20 +02:00 committed by GitHub
commit 973bba7c1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 84 additions and 61 deletions

View File

@ -5,16 +5,13 @@
#include "Common/IniFile.h" #include "Common/IniFile.h"
#include <algorithm> #include <algorithm>
#include <cinttypes>
#include <cstddef> #include <cstddef>
#include <cstring>
#include <fstream> #include <fstream>
#include <map> #include <map>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h" #include "Common/FileUtil.h"
#include "Common/StringUtil.h" #include "Common/StringUtil.h"
@ -54,32 +51,34 @@ void IniFile::Section::Set(const std::string& key, std::string new_value)
keys_order.push_back(key); keys_order.push_back(key);
} }
bool IniFile::Section::Get(const std::string& key, std::string* value, bool IniFile::Section::Get(std::string_view key, std::string* value,
const std::string& defaultValue) const const std::string& default_value) const
{ {
auto it = values.find(key); const auto it = values.find(key);
if (it != values.end()) if (it != values.end())
{ {
*value = it->second; *value = it->second;
return true; return true;
} }
else if (&defaultValue != &NULL_STRING)
if (&default_value != &NULL_STRING)
{ {
*value = defaultValue; *value = default_value;
return true; return true;
} }
return false; return false;
} }
bool IniFile::Section::Exists(const std::string& key) const bool IniFile::Section::Exists(std::string_view key) const
{ {
return values.find(key) != values.end(); return values.find(key) != values.end();
} }
bool IniFile::Section::Delete(const std::string& key) bool IniFile::Section::Delete(std::string_view key)
{ {
auto it = values.find(key); const auto it = values.find(key);
if (it == values.end()) if (it == values.end())
return false; return false;
@ -125,38 +124,45 @@ IniFile::IniFile() = default;
IniFile::~IniFile() = default; IniFile::~IniFile() = default;
const IniFile::Section* IniFile::GetSection(const std::string& sectionName) const const IniFile::Section* IniFile::GetSection(std::string_view section_name) const
{ {
for (const Section& sect : sections) for (const Section& sect : sections)
if (!strcasecmp(sect.name.c_str(), sectionName.c_str())) {
return (&(sect)); if (CaseInsensitiveStringCompare::IsEqual(sect.name, section_name))
return &sect;
}
return nullptr; return nullptr;
} }
IniFile::Section* IniFile::GetSection(const std::string& sectionName) IniFile::Section* IniFile::GetSection(std::string_view section_name)
{ {
for (Section& sect : sections) for (Section& sect : sections)
if (!strcasecmp(sect.name.c_str(), sectionName.c_str())) {
return (&(sect)); if (CaseInsensitiveStringCompare::IsEqual(sect.name, section_name))
return &sect;
}
return nullptr; return nullptr;
} }
IniFile::Section* IniFile::GetOrCreateSection(const std::string& sectionName) IniFile::Section* IniFile::GetOrCreateSection(std::string_view section_name)
{ {
Section* section = GetSection(sectionName); Section* section = GetSection(section_name);
if (!section) if (!section)
{ {
sections.emplace_back(sectionName); sections.emplace_back(std::string(section_name));
section = &sections.back(); section = &sections.back();
} }
return section; return section;
} }
bool IniFile::DeleteSection(const std::string& sectionName) bool IniFile::DeleteSection(std::string_view section_name)
{ {
Section* s = GetSection(sectionName); Section* s = GetSection(section_name);
if (!s) if (!s)
return false; return false;
for (auto iter = sections.begin(); iter != sections.end(); ++iter) for (auto iter = sections.begin(); iter != sections.end(); ++iter)
{ {
if (&(*iter) == s) if (&(*iter) == s)
@ -165,41 +171,43 @@ bool IniFile::DeleteSection(const std::string& sectionName)
return true; return true;
} }
} }
return false; return false;
} }
bool IniFile::Exists(const std::string& sectionName, const std::string& key) const bool IniFile::Exists(std::string_view section_name, std::string_view key) const
{ {
const Section* section = GetSection(sectionName); const Section* section = GetSection(section_name);
if (!section) if (!section)
return false; return false;
return section->Exists(key); return section->Exists(key);
} }
void IniFile::SetLines(const std::string& sectionName, const std::vector<std::string>& lines) void IniFile::SetLines(std::string_view section_name, const std::vector<std::string>& lines)
{ {
Section* section = GetOrCreateSection(sectionName); Section* section = GetOrCreateSection(section_name);
section->SetLines(lines); section->SetLines(lines);
} }
void IniFile::SetLines(const std::string& section_name, std::vector<std::string>&& lines) void IniFile::SetLines(std::string_view section_name, std::vector<std::string>&& lines)
{ {
Section* section = GetOrCreateSection(section_name); Section* section = GetOrCreateSection(section_name);
section->SetLines(std::move(lines)); section->SetLines(std::move(lines));
} }
bool IniFile::DeleteKey(const std::string& sectionName, const std::string& key) bool IniFile::DeleteKey(std::string_view section_name, std::string_view key)
{ {
Section* section = GetSection(sectionName); Section* section = GetSection(section_name);
if (!section) if (!section)
return false; return false;
return section->Delete(key); return section->Delete(key);
} }
// Return a list of all keys in a section // Return a list of all keys in a section
bool IniFile::GetKeys(const std::string& sectionName, std::vector<std::string>* keys) const bool IniFile::GetKeys(std::string_view section_name, std::vector<std::string>* keys) const
{ {
const Section* section = GetSection(sectionName); const Section* section = GetSection(section_name);
if (!section) if (!section)
{ {
return false; return false;
@ -209,12 +217,12 @@ bool IniFile::GetKeys(const std::string& sectionName, std::vector<std::string>*
} }
// Return a list of all lines in a section // Return a list of all lines in a section
bool IniFile::GetLines(const std::string& sectionName, std::vector<std::string>* lines, bool IniFile::GetLines(std::string_view section_name, std::vector<std::string>* lines,
const bool remove_comments) const const bool remove_comments) const
{ {
lines->clear(); lines->clear();
const Section* section = GetSection(sectionName); const Section* section = GetSection(section_name);
if (!section) if (!section)
return false; return false;

View File

@ -4,21 +4,38 @@
#pragma once #pragma once
#include <cstring> #include <algorithm>
#include <cctype>
#include <list> #include <list>
#include <map> #include <map>
#include <string> #include <string>
#include <string_view>
#include <vector> #include <vector>
#include "Common/CommonFuncs.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/StringUtil.h" #include "Common/StringUtil.h"
struct CaseInsensitiveStringCompare struct CaseInsensitiveStringCompare
{ {
bool operator()(const std::string& a, const std::string& b) const // Allow heterogenous lookup.
using is_transparent = void;
bool operator()(std::string_view a, std::string_view b) const
{ {
return strcasecmp(a.c_str(), b.c_str()) < 0; return std::lexicographical_compare(
a.begin(), a.end(), b.begin(), b.end(), [](char lhs, char rhs) {
return std::tolower(static_cast<u8>(lhs)) < std::tolower(static_cast<u8>(rhs));
});
}
static bool IsEqual(std::string_view a, std::string_view b)
{
if (a.size() != b.size())
return false;
return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char lhs, char rhs) {
return std::tolower(static_cast<u8>(lhs)) == std::tolower(static_cast<u8>(rhs));
});
} }
}; };
@ -32,8 +49,8 @@ public:
public: public:
Section(); Section();
explicit Section(std::string name_); explicit Section(std::string name_);
bool Exists(const std::string& key) const; bool Exists(std::string_view key) const;
bool Delete(const std::string& key); bool Delete(std::string_view key);
void Set(const std::string& key, std::string new_value); void Set(const std::string& key, std::string new_value);
@ -52,12 +69,11 @@ public:
Delete(key); Delete(key);
} }
bool Get(const std::string& key, std::string* value, bool Get(std::string_view key, std::string* value,
const std::string& default_value = NULL_STRING) const; const std::string& default_value = NULL_STRING) const;
template <typename T> template <typename T>
bool Get(const std::string& key, T* value, bool Get(std::string_view key, T* value, const std::common_type_t<T>& default_value = {}) const
const std::common_type_t<T>& default_value = {}) const
{ {
std::string temp; std::string temp;
bool retval = Get(key, &temp); bool retval = Get(key, &temp);
@ -104,41 +120,40 @@ public:
bool Save(const std::string& filename); bool Save(const std::string& filename);
// Returns true if key exists in section // Returns true if key exists in section
bool Exists(const std::string& sectionName, const std::string& key) const; bool Exists(std::string_view section_name, std::string_view key) const;
template <typename T> template <typename T>
bool GetIfExists(const std::string& sectionName, const std::string& key, T* value) bool GetIfExists(std::string_view section_name, std::string_view key, T* value)
{ {
if (Exists(sectionName, key)) if (Exists(section_name, key))
return GetOrCreateSection(sectionName)->Get(key, value); return GetOrCreateSection(section_name)->Get(key, value);
return false; return false;
} }
template <typename T> template <typename T>
bool GetIfExists(const std::string& sectionName, const std::string& key, T* value, T defaultValue) bool GetIfExists(std::string_view section_name, std::string_view key, T* value, T default_value)
{ {
if (Exists(sectionName, key)) if (Exists(section_name, key))
return GetOrCreateSection(sectionName)->Get(key, value, defaultValue); return GetOrCreateSection(section_name)->Get(key, value, default_value);
else
*value = defaultValue;
*value = default_value;
return false; return false;
} }
bool GetKeys(const std::string& sectionName, std::vector<std::string>* keys) const; bool GetKeys(std::string_view section_name, std::vector<std::string>* keys) const;
void SetLines(const std::string& sectionName, const std::vector<std::string>& lines); void SetLines(std::string_view section_name, const std::vector<std::string>& lines);
void SetLines(const std::string& section_name, std::vector<std::string>&& lines); void SetLines(std::string_view section_name, std::vector<std::string>&& lines);
bool GetLines(const std::string& sectionName, std::vector<std::string>* lines, bool GetLines(std::string_view section_name, std::vector<std::string>* lines,
const bool remove_comments = true) const; bool remove_comments = true) const;
bool DeleteKey(const std::string& sectionName, const std::string& key); bool DeleteKey(std::string_view section_name, std::string_view key);
bool DeleteSection(const std::string& sectionName); bool DeleteSection(std::string_view section_name);
void SortSections(); void SortSections();
Section* GetOrCreateSection(const std::string& section); Section* GetOrCreateSection(std::string_view section_name);
// This function is related to parsing data from lines of INI files // This function is related to parsing data from lines of INI files
// It's used outside of IniFile, which is why it is exposed publicly // It's used outside of IniFile, which is why it is exposed publicly
@ -150,8 +165,8 @@ public:
private: private:
std::list<Section> sections; std::list<Section> sections;
const Section* GetSection(const std::string& section) const; const Section* GetSection(std::string_view section_name) const;
Section* GetSection(const std::string& section); Section* GetSection(std::string_view section_name);
static const std::string& NULL_STRING; static const std::string& NULL_STRING;
}; };