Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,6 @@ set(LCF_HEADERS
src/generated/lcf/rpg/trooppagecondition.h
src/generated/lcf/rpg/variable.h
src/lcf/third_party/span.h
src/lcf/third_party/string_view.h
)

set(LCF_SUPPORT_INI 0)
Expand Down
4 changes: 2 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,7 @@ lcfrpginclude_HEADERS = \
src/generated/lcf/rpg/variable.h

lcfthirdpartyinclude_HEADERS = \
src/lcf/third_party/span.h \
src/lcf/third_party/string_view.h
src/lcf/third_party/span.h

nodist_lcfinclude_HEADERS = src/lcf/config.h

Expand All @@ -344,6 +343,7 @@ test_runner_SOURCES = \
tests/doctest.h \
tests/enum_tags.cpp \
tests/flag_set.cpp \
tests/ini.cpp \
tests/test_main.cpp \
tests/time_stamp.cpp \
tests/span.cpp \
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ See the file [COPYING] for copying conditions.
liblcf includes code of the following 3rd party software:

- [inih] under New BSD license.
- [string-view-lite] and [span-lite] under Boost Software License, Version 1.0.
- [span-lite] under Boost Software License, Version 1.0.

See the source code comment headers for license details.

Expand Down
2 changes: 1 addition & 1 deletion generator/csv/functions.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Structure,Method,Static,Headers
Actor,void Setup(bool is2k3),f,
Parameters,void Setup(int final_level),f,
Terms,"std::string TermOrDefault(const DBString& db_term, StringView default_term)",t,
Terms,"std::string TermOrDefault(const DBString& db_term, std::string_view default_term)",t,
2 changes: 1 addition & 1 deletion src/generated/lcf/rpg/terms.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace rpg {
// Sentinel name used to denote that the default hardcoded term should be used.
static constexpr const char* kDefaultTerm = "default_term";

static std::string TermOrDefault(const DBString& db_term, StringView default_term);
static std::string TermOrDefault(const DBString& db_term, std::string_view default_term);
DBString encounter;
DBString special_combat;
DBString escape_success;
Expand Down
64 changes: 40 additions & 24 deletions src/inireader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@
#include <cstdlib>
#include <cstring>
#include <istream>
#include <charconv>
#include <ini.h>
#include "lcf/inireader.h"

namespace lcf {

INIReader::INIReader(const std::string& filename)
INIReader::INIReader(std::string filename)
{
_error = ini_parse(filename.c_str(), ValueHandler, this);
}
Expand Down Expand Up @@ -100,41 +101,50 @@ int INIReader::ParseError() const
return _error;
}

std::string INIReader::Get(const std::string& section, const std::string& name, const std::string& default_value) const
std::string_view INIReader::Get(std::string_view section, std::string_view name, std::string_view default_value) const
{
std::string key = MakeKey(section, name);
// Use _values.find() here instead of _values.at() to support pre C++11 compilers
return _values.count(key) ? _values.find(key)->second : default_value;

auto it = _values.find(key);
if (it == _values.end()) {
return default_value;
}
return it->second;
}

std::string INIReader::GetString(const std::string& section, const std::string& name, const std::string& default_value) const
std::string_view INIReader::GetString(std::string_view section, std::string_view name, std::string_view default_value) const
{
const std::string str = Get(section, name, "");
auto str = Get(section, name, "");
return str.empty() ? default_value : str;
}

long INIReader::GetInteger(const std::string& section, const std::string& name, long default_value) const
long INIReader::GetInteger(std::string_view section, std::string_view name, long default_value) const
{
std::string valstr = Get(section, name, "");
const char* value = valstr.c_str();
char* end;
// This parses "1234" (decimal) and also "0x4D2" (hex)
long n = strtol(value, &end, 0);
return end > value ? n : default_value;
std::string_view valstr = Get(section, name, "");
long n;
auto ec = std::from_chars(valstr.data(), valstr.data() + valstr.size(), n).ec;
return ec == std::errc() ? n : default_value;
}

double INIReader::GetReal(const std::string& section, const std::string& name, double default_value) const
double INIReader::GetReal(std::string_view section, std::string_view name, double default_value) const
{
std::string valstr = Get(section, name, "");
std::string valstr = std::string(Get(section, name, ""));
const char* value = valstr.c_str();
char* end;
double n = strtod(value, &end);
return end > value ? n : default_value;
/*
// FIXME: std::from_chars<double> not supported by clang and old g++ versions
std::string_view valstr = Get(section, name, "");
double n;
auto ec = std::from_chars(valstr.data(), valstr.data() + valstr.size(), n).ec;
return ec == std::errc() ? n : default_value;
*/
}

bool INIReader::GetBoolean(const std::string& section, const std::string& name, bool default_value) const
bool INIReader::GetBoolean(std::string_view section, std::string_view name, bool default_value) const
{
std::string valstr = Get(section, name, "");
auto valstr = std::string(Get(section, name, ""));
// Convert to lower case to make string comparisons case-insensitive
std::transform(valstr.begin(), valstr.end(), valstr.begin(), ::tolower);
if (valstr == "true" || valstr == "yes" || valstr == "on" || valstr == "1")
Expand All @@ -145,15 +155,15 @@ bool INIReader::GetBoolean(const std::string& section, const std::string& name,
return default_value;
}

bool INIReader::HasValue(const std::string& section, const std::string& name) const
bool INIReader::HasValue(std::string_view section, std::string_view name) const
{
std::string key = MakeKey(section, name);
return _values.count(key);
return _values.find(key) != _values.end();
}

std::string INIReader::MakeKey(const std::string& section, const std::string& name)
std::string INIReader::MakeKey(std::string_view section, std::string_view name)
{
std::string key = section + "=" + name;
std::string key = std::string(section) + "=" + std::string(name);
// Convert to lower case to make section/name lookups case-insensitive
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
return key;
Expand All @@ -164,9 +174,15 @@ int INIReader::ValueHandler(void* user, const char* section, const char* name,
{
INIReader* reader = static_cast<INIReader*>(user);
std::string key = MakeKey(section, name);
if (reader->_values[key].size() > 0)
reader->_values[key] += "\n";
reader->_values[key] += value;

auto [it, inserted] = reader->_values.try_emplace(key, value);

if (!inserted) {
// Key is duplicated
it->second += "\n";
it->second += value;
}

return 1;
}

Expand Down
8 changes: 4 additions & 4 deletions src/lcf/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ namespace lcf {
*/
struct ContextNameBase {
/** Constructor */
constexpr ContextNameBase(StringView n, int i) : name(n), index(i) {}
constexpr ContextNameBase(std::string_view n, int i) : name(n), index(i) {}

/** Name of the enumerated field */
StringView name;
std::string_view name;

/** Array index when the object is part of a list (-1 when not) */
int index = -1;
Expand All @@ -38,7 +38,7 @@ struct ContextStructBase : ContextNameBase {
using StructType_t = StructType;

/** Constructor */
constexpr ContextStructBase(StringView n, int i, StructType_t* o)
constexpr ContextStructBase(std::string_view n, int i, StructType_t* o)
: ContextNameBase(n, i), obj(o) {}

/** Object instance (cast to appropriate RPG-type */
Expand All @@ -58,7 +58,7 @@ struct Context : ContextStructBase<StructType> {
/** The type of the parent context */
using ParentCtxType_t = ParentCtxType;

constexpr Context(StringView n, int i, StructType* o, const ParentCtxType_t* pctx)
constexpr Context(std::string_view n, int i, StructType* o, const ParentCtxType_t* pctx)
: ContextStructBase<StructType>{n, i, o}, parent(pctx) {}

/** Context of the parent (nullptr when no parent) */
Expand Down
32 changes: 15 additions & 17 deletions src/lcf/dbstring.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@
#include <iterator>
#include <cstdint>
#include <cstring>
#include <limits>
#include <algorithm>
#include <ostream>

#include "lcf/string_view.h"
#include "lcf/dbarrayalloc.h"

namespace lcf {
Expand All @@ -43,17 +41,17 @@ class DBString {
static constexpr size_type npos = size_type(-1);

constexpr DBString() = default;
explicit DBString(StringView s) : _storage(construct_sv(s.data(), s.size())) {}
explicit DBString(std::string_view s) : _storage(construct_sv(s.data(), s.size())) {}
explicit DBString(const std::string& s) : _storage(construct_z(s.c_str(), s.size())) {}

// Explicit construct for general const char*
explicit DBString(const char* s) : DBString(StringView(s)) {}
explicit DBString(const char* s) : DBString(std::string_view(s)) {}
// Implicit constructor to capture string literals
template <size_t N>
DBString(const char(&literal)[N]) : _storage(construct_z(literal, N - 1)) {}
DBString(const char* s, size_t len) : DBString(StringView(s, len)) {}
DBString(const char* s, size_t len) : DBString(std::string_view(s, len)) {}

DBString(const DBString& o) : DBString(StringView(o)) {}
DBString(const DBString& o) : DBString(std::string_view(o)) {}
DBString(DBString&& o) noexcept { swap(o); }

DBString& operator=(const DBString&);
Expand All @@ -66,7 +64,7 @@ class DBString {
~DBString() { destroy(); }

explicit operator std::string() const { return std::string(data(), size()); }
operator StringView() const { return StringView(data(), size()); }
operator std::string_view() const { return std::string_view(data(), size()); }

char& operator[](size_type i) { return data()[i]; }
char operator[](size_type i) const { return data()[i]; }
Expand Down Expand Up @@ -123,21 +121,21 @@ inline std::string ToString(const DBString& s) {
}

#define LCF_DBSTRING_MAKE_CMP_OPS(LTYPE, RTYPE) \
inline bool operator==(LTYPE l, RTYPE r) { return StringView(l) == StringView(r); }\
inline bool operator!=(LTYPE l, RTYPE r) { return StringView(l) != StringView(r); }\
inline bool operator<(LTYPE l, RTYPE r) { return StringView(l) < StringView(r); }\
inline bool operator>(LTYPE l, RTYPE r) { return StringView(l) > StringView(r); }\
inline bool operator<=(LTYPE l, RTYPE r) { return StringView(l) <= StringView(r); }\
inline bool operator>=(LTYPE l, RTYPE r) { return StringView(l) >= StringView(r); }\
inline bool operator==(LTYPE l, RTYPE r) { return std::string_view(l) == std::string_view(r); }\
inline bool operator!=(LTYPE l, RTYPE r) { return std::string_view(l) != std::string_view(r); }\
inline bool operator<(LTYPE l, RTYPE r) { return std::string_view(l) < std::string_view(r); }\
inline bool operator>(LTYPE l, RTYPE r) { return std::string_view(l) > std::string_view(r); }\
inline bool operator<=(LTYPE l, RTYPE r) { return std::string_view(l) <= std::string_view(r); }\
inline bool operator>=(LTYPE l, RTYPE r) { return std::string_view(l) >= std::string_view(r); }\

LCF_DBSTRING_MAKE_CMP_OPS(const DBString&, const DBString&);
LCF_DBSTRING_MAKE_CMP_OPS(StringView, const DBString&);
LCF_DBSTRING_MAKE_CMP_OPS(const DBString&, StringView);
LCF_DBSTRING_MAKE_CMP_OPS(std::string_view, const DBString&);
LCF_DBSTRING_MAKE_CMP_OPS(const DBString&, std::string_view);
LCF_DBSTRING_MAKE_CMP_OPS(const char*, const DBString&);
LCF_DBSTRING_MAKE_CMP_OPS(const DBString&, const char*);

inline std::ostream& operator<<(std::ostream& os, const DBString& s) {
os << StringView(s);
os << std::string_view(s);
return os;
}

Expand All @@ -147,7 +145,7 @@ namespace std {

template <> struct hash<lcf::DBString> {
size_t operator()(const lcf::DBString& s) const {
return std::hash<lcf::StringView>()(lcf::StringView(s));
return std::hash<std::string_view>()(std::string_view(s));
}
};

Expand Down
4 changes: 2 additions & 2 deletions src/lcf/encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class Encoder {

bool IsOk() const;

const std::string& GetEncoding() const;
std::string_view GetEncoding() const;
private:
#if LCF_SUPPORT_ICU
void Init();
Expand All @@ -67,7 +67,7 @@ class Encoder {
};


inline const std::string& Encoder::GetEncoding() const {
inline std::string_view Encoder::GetEncoding() const {
return _encoding;
}

Expand Down
25 changes: 13 additions & 12 deletions src/lcf/inireader.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@
#ifndef LCF_INIREADER_H
#define LCF_INIREADER_H

#include <map>
#include <unordered_map>
#include <string>
#include <string_view>

namespace lcf {

Expand All @@ -44,7 +45,7 @@ class INIReader
public:
// Construct INIReader and parse given filename. See ini.h for more info
// about the parsing.
explicit INIReader(const std::string& filename);
explicit INIReader(std::string filename);

// Construct INIReader and parse given stream. See ini.h for more info
// about the parsing.
Expand All @@ -56,35 +57,35 @@ class INIReader
int ParseError() const;

// Get a string value from INI file, returning default_value if not found.
std::string Get(const std::string& section, const std::string& name,
const std::string& default_value) const;
std::string_view Get(std::string_view section, std::string_view name,
std::string_view default_value) const;

// Get a string value from INI file, returning default_value if not found,
// empty, or contains only whitespace.
std::string GetString(const std::string& section, const std::string& name,
const std::string& default_value) const;
std::string_view GetString(std::string_view section, std::string_view name,
std::string_view default_value) const;

// Get an integer (long) value from INI file, returning default_value if
// not found or not a valid integer (decimal "1234", "-1234", or hex "0x4d2").
long GetInteger(const std::string& section, const std::string& name, long default_value) const;
long GetInteger(std::string_view section, std::string_view name, long default_value) const;

// Get a real (floating point double) value from INI file, returning
// default_value if not found or not a valid floating point value
// according to strtod().
double GetReal(const std::string& section, const std::string& name, double default_value) const;
double GetReal(std::string_view section, std::string_view name, double default_value) const;

// Get a boolean value from INI file, returning default_value if not found or if
// not a valid true/false value. Valid true values are "true", "yes", "on", "1",
// and valid false values are "false", "no", "off", "0" (not case sensitive).
bool GetBoolean(const std::string& section, const std::string& name, bool default_value) const;
bool GetBoolean(std::string_view section, std::string_view name, bool default_value) const;

// Return true if a value exists with the given section and field names.
bool HasValue(const std::string& section, const std::string& name) const;
bool HasValue(std::string_view section, std::string_view name) const;

private:
int _error;
std::map<std::string, std::string> _values;
static std::string MakeKey(const std::string& section, const std::string& name);
std::unordered_map<std::string, std::string> _values;
static std::string MakeKey(std::string_view section, std::string_view name);
static int ValueHandler(void* user, const char* section, const char* name, const char* value);
};

Expand Down
Loading