diff --git a/CMakeLists.txt b/CMakeLists.txt index ebab73fe..8dc99029 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/Makefile.am b/Makefile.am index b6585257..fac3fab9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 @@ -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 \ diff --git a/README.md b/README.md index 5cba66b7..f1c0ab6b 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/generator/csv/functions.csv b/generator/csv/functions.csv index ef9a54a3..1260af2a 100644 --- a/generator/csv/functions.csv +++ b/generator/csv/functions.csv @@ -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, diff --git a/src/generated/lcf/rpg/terms.h b/src/generated/lcf/rpg/terms.h index ea815f53..3f86869e 100644 --- a/src/generated/lcf/rpg/terms.h +++ b/src/generated/lcf/rpg/terms.h @@ -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; diff --git a/src/inireader.cpp b/src/inireader.cpp index 6222ae29..9cf4e207 100644 --- a/src/inireader.cpp +++ b/src/inireader.cpp @@ -34,12 +34,13 @@ #include #include #include +#include #include #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); } @@ -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 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") @@ -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; @@ -164,9 +174,15 @@ int INIReader::ValueHandler(void* user, const char* section, const char* name, { INIReader* reader = static_cast(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; } diff --git a/src/lcf/context.h b/src/lcf/context.h index 13e307db..9261e605 100644 --- a/src/lcf/context.h +++ b/src/lcf/context.h @@ -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; @@ -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 */ @@ -58,7 +58,7 @@ struct Context : ContextStructBase { /** 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{n, i, o}, parent(pctx) {} /** Context of the parent (nullptr when no parent) */ diff --git a/src/lcf/dbstring.h b/src/lcf/dbstring.h index 1385e709..b01fa735 100644 --- a/src/lcf/dbstring.h +++ b/src/lcf/dbstring.h @@ -14,11 +14,9 @@ #include #include #include -#include #include #include -#include "lcf/string_view.h" #include "lcf/dbarrayalloc.h" namespace lcf { @@ -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 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&); @@ -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]; } @@ -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; } @@ -147,7 +145,7 @@ namespace std { template <> struct hash { size_t operator()(const lcf::DBString& s) const { - return std::hash()(lcf::StringView(s)); + return std::hash()(std::string_view(s)); } }; diff --git a/src/lcf/encoder.h b/src/lcf/encoder.h index 4ebdbd49..d9d1db5d 100644 --- a/src/lcf/encoder.h +++ b/src/lcf/encoder.h @@ -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(); @@ -67,7 +67,7 @@ class Encoder { }; -inline const std::string& Encoder::GetEncoding() const { +inline std::string_view Encoder::GetEncoding() const { return _encoding; } diff --git a/src/lcf/inireader.h b/src/lcf/inireader.h index e3d62a88..b8f96ee9 100644 --- a/src/lcf/inireader.h +++ b/src/lcf/inireader.h @@ -32,8 +32,9 @@ #ifndef LCF_INIREADER_H #define LCF_INIREADER_H -#include +#include #include +#include namespace lcf { @@ -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. @@ -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 _values; - static std::string MakeKey(const std::string& section, const std::string& name); + std::unordered_map _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); }; diff --git a/src/lcf/ldb/reader.h b/src/lcf/ldb/reader.h index 384db519..72c78ed7 100644 --- a/src/lcf/ldb/reader.h +++ b/src/lcf/ldb/reader.h @@ -30,32 +30,32 @@ namespace LDB_Reader { /** * Loads Database. */ - std::unique_ptr Load(StringView filename, StringView encoding = ""); + std::unique_ptr Load(std::string_view filename, std::string_view encoding = ""); /** * Saves Database. */ - bool Save(StringView filename, const lcf::rpg::Database& db, StringView encoding = "", SaveOpt opt = SaveOpt::eNone); + bool Save(std::string_view filename, const lcf::rpg::Database& db, std::string_view encoding = "", SaveOpt opt = SaveOpt::eNone); /** * Saves Database as XML. */ - bool SaveXml(StringView filename, const lcf::rpg::Database& db); + bool SaveXml(std::string_view filename, const lcf::rpg::Database& db); /** * Load Database as XML. */ - std::unique_ptr LoadXml(StringView filename); + std::unique_ptr LoadXml(std::string_view filename); /** * Loads Database. */ - std::unique_ptr Load(std::istream& filestream, StringView encoding = ""); + std::unique_ptr Load(std::istream& filestream, std::string_view encoding = ""); /** * Saves Database. */ - bool Save(std::ostream& filestream, const lcf::rpg::Database& db, StringView encoding = "", SaveOpt opt = SaveOpt::eNone); + bool Save(std::ostream& filestream, const lcf::rpg::Database& db, std::string_view encoding = "", SaveOpt opt = SaveOpt::eNone); /** * Saves Database as XML. diff --git a/src/lcf/lmt/reader.h b/src/lcf/lmt/reader.h index 1078a386..340fe6d1 100644 --- a/src/lcf/lmt/reader.h +++ b/src/lcf/lmt/reader.h @@ -25,32 +25,32 @@ namespace LMT_Reader { /** * Loads Map Tree. */ - std::unique_ptr Load(StringView filename, StringView encoding = ""); + std::unique_ptr Load(std::string_view filename, std::string_view encoding = ""); /** * Saves Map Tree. */ - bool Save(StringView filename, const lcf::rpg::TreeMap& tmap, EngineVersion engine, StringView encoding = "", SaveOpt opt = SaveOpt::eNone); + bool Save(std::string_view filename, const lcf::rpg::TreeMap& tmap, EngineVersion engine, std::string_view encoding = "", SaveOpt opt = SaveOpt::eNone); /** * Saves Map Tree as XML. */ - bool SaveXml(StringView filename, const lcf::rpg::TreeMap& tmap, EngineVersion engine); + bool SaveXml(std::string_view filename, const lcf::rpg::TreeMap& tmap, EngineVersion engine); /** * Loads Map Tree as XML. */ - std::unique_ptr LoadXml(StringView filename); + std::unique_ptr LoadXml(std::string_view filename); /** * Loads Map Tree. */ - std::unique_ptr Load(std::istream& filestream, StringView encoding = ""); + std::unique_ptr Load(std::istream& filestream, std::string_view encoding = ""); /** * Saves Map Tree. */ - bool Save(std::ostream& filestream, const lcf::rpg::TreeMap& tmap, EngineVersion engine, StringView encoding = "", SaveOpt opt = SaveOpt::eNone); + bool Save(std::ostream& filestream, const lcf::rpg::TreeMap& tmap, EngineVersion engine, std::string_view encoding = "", SaveOpt opt = SaveOpt::eNone); /** * Saves Map Tree as XML. diff --git a/src/lcf/lmu/reader.h b/src/lcf/lmu/reader.h index ed24c50a..dddbb1c7 100644 --- a/src/lcf/lmu/reader.h +++ b/src/lcf/lmu/reader.h @@ -30,32 +30,32 @@ namespace LMU_Reader { /** * Loads map. */ - std::unique_ptr Load(StringView filename, StringView encoding = ""); + std::unique_ptr Load(std::string_view filename, std::string_view encoding = ""); /** * Saves map. */ - bool Save(StringView filename, const rpg::Map& map, EngineVersion engine, StringView encoding = "", SaveOpt opt = SaveOpt::eNone); + bool Save(std::string_view filename, const rpg::Map& map, EngineVersion engine, std::string_view encoding = "", SaveOpt opt = SaveOpt::eNone); /** * Saves map as XML. */ - bool SaveXml(StringView filename, const rpg::Map& map, EngineVersion engine); + bool SaveXml(std::string_view filename, const rpg::Map& map, EngineVersion engine); /** * Loads map as XML. */ - std::unique_ptr LoadXml(StringView filename); + std::unique_ptr LoadXml(std::string_view filename); /** * Loads map. */ - std::unique_ptr Load(std::istream& filestream, StringView encoding = ""); + std::unique_ptr Load(std::istream& filestream, std::string_view encoding = ""); /** * Saves map. */ - bool Save(std::ostream& filestream, const rpg::Map& map, EngineVersion engine, StringView encoding = "", SaveOpt opt = SaveOpt::eNone); + bool Save(std::ostream& filestream, const rpg::Map& map, EngineVersion engine, std::string_view encoding = "", SaveOpt opt = SaveOpt::eNone); /** * Saves map as XML. diff --git a/src/lcf/log_handler.h b/src/lcf/log_handler.h index e39c28b6..9e0e5def 100644 --- a/src/lcf/log_handler.h +++ b/src/lcf/log_handler.h @@ -31,7 +31,7 @@ static constexpr auto kLevelTags = lcf::makeEnumTags( ); using UserData = void*; -using LogHandlerFn = void (*)(Level level, StringView message, UserData userdata); +using LogHandlerFn = void (*)(Level level, std::string_view message, UserData userdata); /** * Sets the output handler for all lcf logging. diff --git a/src/lcf/lsd/reader.h b/src/lcf/lsd/reader.h index 1e944ddf..be7a8a18 100644 --- a/src/lcf/lsd/reader.h +++ b/src/lcf/lsd/reader.h @@ -47,32 +47,32 @@ namespace LSD_Reader { /** * Loads Savegame. */ - std::unique_ptr Load(StringView filename, StringView encoding = ""); + std::unique_ptr Load(std::string_view filename, std::string_view encoding = ""); /** * Saves Savegame. */ - bool Save(StringView filename, const rpg::Save& save, EngineVersion engine, StringView encoding = ""); + bool Save(std::string_view filename, const rpg::Save& save, EngineVersion engine, std::string_view encoding = ""); /* * Saves Savegame as XML. */ - bool SaveXml(StringView filename, const rpg::Save& save, EngineVersion engine); + bool SaveXml(std::string_view filename, const rpg::Save& save, EngineVersion engine); /** * Loads Savegame as XML. */ - std::unique_ptr LoadXml(StringView filename); + std::unique_ptr LoadXml(std::string_view filename); /** * Loads Savegame. */ - std::unique_ptr Load(std::istream& filestream, StringView encoding = ""); + std::unique_ptr Load(std::istream& filestream, std::string_view encoding = ""); /** * Saves Savegame. */ - bool Save(std::ostream& filestream, const rpg::Save& save, EngineVersion engine, StringView encoding = ""); + bool Save(std::ostream& filestream, const rpg::Save& save, EngineVersion engine, std::string_view encoding = ""); /* * Saves Savegame as XML. diff --git a/src/lcf/reader_util.h b/src/lcf/reader_util.h index ed3413fb..78cfddaa 100644 --- a/src/lcf/reader_util.h +++ b/src/lcf/reader_util.h @@ -57,7 +57,7 @@ namespace ReaderUtil { * * @return encoding or empty string if not detected. */ - std::string DetectEncoding(StringView data); + std::string DetectEncoding(std::string_view data); /** * Detects the encoding of a string based on text analysis. @@ -67,7 +67,7 @@ namespace ReaderUtil { * * @return list of encodings or empty if not detected */ - std::vector DetectEncodings(StringView string); + std::vector DetectEncodings(std::string_view string); /** * Returns the encoding set in the ini file. @@ -76,7 +76,7 @@ namespace ReaderUtil { * * @return encoding or empty string if not found. */ - std::string GetEncoding(StringView ini_file); + std::string GetEncoding(std::string_view ini_file); /** * Returns the encoding set in the ini file. @@ -102,7 +102,7 @@ namespace ReaderUtil { * * @return the recoded string. */ - std::string Recode(StringView str_to_encode, StringView source_encoding); + std::string Recode(std::string_view str_to_encode, std::string_view source_encoding); /** * Converts a UTF-8 string to lowercase and then decomposes it. @@ -110,7 +110,7 @@ namespace ReaderUtil { * @param str the string to normalize. * @return the normalized string. */ - std::string Normalize(StringView str); + std::string Normalize(std::string_view str); /** * Helper function that returns an element from a vector using a 1-based diff --git a/src/lcf/span.h b/src/lcf/span.h index 70338e6a..19eb9eb3 100644 --- a/src/lcf/span.h +++ b/src/lcf/span.h @@ -20,7 +20,7 @@ #define span_FEATURE_WITH_CONTAINER 1 #define span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE 1 #define span_FEATURE_MAKE_SPAN 1 -#define span_CONFIG_SLECT_SPAN span_SPAN_NONSTD +#define span_CONFIG_SELECT_SPAN span_SPAN_NONSTD #include namespace lcf { diff --git a/src/lcf/string_view.h b/src/lcf/string_view.h index b35e13e6..882c6980 100644 --- a/src/lcf/string_view.h +++ b/src/lcf/string_view.h @@ -9,43 +9,47 @@ #ifndef LCF_STRING_VIEW_H #define LCF_STRING_VIEW_H + #include #include -#include -#include -#include -#include - -#define nssv_CONFIG_NO_EXCEPTIONS 1 -#define nssv_CONFIG_CONVERSION_STD_STRING 1 -#define nssv_CONFIG_SELECT_STRING_VIEW nssv_STRING_VIEW_NONSTD -#include +#include namespace lcf { -template > - using BasicStringView = nonstd::basic_string_view; +using StringView [[deprecated("Use std::string_view")]] = std::string_view; +using U16StringView [[deprecated("Use std::u16string_view")]] = std::u16string_view; +using U32StringView [[deprecated("Use std::u32string_view")]] = std::u32string_view; + +inline std::string ToString(std::string_view sv) { + return std::string(sv); +} + +constexpr bool StartsWith(std::string_view l, std::string_view r) noexcept { + return l.size() >= r.size() && l.compare(0, r.size(), r) == 0; +} -using StringView = BasicStringView; -using WStringView = BasicStringView; -using U16StringView = BasicStringView; -using U32StringView = BasicStringView; +constexpr bool StartsWith(std::string_view l, char c) noexcept { + return StartsWith(l, std::string_view(&c, 1)); +} + +constexpr bool StartsWith(std::string_view l, const char* s) { + return StartsWith(l, std::string_view(s)); +} + +constexpr bool EndsWith(std::string_view l, std::string_view r) noexcept { + return l.size() >= r.size() && l.compare(l.size() - r.size(), std::string_view::npos, r) == 0; +} -template< class CharT, class Traits, class Allocator = std::allocator > -std::basic_string -ToString(BasicStringView sv, const Allocator& a = Allocator()) { - return nonstd::to_string(sv, a); +constexpr bool EndsWith(std::string_view l, char c) noexcept { + return EndsWith(l, std::string_view(&c, 1)); } -template< class CharT, class Traits, class Allocator > -BasicStringView -ToStringView(const std::basic_string& s ) -{ - return nonstd::to_string_view(s); +constexpr bool EndsWith(std::string_view l, const char* s) { + return EndsWith(l, std::string_view(s)); } -/** A reimplementation of std::atoi() which works for StringView */ -inline int SvAtoi(StringView str) { +/** A reimplementation of std::atoi() which works for std::string_view */ +inline int SvAtoi(std::string_view str) { const char* b = str.data(); const char* e = str.data() + str.length(); auto value = std::strtol(b, const_cast(&e), 10); diff --git a/src/lcf/third_party/string_view.h b/src/lcf/third_party/string_view.h deleted file mode 100644 index 9eb5b4c6..00000000 --- a/src/lcf/third_party/string_view.h +++ /dev/null @@ -1,1709 +0,0 @@ -// Copyright 2017-2020 by Martin Moene -// -// string-view lite, a C++17-like string_view for C++98 and later. -// For more information see https://github.com/martinmoene/string-view-lite -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#pragma once - -#ifndef NONSTD_SV_LITE_H_INCLUDED -#define NONSTD_SV_LITE_H_INCLUDED - -#define string_view_lite_MAJOR 1 -#define string_view_lite_MINOR 8 -#define string_view_lite_PATCH 0 - -#define string_view_lite_VERSION nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY(string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH) - -#define nssv_STRINGIFY( x ) nssv_STRINGIFY_( x ) -#define nssv_STRINGIFY_( x ) #x - -// string-view lite configuration: - -#define nssv_STRING_VIEW_DEFAULT 0 -#define nssv_STRING_VIEW_NONSTD 1 -#define nssv_STRING_VIEW_STD 2 - -// tweak header support: - -#ifdef __has_include -# if __has_include() -# include -# endif -#define nssv_HAVE_TWEAK_HEADER 1 -#else -#define nssv_HAVE_TWEAK_HEADER 0 -//# pragma message("string_view.hpp: Note: Tweak header not supported.") -#endif - -// string_view selection and configuration: - -#if !defined( nssv_CONFIG_SELECT_STRING_VIEW ) -# define nssv_CONFIG_SELECT_STRING_VIEW ( nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD ) -#endif - -#ifndef nssv_CONFIG_STD_SV_OPERATOR -# define nssv_CONFIG_STD_SV_OPERATOR 0 -#endif - -#ifndef nssv_CONFIG_USR_SV_OPERATOR -# define nssv_CONFIG_USR_SV_OPERATOR 1 -#endif - -#ifdef nssv_CONFIG_CONVERSION_STD_STRING -# define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS nssv_CONFIG_CONVERSION_STD_STRING -# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS nssv_CONFIG_CONVERSION_STD_STRING -#endif - -#ifndef nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS -# define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS 1 -#endif - -#ifndef nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS -# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS 1 -#endif - -#ifndef nssv_CONFIG_NO_STREAM_INSERTION -# define nssv_CONFIG_NO_STREAM_INSERTION 0 -#endif - -#ifndef nssv_CONFIG_CONSTEXPR11_STD_SEARCH -# define nssv_CONFIG_CONSTEXPR11_STD_SEARCH 1 -#endif - -// Control presence of exception handling (try and auto discover): - -#ifndef nssv_CONFIG_NO_EXCEPTIONS -# if defined(_MSC_VER) -# include // for _HAS_EXCEPTIONS -# endif -# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) -# define nssv_CONFIG_NO_EXCEPTIONS 0 -# else -# define nssv_CONFIG_NO_EXCEPTIONS 1 -# endif -#endif - -// C++ language version detection (C++23 is speculative): -// Note: VC14.0/1900 (VS2015) lacks too much from C++14. - -#ifndef nssv_CPLUSPLUS -# if defined(_MSVC_LANG ) && !defined(__clang__) -# define nssv_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG ) -# else -# define nssv_CPLUSPLUS __cplusplus -# endif -#endif - -#define nssv_CPP98_OR_GREATER ( nssv_CPLUSPLUS >= 199711L ) -#define nssv_CPP11_OR_GREATER ( nssv_CPLUSPLUS >= 201103L ) -#define nssv_CPP11_OR_GREATER_ ( nssv_CPLUSPLUS >= 201103L ) -#define nssv_CPP14_OR_GREATER ( nssv_CPLUSPLUS >= 201402L ) -#define nssv_CPP17_OR_GREATER ( nssv_CPLUSPLUS >= 201703L ) -#define nssv_CPP20_OR_GREATER ( nssv_CPLUSPLUS >= 202002L ) -#define nssv_CPP23_OR_GREATER ( nssv_CPLUSPLUS >= 202300L ) - -// use C++17 std::string_view if available and requested: - -#if nssv_CPP17_OR_GREATER && defined(__has_include ) -# if __has_include( ) -# define nssv_HAVE_STD_STRING_VIEW 1 -# else -# define nssv_HAVE_STD_STRING_VIEW 0 -# endif -#else -# define nssv_HAVE_STD_STRING_VIEW 0 -#endif - -#define nssv_USES_STD_STRING_VIEW ( (nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_STD) || ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_DEFAULT) && nssv_HAVE_STD_STRING_VIEW) ) - -#define nssv_HAVE_STARTS_WITH ( nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW ) -#define nssv_HAVE_ENDS_WITH nssv_HAVE_STARTS_WITH - -// -// Use C++17 std::string_view: -// - -#if nssv_USES_STD_STRING_VIEW - -#include - -// Extensions for std::string: - -#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS - -#include - -namespace nonstd { - -template< class CharT, class Traits, class Allocator = std::allocator > -std::basic_string -to_string( std::basic_string_view v, Allocator const & a = Allocator() ) -{ - return std::basic_string( v.begin(), v.end(), a ); -} - -template< class CharT, class Traits, class Allocator > -std::basic_string_view -to_string_view( std::basic_string const & s ) -{ - return std::basic_string_view( s.data(), s.size() ); -} - -// Literal operators sv and _sv: - -#if nssv_CONFIG_STD_SV_OPERATOR - -using namespace std::literals::string_view_literals; - -#endif - -#if nssv_CONFIG_USR_SV_OPERATOR - -inline namespace literals { -inline namespace string_view_literals { - - -constexpr std::string_view operator ""_sv( const char* str, size_t len ) noexcept // (1) -{ - return std::string_view{ str, len }; -} - -constexpr std::u16string_view operator ""_sv( const char16_t* str, size_t len ) noexcept // (2) -{ - return std::u16string_view{ str, len }; -} - -constexpr std::u32string_view operator ""_sv( const char32_t* str, size_t len ) noexcept // (3) -{ - return std::u32string_view{ str, len }; -} - -constexpr std::wstring_view operator ""_sv( const wchar_t* str, size_t len ) noexcept // (4) -{ - return std::wstring_view{ str, len }; -} - -}} // namespace literals::string_view_literals - -#endif // nssv_CONFIG_USR_SV_OPERATOR - -} // namespace nonstd - -#endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS - -namespace nonstd { - -using std::string_view; -using std::wstring_view; -using std::u16string_view; -using std::u32string_view; -using std::basic_string_view; - -// literal "sv" and "_sv", see above - -using std::operator==; -using std::operator!=; -using std::operator<; -using std::operator<=; -using std::operator>; -using std::operator>=; - -using std::operator<<; - -} // namespace nonstd - -#else // nssv_HAVE_STD_STRING_VIEW - -// -// Before C++17: use string_view lite: -// - -// Compiler versions: -// -// MSVC++ 6.0 _MSC_VER == 1200 nssv_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0) -// MSVC++ 7.0 _MSC_VER == 1300 nssv_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002) -// MSVC++ 7.1 _MSC_VER == 1310 nssv_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003) -// MSVC++ 8.0 _MSC_VER == 1400 nssv_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005) -// MSVC++ 9.0 _MSC_VER == 1500 nssv_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008) -// MSVC++ 10.0 _MSC_VER == 1600 nssv_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010) -// MSVC++ 11.0 _MSC_VER == 1700 nssv_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012) -// MSVC++ 12.0 _MSC_VER == 1800 nssv_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013) -// MSVC++ 14.0 _MSC_VER == 1900 nssv_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015) -// MSVC++ 14.1 _MSC_VER >= 1910 nssv_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017) -// MSVC++ 14.2 _MSC_VER >= 1920 nssv_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019) - -#if defined(_MSC_VER ) && !defined(__clang__) -# define nssv_COMPILER_MSVC_VER (_MSC_VER ) -# define nssv_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) ) -#else -# define nssv_COMPILER_MSVC_VER 0 -# define nssv_COMPILER_MSVC_VERSION 0 -#endif - -#define nssv_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) ) - -#if defined( __apple_build_version__ ) -# define nssv_COMPILER_APPLECLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) -# define nssv_COMPILER_CLANG_VERSION 0 -#elif defined( __clang__ ) -# define nssv_COMPILER_APPLECLANG_VERSION 0 -# define nssv_COMPILER_CLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) -#else -# define nssv_COMPILER_APPLECLANG_VERSION 0 -# define nssv_COMPILER_CLANG_VERSION 0 -#endif - -#if defined(__GNUC__) && !defined(__clang__) -# define nssv_COMPILER_GNUC_VERSION nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#else -# define nssv_COMPILER_GNUC_VERSION 0 -#endif - -// half-open range [lo..hi): -#define nssv_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) ) - -// Presence of language and library features: - -#ifdef _HAS_CPP0X -# define nssv_HAS_CPP0X _HAS_CPP0X -#else -# define nssv_HAS_CPP0X 0 -#endif - -// Unless defined otherwise below, consider VC14 as C++11 for string-view-lite: - -#if nssv_COMPILER_MSVC_VER >= 1900 -# undef nssv_CPP11_OR_GREATER -# define nssv_CPP11_OR_GREATER 1 -#endif - -#define nssv_CPP11_90 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500) -#define nssv_CPP11_100 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600) -#define nssv_CPP11_110 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700) -#define nssv_CPP11_120 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800) -#define nssv_CPP11_140 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900) -#define nssv_CPP11_141 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910) - -#define nssv_CPP14_000 (nssv_CPP14_OR_GREATER) -#define nssv_CPP17_000 (nssv_CPP17_OR_GREATER) - -// Presence of C++11 language features: - -#define nssv_HAVE_CONSTEXPR_11 nssv_CPP11_140 -#define nssv_HAVE_EXPLICIT_CONVERSION nssv_CPP11_140 -#define nssv_HAVE_INLINE_NAMESPACE nssv_CPP11_140 -#define nssv_HAVE_IS_DEFAULT nssv_CPP11_140 -#define nssv_HAVE_IS_DELETE nssv_CPP11_140 -#define nssv_HAVE_NOEXCEPT nssv_CPP11_140 -#define nssv_HAVE_NULLPTR nssv_CPP11_100 -#define nssv_HAVE_REF_QUALIFIER nssv_CPP11_140 -#define nssv_HAVE_UNICODE_LITERALS nssv_CPP11_140 -#define nssv_HAVE_USER_DEFINED_LITERALS nssv_CPP11_140 -#define nssv_HAVE_WCHAR16_T nssv_CPP11_100 -#define nssv_HAVE_WCHAR32_T nssv_CPP11_100 - -#if ! ( ( nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION ) || nssv_BETWEEN( nssv_COMPILER_CLANG_VERSION, 300, 400 ) ) -# define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140 -#else -# define nssv_HAVE_STD_DEFINED_LITERALS 0 -#endif - -// Presence of C++14 language features: - -#define nssv_HAVE_CONSTEXPR_14 nssv_CPP14_000 - -// Presence of C++17 language features: - -#define nssv_HAVE_NODISCARD nssv_CPP17_000 - -// Presence of C++ library features: - -#define nssv_HAVE_STD_HASH nssv_CPP11_120 - -// Presence of compiler intrinsics: - -// Providing char-type specializations for compare() and length() that -// use compiler intrinsics can improve compile- and run-time performance. -// -// The challenge is in using the right combinations of builtin availability -// and its constexpr-ness. -// -// | compiler | __builtin_memcmp (constexpr) | memcmp (constexpr) | -// |----------|------------------------------|---------------------| -// | clang | 4.0 (>= 4.0 ) | any (? ) | -// | clang-a | 9.0 (>= 9.0 ) | any (? ) | -// | gcc | any (constexpr) | any (? ) | -// | msvc | >= 14.2 C++17 (>= 14.2 ) | any (? ) | - -#define nssv_HAVE_BUILTIN_VER ( (nssv_CPP17_000 && nssv_COMPILER_MSVC_VERSION >= 142) || nssv_COMPILER_GNUC_VERSION > 0 || nssv_COMPILER_CLANG_VERSION >= 400 || nssv_COMPILER_APPLECLANG_VERSION >= 900 ) -#define nssv_HAVE_BUILTIN_CE ( nssv_HAVE_BUILTIN_VER ) - -#define nssv_HAVE_BUILTIN_MEMCMP ( (nssv_HAVE_CONSTEXPR_14 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_14 ) -#define nssv_HAVE_BUILTIN_STRLEN ( (nssv_HAVE_CONSTEXPR_11 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_11 ) - -#ifdef __has_builtin -# define nssv_HAVE_BUILTIN( x ) __has_builtin( x ) -#else -# define nssv_HAVE_BUILTIN( x ) 0 -#endif - -#if nssv_HAVE_BUILTIN(__builtin_memcmp) || nssv_HAVE_BUILTIN_VER -# define nssv_BUILTIN_MEMCMP __builtin_memcmp -#else -# define nssv_BUILTIN_MEMCMP memcmp -#endif - -#if nssv_HAVE_BUILTIN(__builtin_strlen) || nssv_HAVE_BUILTIN_VER -# define nssv_BUILTIN_STRLEN __builtin_strlen -#else -# define nssv_BUILTIN_STRLEN strlen -#endif - -// C++ feature usage: - -#if nssv_HAVE_CONSTEXPR_11 -# define nssv_constexpr constexpr -#else -# define nssv_constexpr /*constexpr*/ -#endif - -#if nssv_HAVE_CONSTEXPR_14 -# define nssv_constexpr14 constexpr -#else -# define nssv_constexpr14 /*constexpr*/ -#endif - -#if nssv_HAVE_EXPLICIT_CONVERSION -# define nssv_explicit explicit -#else -# define nssv_explicit /*explicit*/ -#endif - -#if nssv_HAVE_INLINE_NAMESPACE -# define nssv_inline_ns inline -#else -# define nssv_inline_ns /*inline*/ -#endif - -#if nssv_HAVE_NOEXCEPT -# define nssv_noexcept noexcept -#else -# define nssv_noexcept /*noexcept*/ -#endif - -//#if nssv_HAVE_REF_QUALIFIER -//# define nssv_ref_qual & -//# define nssv_refref_qual && -//#else -//# define nssv_ref_qual /*&*/ -//# define nssv_refref_qual /*&&*/ -//#endif - -#if nssv_HAVE_NULLPTR -# define nssv_nullptr nullptr -#else -# define nssv_nullptr NULL -#endif - -#if nssv_HAVE_NODISCARD -# define nssv_nodiscard [[nodiscard]] -#else -# define nssv_nodiscard /*[[nodiscard]]*/ -#endif - -// Additional includes: - -#include -#include -#include -#include -#include // std::char_traits<> - -#if ! nssv_CONFIG_NO_STREAM_INSERTION -# include -#endif - -#if ! nssv_CONFIG_NO_EXCEPTIONS -# include -#endif - -#if nssv_CPP11_OR_GREATER -# include -#endif - -// Clang, GNUC, MSVC warning suppression macros: - -#if defined(__clang__) -# pragma clang diagnostic ignored "-Wreserved-user-defined-literal" -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wuser-defined-literals" -#elif nssv_COMPILER_GNUC_VERSION >= 480 -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wliteral-suffix" -#endif // __clang__ - -#if nssv_COMPILER_MSVC_VERSION >= 140 -# define nssv_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]] -# define nssv_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress: code) ) -# define nssv_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes)) -#else -# define nssv_SUPPRESS_MSGSL_WARNING(expr) -# define nssv_SUPPRESS_MSVC_WARNING(code, descr) -# define nssv_DISABLE_MSVC_WARNINGS(codes) -#endif - -#if defined(__clang__) -# define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") -#elif nssv_COMPILER_GNUC_VERSION >= 480 -# define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") -#elif nssv_COMPILER_MSVC_VERSION >= 140 -# define nssv_RESTORE_WARNINGS() __pragma(warning(pop )) -#else -# define nssv_RESTORE_WARNINGS() -#endif - -// Suppress the following MSVC (GSL) warnings: -// - C4455, non-gsl : 'operator ""sv': literal suffix identifiers that do not -// start with an underscore are reserved -// - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions; -// use brace initialization, gsl::narrow_cast or gsl::narow -// - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead - -nssv_DISABLE_MSVC_WARNINGS( 4455 26481 26472 ) -//nssv_DISABLE_CLANG_WARNINGS( "-Wuser-defined-literals" ) -//nssv_DISABLE_GNUC_WARNINGS( -Wliteral-suffix ) - -namespace nonstd { namespace sv_lite { - -// -// basic_string_view declaration: -// - -template -< - class CharT, - class Traits = std::char_traits -> -class basic_string_view; - -namespace detail { - -// support constexpr comparison in C++14; -// for C++17 and later, use provided traits: - -template< typename CharT > -inline nssv_constexpr14 int compare( CharT const * s1, CharT const * s2, std::size_t count ) -{ - while ( count-- != 0 ) - { - if ( *s1 < *s2 ) return -1; - if ( *s1 > *s2 ) return +1; - ++s1; ++s2; - } - return 0; -} - -#if nssv_HAVE_BUILTIN_MEMCMP - -// specialization of compare() for char, see also generic compare() above: - -inline nssv_constexpr14 int compare( char const * s1, char const * s2, std::size_t count ) -{ - return nssv_BUILTIN_MEMCMP( s1, s2, count ); -} - -#endif - -#if nssv_HAVE_BUILTIN_STRLEN - -// specialization of length() for char, see also generic length() further below: - -inline nssv_constexpr std::size_t length( char const * s ) -{ - return nssv_BUILTIN_STRLEN( s ); -} - -#endif - -#if defined(__OPTIMIZE__) - -// gcc, clang provide __OPTIMIZE__ -// Expect tail call optimization to make length() non-recursive: - -template< typename CharT > -inline nssv_constexpr std::size_t length( CharT * s, std::size_t result = 0 ) -{ - return *s == '\0' ? result : length( s + 1, result + 1 ); -} - -#else // OPTIMIZE - -// non-recursive: - -template< typename CharT > -inline nssv_constexpr14 std::size_t length( CharT * s ) -{ - std::size_t result = 0; - while ( *s++ != '\0' ) - { - ++result; - } - return result; -} - -#endif // OPTIMIZE - -#if nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER -#if defined(__OPTIMIZE__) - -// gcc, clang provide __OPTIMIZE__ -// Expect tail call optimization to make search() non-recursive: - -template< class CharT, class Traits = std::char_traits > -constexpr const CharT* search( basic_string_view haystack, basic_string_view needle ) -{ - return haystack.starts_with( needle ) ? haystack.begin() : - haystack.empty() ? haystack.end() : search( haystack.substr(1), needle ); -} - -#else // OPTIMIZE - -// non-recursive: - -#if nssv_CONFIG_CONSTEXPR11_STD_SEARCH - -template< class CharT, class Traits = std::char_traits > -constexpr const CharT* search( basic_string_view haystack, basic_string_view needle ) -{ - return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() ); -} - -#else // nssv_CONFIG_CONSTEXPR11_STD_SEARCH - -template< class CharT, class Traits = std::char_traits > -nssv_constexpr14 const CharT* search( basic_string_view haystack, basic_string_view needle ) -{ - while ( needle.size() <= haystack.size() ) - { - if ( haystack.starts_with(needle) ) - { - return haystack.cbegin(); - } - haystack = basic_string_view{ haystack.begin() + 1, haystack.size() - 1U }; - } - return haystack.cend(); -} -#endif // nssv_CONFIG_CONSTEXPR11_STD_SEARCH - -#endif // OPTIMIZE -#endif // nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER - -} // namespace detail - -// -// basic_string_view: -// - -template -< - class CharT, - class Traits /* = std::char_traits */ -> -class basic_string_view -{ -public: - // Member types: - - typedef Traits traits_type; - typedef CharT value_type; - - typedef CharT * pointer; - typedef CharT const * const_pointer; - typedef CharT & reference; - typedef CharT const & const_reference; - - typedef const_pointer iterator; - typedef const_pointer const_iterator; - typedef std::reverse_iterator< const_iterator > reverse_iterator; - typedef std::reverse_iterator< const_iterator > const_reverse_iterator; - - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - - // 24.4.2.1 Construction and assignment: - - nssv_constexpr basic_string_view() nssv_noexcept - : data_( nssv_nullptr ) - , size_( 0 ) - {} - -#if nssv_CPP11_OR_GREATER - nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept = default; -#else - nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept - : data_( other.data_) - , size_( other.size_) - {} -#endif - - nssv_constexpr basic_string_view( CharT const * s, size_type count ) nssv_noexcept // non-standard noexcept - : data_( s ) - , size_( count ) - {} - - nssv_constexpr basic_string_view( CharT const * s) nssv_noexcept // non-standard noexcept - : data_( s ) -#if nssv_CPP17_OR_GREATER - , size_( Traits::length(s) ) -#elif nssv_CPP11_OR_GREATER - , size_( detail::length(s) ) -#else - , size_( Traits::length(s) ) -#endif - {} - -#if nssv_HAVE_NULLPTR -# if nssv_HAVE_IS_DELETE - nssv_constexpr basic_string_view( std::nullptr_t ) nssv_noexcept = delete; -# else - private: nssv_constexpr basic_string_view( std::nullptr_t ) nssv_noexcept; public: -# endif -#endif - - // Assignment: - -#if nssv_CPP11_OR_GREATER - nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept = default; -#else - nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept - { - data_ = other.data_; - size_ = other.size_; - return *this; - } -#endif - - // 24.4.2.2 Iterator support: - - nssv_constexpr const_iterator begin() const nssv_noexcept { return data_; } - nssv_constexpr const_iterator end() const nssv_noexcept { return data_ + size_; } - - nssv_constexpr const_iterator cbegin() const nssv_noexcept { return begin(); } - nssv_constexpr const_iterator cend() const nssv_noexcept { return end(); } - - nssv_constexpr const_reverse_iterator rbegin() const nssv_noexcept { return const_reverse_iterator( end() ); } - nssv_constexpr const_reverse_iterator rend() const nssv_noexcept { return const_reverse_iterator( begin() ); } - - nssv_constexpr const_reverse_iterator crbegin() const nssv_noexcept { return rbegin(); } - nssv_constexpr const_reverse_iterator crend() const nssv_noexcept { return rend(); } - - // 24.4.2.3 Capacity: - - nssv_constexpr size_type size() const nssv_noexcept { return size_; } - nssv_constexpr size_type length() const nssv_noexcept { return size_; } - nssv_constexpr size_type max_size() const nssv_noexcept { return (std::numeric_limits< size_type >::max)(); } - - // since C++20 - nssv_nodiscard nssv_constexpr bool empty() const nssv_noexcept - { - return 0 == size_; - } - - // 24.4.2.4 Element access: - - nssv_constexpr const_reference operator[]( size_type pos ) const - { - return data_at( pos ); - } - - nssv_constexpr14 const_reference at( size_type pos ) const - { -#if nssv_CONFIG_NO_EXCEPTIONS - assert( pos < size() ); -#else - if ( pos >= size() ) - { - throw std::out_of_range("nonstd::string_view::at()"); - } -#endif - return data_at( pos ); - } - - nssv_constexpr const_reference front() const { return data_at( 0 ); } - nssv_constexpr const_reference back() const { return data_at( size() - 1 ); } - - nssv_constexpr const_pointer data() const nssv_noexcept { return data_; } - - // 24.4.2.5 Modifiers: - - nssv_constexpr14 void remove_prefix( size_type n ) - { - assert( n <= size() ); - data_ += n; - size_ -= n; - } - - nssv_constexpr14 void remove_suffix( size_type n ) - { - assert( n <= size() ); - size_ -= n; - } - - nssv_constexpr14 void swap( basic_string_view & other ) nssv_noexcept - { - const basic_string_view tmp(other); - other = *this; - *this = tmp; - } - - // 24.4.2.6 String operations: - - size_type copy( CharT * dest, size_type n, size_type pos = 0 ) const - { -#if nssv_CONFIG_NO_EXCEPTIONS - assert( pos <= size() ); -#else - if ( pos > size() ) - { - throw std::out_of_range("nonstd::string_view::copy()"); - } -#endif - const size_type rlen = (std::min)( n, size() - pos ); - - (void) Traits::copy( dest, data() + pos, rlen ); - - return rlen; - } - - nssv_constexpr14 basic_string_view substr( size_type pos = 0, size_type n = npos ) const - { -#if nssv_CONFIG_NO_EXCEPTIONS - assert( pos <= size() ); -#else - if ( pos > size() ) - { - throw std::out_of_range("nonstd::string_view::substr()"); - } -#endif - return basic_string_view( data() + pos, (std::min)( n, size() - pos ) ); - } - - // compare(), 6x: - - nssv_constexpr14 int compare( basic_string_view other ) const nssv_noexcept // (1) - { -#if nssv_CPP17_OR_GREATER - if ( const int result = Traits::compare( data(), other.data(), (std::min)( size(), other.size() ) ) ) -#else - if ( const int result = detail::compare( data(), other.data(), (std::min)( size(), other.size() ) ) ) -#endif - { - return result; - } - - return size() == other.size() ? 0 : size() < other.size() ? -1 : 1; - } - - nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other ) const // (2) - { - return substr( pos1, n1 ).compare( other ); - } - - nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other, size_type pos2, size_type n2 ) const // (3) - { - return substr( pos1, n1 ).compare( other.substr( pos2, n2 ) ); - } - - nssv_constexpr int compare( CharT const * s ) const // (4) - { - return compare( basic_string_view( s ) ); - } - - nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s ) const // (5) - { - return substr( pos1, n1 ).compare( basic_string_view( s ) ); - } - - nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s, size_type n2 ) const // (6) - { - return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) ); - } - - // 24.4.2.7 Searching: - - // starts_with(), 3x, since C++20: - - nssv_constexpr bool starts_with( basic_string_view v ) const nssv_noexcept // (1) - { - return size() >= v.size() && compare( 0, v.size(), v ) == 0; - } - - nssv_constexpr bool starts_with( CharT c ) const nssv_noexcept // (2) - { - return starts_with( basic_string_view( &c, 1 ) ); - } - - nssv_constexpr bool starts_with( CharT const * s ) const // (3) - { - return starts_with( basic_string_view( s ) ); - } - - // ends_with(), 3x, since C++20: - - nssv_constexpr bool ends_with( basic_string_view v ) const nssv_noexcept // (1) - { - return size() >= v.size() && compare( size() - v.size(), npos, v ) == 0; - } - - nssv_constexpr bool ends_with( CharT c ) const nssv_noexcept // (2) - { - return ends_with( basic_string_view( &c, 1 ) ); - } - - nssv_constexpr bool ends_with( CharT const * s ) const // (3) - { - return ends_with( basic_string_view( s ) ); - } - - // find(), 4x: - - nssv_constexpr14 size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) - { - return assert( v.size() == 0 || v.data() != nssv_nullptr ) - , pos >= size() - ? npos : to_pos( -#if nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER - detail::search( substr(pos), v ) -#else - std::search( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq ) -#endif - ); - } - - nssv_constexpr size_type find( CharT c, size_type pos = 0 ) const nssv_noexcept // (2) - { - return find( basic_string_view( &c, 1 ), pos ); - } - - nssv_constexpr size_type find( CharT const * s, size_type pos, size_type n ) const // (3) - { - return find( basic_string_view( s, n ), pos ); - } - - nssv_constexpr size_type find( CharT const * s, size_type pos = 0 ) const // (4) - { - return find( basic_string_view( s ), pos ); - } - - // rfind(), 4x: - - nssv_constexpr14 size_type rfind( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1) - { - if ( size() < v.size() ) - { - return npos; - } - - if ( v.empty() ) - { - return (std::min)( size(), pos ); - } - - const_iterator last = cbegin() + (std::min)( size() - v.size(), pos ) + v.size(); - const_iterator result = std::find_end( cbegin(), last, v.cbegin(), v.cend(), Traits::eq ); - - return result != last ? size_type( result - cbegin() ) : npos; - } - - nssv_constexpr14 size_type rfind( CharT c, size_type pos = npos ) const nssv_noexcept // (2) - { - return rfind( basic_string_view( &c, 1 ), pos ); - } - - nssv_constexpr14 size_type rfind( CharT const * s, size_type pos, size_type n ) const // (3) - { - return rfind( basic_string_view( s, n ), pos ); - } - - nssv_constexpr14 size_type rfind( CharT const * s, size_type pos = npos ) const // (4) - { - return rfind( basic_string_view( s ), pos ); - } - - // find_first_of(), 4x: - - nssv_constexpr size_type find_first_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) - { - return pos >= size() - ? npos - : to_pos( std::find_first_of( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq ) ); - } - - nssv_constexpr size_type find_first_of( CharT c, size_type pos = 0 ) const nssv_noexcept // (2) - { - return find_first_of( basic_string_view( &c, 1 ), pos ); - } - - nssv_constexpr size_type find_first_of( CharT const * s, size_type pos, size_type n ) const // (3) - { - return find_first_of( basic_string_view( s, n ), pos ); - } - - nssv_constexpr size_type find_first_of( CharT const * s, size_type pos = 0 ) const // (4) - { - return find_first_of( basic_string_view( s ), pos ); - } - - // find_last_of(), 4x: - - nssv_constexpr size_type find_last_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1) - { - return empty() - ? npos - : pos >= size() - ? find_last_of( v, size() - 1 ) - : to_pos( std::find_first_of( const_reverse_iterator( cbegin() + pos + 1 ), crend(), v.cbegin(), v.cend(), Traits::eq ) ); - } - - nssv_constexpr size_type find_last_of( CharT c, size_type pos = npos ) const nssv_noexcept // (2) - { - return find_last_of( basic_string_view( &c, 1 ), pos ); - } - - nssv_constexpr size_type find_last_of( CharT const * s, size_type pos, size_type count ) const // (3) - { - return find_last_of( basic_string_view( s, count ), pos ); - } - - nssv_constexpr size_type find_last_of( CharT const * s, size_type pos = npos ) const // (4) - { - return find_last_of( basic_string_view( s ), pos ); - } - - // find_first_not_of(), 4x: - - nssv_constexpr size_type find_first_not_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) - { - return pos >= size() - ? npos - : to_pos( std::find_if( cbegin() + pos, cend(), not_in_view( v ) ) ); - } - - nssv_constexpr size_type find_first_not_of( CharT c, size_type pos = 0 ) const nssv_noexcept // (2) - { - return find_first_not_of( basic_string_view( &c, 1 ), pos ); - } - - nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos, size_type count ) const // (3) - { - return find_first_not_of( basic_string_view( s, count ), pos ); - } - - nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos = 0 ) const // (4) - { - return find_first_not_of( basic_string_view( s ), pos ); - } - - // find_last_not_of(), 4x: - - nssv_constexpr size_type find_last_not_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1) - { - return empty() - ? npos - : pos >= size() - ? find_last_not_of( v, size() - 1 ) - : to_pos( std::find_if( const_reverse_iterator( cbegin() + pos + 1 ), crend(), not_in_view( v ) ) ); - } - - nssv_constexpr size_type find_last_not_of( CharT c, size_type pos = npos ) const nssv_noexcept // (2) - { - return find_last_not_of( basic_string_view( &c, 1 ), pos ); - } - - nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos, size_type count ) const // (3) - { - return find_last_not_of( basic_string_view( s, count ), pos ); - } - - nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos = npos ) const // (4) - { - return find_last_not_of( basic_string_view( s ), pos ); - } - - // Constants: - -#if nssv_CPP17_OR_GREATER - static nssv_constexpr size_type npos = size_type(-1); -#elif nssv_CPP11_OR_GREATER - enum : size_type { npos = size_type(-1) }; -#else - enum { npos = size_type(-1) }; -#endif - -private: - struct not_in_view - { - const basic_string_view v; - - nssv_constexpr explicit not_in_view( basic_string_view v_ ) : v( v_ ) {} - - nssv_constexpr bool operator()( CharT c ) const - { - return npos == v.find_first_of( c ); - } - }; - - nssv_constexpr size_type to_pos( const_iterator it ) const - { - return it == cend() ? npos : size_type( it - cbegin() ); - } - - nssv_constexpr size_type to_pos( const_reverse_iterator it ) const - { - return it == crend() ? npos : size_type( crend() - it - 1 ); - } - - nssv_constexpr const_reference data_at( size_type pos ) const - { -#if nssv_BETWEEN( nssv_COMPILER_GNUC_VERSION, 1, 500 ) - return data_[pos]; -#else - return assert( pos < size() ), data_[pos]; -#endif - } - -private: - const_pointer data_; - size_type size_; - -public: -#if nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS - - template< class Allocator > - basic_string_view( std::basic_string const & s ) nssv_noexcept - : data_( s.data() ) - , size_( s.size() ) - {} - -#if nssv_HAVE_EXPLICIT_CONVERSION - - template< class Allocator > - explicit operator std::basic_string() const - { - return to_string( Allocator() ); - } - -#endif // nssv_HAVE_EXPLICIT_CONVERSION - -#if nssv_CPP11_OR_GREATER - - template< class Allocator = std::allocator > - std::basic_string - to_string( Allocator const & a = Allocator() ) const - { - return std::basic_string( begin(), end(), a ); - } - -#else - - std::basic_string - to_string() const - { - return std::basic_string( begin(), end() ); - } - - template< class Allocator > - std::basic_string - to_string( Allocator const & a ) const - { - return std::basic_string( begin(), end(), a ); - } - -#endif // nssv_CPP11_OR_GREATER - -#endif // nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS -}; - -// -// Non-member functions: -// - -// 24.4.3 Non-member comparison functions: -// lexicographically compare two string views (function template): - -template< class CharT, class Traits > -nssv_constexpr bool operator== ( - basic_string_view lhs, - basic_string_view rhs ) nssv_noexcept -{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; } - -template< class CharT, class Traits > -nssv_constexpr bool operator!= ( - basic_string_view lhs, - basic_string_view rhs ) nssv_noexcept -{ return !( lhs == rhs ); } - -template< class CharT, class Traits > -nssv_constexpr bool operator< ( - basic_string_view lhs, - basic_string_view rhs ) nssv_noexcept -{ return lhs.compare( rhs ) < 0; } - -template< class CharT, class Traits > -nssv_constexpr bool operator<= ( - basic_string_view lhs, - basic_string_view rhs ) nssv_noexcept -{ return lhs.compare( rhs ) <= 0; } - -template< class CharT, class Traits > -nssv_constexpr bool operator> ( - basic_string_view lhs, - basic_string_view rhs ) nssv_noexcept -{ return lhs.compare( rhs ) > 0; } - -template< class CharT, class Traits > -nssv_constexpr bool operator>= ( - basic_string_view lhs, - basic_string_view rhs ) nssv_noexcept -{ return lhs.compare( rhs ) >= 0; } - -// Let S be basic_string_view, and sv be an instance of S. -// Implementations shall provide sufficient additional overloads marked -// constexpr and noexcept so that an object t with an implicit conversion -// to S can be compared according to Table 67. - -#if ! nssv_CPP11_OR_GREATER || nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 100, 141 ) - -// accommodate for older compilers: - -// == - -template< class CharT, class Traits> -nssv_constexpr bool operator==( - basic_string_view lhs, - CharT const * rhs ) nssv_noexcept -{ return lhs.size() == detail::length( rhs ) && lhs.compare( rhs ) == 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator==( - CharT const * lhs, - basic_string_view rhs ) nssv_noexcept -{ return detail::length( lhs ) == rhs.size() && rhs.compare( lhs ) == 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator==( - basic_string_view lhs, - std::basic_string rhs ) nssv_noexcept -{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator==( - std::basic_string rhs, - basic_string_view lhs ) nssv_noexcept -{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; } - -// != - -template< class CharT, class Traits> -nssv_constexpr bool operator!=( - basic_string_view lhs, - CharT const * rhs ) nssv_noexcept -{ return !( lhs == rhs ); } - -template< class CharT, class Traits> -nssv_constexpr bool operator!=( - CharT const * lhs, - basic_string_view rhs ) nssv_noexcept -{ return !( lhs == rhs ); } - -template< class CharT, class Traits> -nssv_constexpr bool operator!=( - basic_string_view lhs, - std::basic_string rhs ) nssv_noexcept -{ return !( lhs == rhs ); } - -template< class CharT, class Traits> -nssv_constexpr bool operator!=( - std::basic_string rhs, - basic_string_view lhs ) nssv_noexcept -{ return !( lhs == rhs ); } - -// < - -template< class CharT, class Traits> -nssv_constexpr bool operator<( - basic_string_view lhs, - CharT const * rhs ) nssv_noexcept -{ return lhs.compare( rhs ) < 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator<( - CharT const * lhs, - basic_string_view rhs ) nssv_noexcept -{ return rhs.compare( lhs ) > 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator<( - basic_string_view lhs, - std::basic_string rhs ) nssv_noexcept -{ return lhs.compare( rhs ) < 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator<( - std::basic_string rhs, - basic_string_view lhs ) nssv_noexcept -{ return rhs.compare( lhs ) > 0; } - -// <= - -template< class CharT, class Traits> -nssv_constexpr bool operator<=( - basic_string_view lhs, - CharT const * rhs ) nssv_noexcept -{ return lhs.compare( rhs ) <= 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator<=( - CharT const * lhs, - basic_string_view rhs ) nssv_noexcept -{ return rhs.compare( lhs ) >= 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator<=( - basic_string_view lhs, - std::basic_string rhs ) nssv_noexcept -{ return lhs.compare( rhs ) <= 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator<=( - std::basic_string rhs, - basic_string_view lhs ) nssv_noexcept -{ return rhs.compare( lhs ) >= 0; } - -// > - -template< class CharT, class Traits> -nssv_constexpr bool operator>( - basic_string_view lhs, - CharT const * rhs ) nssv_noexcept -{ return lhs.compare( rhs ) > 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator>( - CharT const * lhs, - basic_string_view rhs ) nssv_noexcept -{ return rhs.compare( lhs ) < 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator>( - basic_string_view lhs, - std::basic_string rhs ) nssv_noexcept -{ return lhs.compare( rhs ) > 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator>( - std::basic_string rhs, - basic_string_view lhs ) nssv_noexcept -{ return rhs.compare( lhs ) < 0; } - -// >= - -template< class CharT, class Traits> -nssv_constexpr bool operator>=( - basic_string_view lhs, - CharT const * rhs ) nssv_noexcept -{ return lhs.compare( rhs ) >= 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator>=( - CharT const * lhs, - basic_string_view rhs ) nssv_noexcept -{ return rhs.compare( lhs ) <= 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator>=( - basic_string_view lhs, - std::basic_string rhs ) nssv_noexcept -{ return lhs.compare( rhs ) >= 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator>=( - std::basic_string rhs, - basic_string_view lhs ) nssv_noexcept -{ return rhs.compare( lhs ) <= 0; } - -#else // newer compilers: - -#define nssv_BASIC_STRING_VIEW_I(T,U) typename std::decay< basic_string_view >::type - -#if defined(_MSC_VER) // issue 40 -# define nssv_MSVC_ORDER(x) , int=x -#else -# define nssv_MSVC_ORDER(x) /*, int=x*/ -#endif - -// == - -template< class CharT, class Traits nssv_MSVC_ORDER(1) > -nssv_constexpr bool operator==( - basic_string_view lhs, - nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs ) nssv_noexcept -{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; } - -template< class CharT, class Traits nssv_MSVC_ORDER(2) > -nssv_constexpr bool operator==( - nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, - basic_string_view rhs ) nssv_noexcept -{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; } - -// != - -template< class CharT, class Traits nssv_MSVC_ORDER(1) > -nssv_constexpr bool operator!= ( - basic_string_view < CharT, Traits > lhs, - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept -{ return !( lhs == rhs ); } - -template< class CharT, class Traits nssv_MSVC_ORDER(2) > -nssv_constexpr bool operator!= ( - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs, - basic_string_view < CharT, Traits > rhs ) nssv_noexcept -{ return !( lhs == rhs ); } - -// < - -template< class CharT, class Traits nssv_MSVC_ORDER(1) > -nssv_constexpr bool operator< ( - basic_string_view < CharT, Traits > lhs, - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept -{ return lhs.compare( rhs ) < 0; } - -template< class CharT, class Traits nssv_MSVC_ORDER(2) > -nssv_constexpr bool operator< ( - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs, - basic_string_view < CharT, Traits > rhs ) nssv_noexcept -{ return lhs.compare( rhs ) < 0; } - -// <= - -template< class CharT, class Traits nssv_MSVC_ORDER(1) > -nssv_constexpr bool operator<= ( - basic_string_view < CharT, Traits > lhs, - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept -{ return lhs.compare( rhs ) <= 0; } - -template< class CharT, class Traits nssv_MSVC_ORDER(2) > -nssv_constexpr bool operator<= ( - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs, - basic_string_view < CharT, Traits > rhs ) nssv_noexcept -{ return lhs.compare( rhs ) <= 0; } - -// > - -template< class CharT, class Traits nssv_MSVC_ORDER(1) > -nssv_constexpr bool operator> ( - basic_string_view < CharT, Traits > lhs, - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept -{ return lhs.compare( rhs ) > 0; } - -template< class CharT, class Traits nssv_MSVC_ORDER(2) > -nssv_constexpr bool operator> ( - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs, - basic_string_view < CharT, Traits > rhs ) nssv_noexcept -{ return lhs.compare( rhs ) > 0; } - -// >= - -template< class CharT, class Traits nssv_MSVC_ORDER(1) > -nssv_constexpr bool operator>= ( - basic_string_view < CharT, Traits > lhs, - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept -{ return lhs.compare( rhs ) >= 0; } - -template< class CharT, class Traits nssv_MSVC_ORDER(2) > -nssv_constexpr bool operator>= ( - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs, - basic_string_view < CharT, Traits > rhs ) nssv_noexcept -{ return lhs.compare( rhs ) >= 0; } - -#undef nssv_MSVC_ORDER -#undef nssv_BASIC_STRING_VIEW_I - -#endif // compiler-dependent approach to comparisons - -// 24.4.4 Inserters and extractors: - -#if ! nssv_CONFIG_NO_STREAM_INSERTION - -namespace detail { - -template< class Stream > -void write_padding( Stream & os, std::streamsize n ) -{ - for ( std::streamsize i = 0; i < n; ++i ) - os.rdbuf()->sputc( os.fill() ); -} - -template< class Stream, class View > -Stream & write_to_stream( Stream & os, View const & sv ) -{ - typename Stream::sentry sentry( os ); - - if ( !sentry ) - return os; - - const std::streamsize length = static_cast( sv.length() ); - - // Whether, and how, to pad: - const bool pad = ( length < os.width() ); - const bool left_pad = pad && ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::right; - - if ( left_pad ) - write_padding( os, os.width() - length ); - - // Write span characters: - os.rdbuf()->sputn( sv.begin(), length ); - - if ( pad && !left_pad ) - write_padding( os, os.width() - length ); - - // Reset output stream width: - os.width( 0 ); - - return os; -} - -} // namespace detail - -template< class CharT, class Traits > -std::basic_ostream & -operator<<( - std::basic_ostream& os, - basic_string_view sv ) -{ - return detail::write_to_stream( os, sv ); -} - -#endif // nssv_CONFIG_NO_STREAM_INSERTION - -// Several typedefs for common character types are provided: - -typedef basic_string_view string_view; -typedef basic_string_view wstring_view; -#if nssv_HAVE_WCHAR16_T -typedef basic_string_view u16string_view; -typedef basic_string_view u32string_view; -#endif - -}} // namespace nonstd::sv_lite - -// -// 24.4.6 Suffix for basic_string_view literals: -// - -#if nssv_HAVE_USER_DEFINED_LITERALS - -namespace nonstd { -nssv_inline_ns namespace literals { -nssv_inline_ns namespace string_view_literals { - -#if nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS - -nssv_constexpr nonstd::sv_lite::string_view operator "" sv( const char* str, size_t len ) nssv_noexcept // (1) -{ - return nonstd::sv_lite::string_view{ str, len }; -} - -nssv_constexpr nonstd::sv_lite::u16string_view operator "" sv( const char16_t* str, size_t len ) nssv_noexcept // (2) -{ - return nonstd::sv_lite::u16string_view{ str, len }; -} - -nssv_constexpr nonstd::sv_lite::u32string_view operator "" sv( const char32_t* str, size_t len ) nssv_noexcept // (3) -{ - return nonstd::sv_lite::u32string_view{ str, len }; -} - -nssv_constexpr nonstd::sv_lite::wstring_view operator "" sv( const wchar_t* str, size_t len ) nssv_noexcept // (4) -{ - return nonstd::sv_lite::wstring_view{ str, len }; -} - -#endif // nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS - -#if nssv_CONFIG_USR_SV_OPERATOR - -nssv_constexpr nonstd::sv_lite::string_view operator ""_sv( const char* str, size_t len ) nssv_noexcept // (1) -{ - return nonstd::sv_lite::string_view{ str, len }; -} - -nssv_constexpr nonstd::sv_lite::u16string_view operator ""_sv( const char16_t* str, size_t len ) nssv_noexcept // (2) -{ - return nonstd::sv_lite::u16string_view{ str, len }; -} - -nssv_constexpr nonstd::sv_lite::u32string_view operator ""_sv( const char32_t* str, size_t len ) nssv_noexcept // (3) -{ - return nonstd::sv_lite::u32string_view{ str, len }; -} - -nssv_constexpr nonstd::sv_lite::wstring_view operator ""_sv( const wchar_t* str, size_t len ) nssv_noexcept // (4) -{ - return nonstd::sv_lite::wstring_view{ str, len }; -} - -#endif // nssv_CONFIG_USR_SV_OPERATOR - -}}} // namespace nonstd::literals::string_view_literals - -#endif - -// -// Extensions for std::string: -// - -#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS - -namespace nonstd { -namespace sv_lite { - -// Exclude MSVC 14 (19.00): it yields ambiguous to_string(): - -#if nssv_CPP11_OR_GREATER && nssv_COMPILER_MSVC_VERSION != 140 - -template< class CharT, class Traits, class Allocator = std::allocator > -std::basic_string -to_string( basic_string_view v, Allocator const & a = Allocator() ) -{ - return std::basic_string( v.begin(), v.end(), a ); -} - -#else - -template< class CharT, class Traits > -std::basic_string -to_string( basic_string_view v ) -{ - return std::basic_string( v.begin(), v.end() ); -} - -template< class CharT, class Traits, class Allocator > -std::basic_string -to_string( basic_string_view v, Allocator const & a ) -{ - return std::basic_string( v.begin(), v.end(), a ); -} - -#endif // nssv_CPP11_OR_GREATER - -template< class CharT, class Traits, class Allocator > -basic_string_view -to_string_view( std::basic_string const & s ) -{ - return basic_string_view( s.data(), s.size() ); -} - -}} // namespace nonstd::sv_lite - -#endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS - -// -// make types and algorithms available in namespace nonstd: -// - -namespace nonstd { - -using sv_lite::basic_string_view; -using sv_lite::string_view; -using sv_lite::wstring_view; - -#if nssv_HAVE_WCHAR16_T -using sv_lite::u16string_view; -#endif -#if nssv_HAVE_WCHAR32_T -using sv_lite::u32string_view; -#endif - -// literal "sv" - -using sv_lite::operator==; -using sv_lite::operator!=; -using sv_lite::operator<; -using sv_lite::operator<=; -using sv_lite::operator>; -using sv_lite::operator>=; - -#if ! nssv_CONFIG_NO_STREAM_INSERTION -using sv_lite::operator<<; -#endif - -#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS -using sv_lite::to_string; -using sv_lite::to_string_view; -#endif - -} // namespace nonstd - -// 24.4.5 Hash support (C++11): - -// Note: The hash value of a string view object is equal to the hash value of -// the corresponding string object. - -#if nssv_HAVE_STD_HASH - -#include - -namespace std { - -template<> -struct hash< nonstd::string_view > -{ -public: - std::size_t operator()( nonstd::string_view v ) const nssv_noexcept - { - return std::hash()( std::string( v.data(), v.size() ) ); - } -}; - -template<> -struct hash< nonstd::wstring_view > -{ -public: - std::size_t operator()( nonstd::wstring_view v ) const nssv_noexcept - { - return std::hash()( std::wstring( v.data(), v.size() ) ); - } -}; - -template<> -struct hash< nonstd::u16string_view > -{ -public: - std::size_t operator()( nonstd::u16string_view v ) const nssv_noexcept - { - return std::hash()( std::u16string( v.data(), v.size() ) ); - } -}; - -template<> -struct hash< nonstd::u32string_view > -{ -public: - std::size_t operator()( nonstd::u32string_view v ) const nssv_noexcept - { - return std::hash()( std::u32string( v.data(), v.size() ) ); - } -}; - -} // namespace std - -#endif // nssv_HAVE_STD_HASH - -nssv_RESTORE_WARNINGS() - -#endif // nssv_HAVE_STD_STRING_VIEW -#endif // NONSTD_SV_LITE_H_INCLUDED diff --git a/src/lcf/writer_lcf.h b/src/lcf/writer_lcf.h index f2e91019..9ff86291 100644 --- a/src/lcf/writer_lcf.h +++ b/src/lcf/writer_lcf.h @@ -119,7 +119,7 @@ class LcfWriter { * @param str_to_encode UTF-8 string to encode. * @return native version of string. */ - std::string Decode(StringView str_to_encode); + std::string Decode(std::string_view str_to_encode); /** @return true if 2k3 format, false if 2k format */ bool Is2k3() const; diff --git a/src/lcf/writer_xml.h b/src/lcf/writer_xml.h index be1c514e..6868be73 100644 --- a/src/lcf/writer_xml.h +++ b/src/lcf/writer_xml.h @@ -131,7 +131,7 @@ class XmlWriter { template void WriteVector(const ArrayType& val); - void WriteString(StringView s); + void WriteString(std::string_view s); }; inline bool XmlWriter::Is2k3() const { diff --git a/src/ldb_reader.cpp b/src/ldb_reader.cpp index cfc20c38..ac62eec6 100644 --- a/src/ldb_reader.cpp +++ b/src/ldb_reader.cpp @@ -23,7 +23,7 @@ void LDB_Reader::PrepareSave(rpg::Database& db) { ++db.system.save_count; } -std::unique_ptr LDB_Reader::Load(StringView filename, StringView encoding) { +std::unique_ptr LDB_Reader::Load(std::string_view filename, std::string_view encoding) { std::ifstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LDB file '%s' for reading: %s", ToString(filename).c_str(), strerror(errno)); @@ -32,7 +32,7 @@ std::unique_ptr LDB_Reader::Load(StringView filename, String return LDB_Reader::Load(stream, encoding); } -bool LDB_Reader::Save(StringView filename, const lcf::rpg::Database& db, StringView encoding, SaveOpt opt) { +bool LDB_Reader::Save(std::string_view filename, const lcf::rpg::Database& db, std::string_view encoding, SaveOpt opt) { std::ofstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LDB file '%s' for writing: %s", ToString(filename).c_str(), strerror(errno)); @@ -41,7 +41,7 @@ bool LDB_Reader::Save(StringView filename, const lcf::rpg::Database& db, StringV return LDB_Reader::Save(stream, db, encoding, opt); } -bool LDB_Reader::SaveXml(StringView filename, const lcf::rpg::Database& db) { +bool LDB_Reader::SaveXml(std::string_view filename, const lcf::rpg::Database& db) { std::ofstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LDB XML file '%s' for writing: %s", ToString(filename).c_str(), strerror(errno)); @@ -50,7 +50,7 @@ bool LDB_Reader::SaveXml(StringView filename, const lcf::rpg::Database& db) { return LDB_Reader::SaveXml(stream, db); } -std::unique_ptr LDB_Reader::LoadXml(StringView filename) { +std::unique_ptr LDB_Reader::LoadXml(std::string_view filename) { std::ifstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LDB XML file '%s' for reading: %s", ToString(filename).c_str(), strerror(errno)); @@ -59,7 +59,7 @@ std::unique_ptr LDB_Reader::LoadXml(StringView filename) { return LDB_Reader::LoadXml(stream); } -std::unique_ptr LDB_Reader::Load(std::istream& filestream, StringView encoding) { +std::unique_ptr LDB_Reader::Load(std::istream& filestream, std::string_view encoding) { LcfReader reader(filestream, ToString(encoding)); if (!reader.IsOk()) { LcfReader::SetError("Couldn't parse database file."); @@ -88,7 +88,7 @@ std::unique_ptr LDB_Reader::Load(std::istream& filestream, S return db; } -bool LDB_Reader::Save(std::ostream& filestream, const lcf::rpg::Database& db, StringView encoding, SaveOpt opt) { +bool LDB_Reader::Save(std::ostream& filestream, const lcf::rpg::Database& db, std::string_view encoding, SaveOpt opt) { const auto engine = GetEngineVersion(db); LcfWriter writer(filestream, engine, ToString(encoding)); if (!writer.IsOk()) { diff --git a/src/lmt_reader.cpp b/src/lmt_reader.cpp index c603b31c..d5245ff0 100644 --- a/src/lmt_reader.cpp +++ b/src/lmt_reader.cpp @@ -19,7 +19,7 @@ namespace lcf { -std::unique_ptr LMT_Reader::Load(StringView filename, StringView encoding) { +std::unique_ptr LMT_Reader::Load(std::string_view filename, std::string_view encoding) { std::ifstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LMT file '%s' for reading: %s", ToString(filename).c_str(), strerror(errno)); @@ -28,7 +28,7 @@ std::unique_ptr LMT_Reader::Load(StringView filename, StringV return LMT_Reader::Load(stream, encoding); } -bool LMT_Reader::Save(StringView filename, const lcf::rpg::TreeMap& tmap, EngineVersion engine, StringView encoding, SaveOpt opt) { +bool LMT_Reader::Save(std::string_view filename, const lcf::rpg::TreeMap& tmap, EngineVersion engine, std::string_view encoding, SaveOpt opt) { std::ofstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LMT file '%s' for writing: %s", ToString(filename).c_str(), strerror(errno)); @@ -37,7 +37,7 @@ bool LMT_Reader::Save(StringView filename, const lcf::rpg::TreeMap& tmap, Engine return LMT_Reader::Save(stream, tmap, engine, encoding, opt); } -bool LMT_Reader::SaveXml(StringView filename, const lcf::rpg::TreeMap& tmap, EngineVersion engine) { +bool LMT_Reader::SaveXml(std::string_view filename, const lcf::rpg::TreeMap& tmap, EngineVersion engine) { std::ofstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LMT XML file '%s' for writing: %s", ToString(filename).c_str(), strerror(errno)); @@ -46,7 +46,7 @@ bool LMT_Reader::SaveXml(StringView filename, const lcf::rpg::TreeMap& tmap, Eng return LMT_Reader::SaveXml(stream, tmap, engine); } -std::unique_ptr LMT_Reader::LoadXml(StringView filename) { +std::unique_ptr LMT_Reader::LoadXml(std::string_view filename) { std::ifstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LMT XML file '%s' for reading: %s", ToString(filename).c_str(), strerror(errno)); @@ -55,7 +55,7 @@ std::unique_ptr LMT_Reader::LoadXml(StringView filename) { return LMT_Reader::LoadXml(stream); } -std::unique_ptr LMT_Reader::Load(std::istream& filestream, StringView encoding) { +std::unique_ptr LMT_Reader::Load(std::istream& filestream, std::string_view encoding) { LcfReader reader(filestream, ToString(encoding)); if (!reader.IsOk()) { LcfReader::SetError("Couldn't parse map tree file."); @@ -76,7 +76,7 @@ std::unique_ptr LMT_Reader::Load(std::istream& filestream, St return tmap; } -bool LMT_Reader::Save(std::ostream& filestream, const lcf::rpg::TreeMap& tmap, EngineVersion engine, StringView encoding, SaveOpt opt) { +bool LMT_Reader::Save(std::ostream& filestream, const lcf::rpg::TreeMap& tmap, EngineVersion engine, std::string_view encoding, SaveOpt opt) { LcfWriter writer(filestream, engine, ToString(encoding)); if (!writer.IsOk()) { LcfReader::SetError("Couldn't parse map tree file."); diff --git a/src/lmu_reader.cpp b/src/lmu_reader.cpp index c1b635a5..1b781821 100644 --- a/src/lmu_reader.cpp +++ b/src/lmu_reader.cpp @@ -25,7 +25,7 @@ void LMU_Reader::PrepareSave(rpg::Map& map) { ++map.save_count; } -std::unique_ptr LMU_Reader::Load(StringView filename, StringView encoding) { +std::unique_ptr LMU_Reader::Load(std::string_view filename, std::string_view encoding) { std::ifstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LMU file '%s' for reading: %s", ToString(filename).c_str(), strerror(errno)); @@ -34,7 +34,7 @@ std::unique_ptr LMU_Reader::Load(StringView filename, StringView encod return LMU_Reader::Load(stream, encoding); } -bool LMU_Reader::Save(StringView filename, const rpg::Map& save, EngineVersion engine, StringView encoding, SaveOpt opt) { +bool LMU_Reader::Save(std::string_view filename, const rpg::Map& save, EngineVersion engine, std::string_view encoding, SaveOpt opt) { std::ofstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LMU file '%s' for writing: %s", ToString(filename).c_str(), strerror(errno)); @@ -43,7 +43,7 @@ bool LMU_Reader::Save(StringView filename, const rpg::Map& save, EngineVersion e return LMU_Reader::Save(stream, save, engine, encoding, opt); } -bool LMU_Reader::SaveXml(StringView filename, const rpg::Map& save, EngineVersion engine) { +bool LMU_Reader::SaveXml(std::string_view filename, const rpg::Map& save, EngineVersion engine) { std::ofstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LMU XML file '%s' for writing: %s", ToString(filename).c_str(), strerror(errno)); @@ -52,7 +52,7 @@ bool LMU_Reader::SaveXml(StringView filename, const rpg::Map& save, EngineVersio return LMU_Reader::SaveXml(stream, save, engine); } -std::unique_ptr LMU_Reader::LoadXml(StringView filename) { +std::unique_ptr LMU_Reader::LoadXml(std::string_view filename) { std::ifstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LMU XML file '%s' for reading: %s", ToString(filename).c_str(), strerror(errno)); @@ -61,7 +61,7 @@ std::unique_ptr LMU_Reader::LoadXml(StringView filename) { return LMU_Reader::LoadXml(stream); } -std::unique_ptr LMU_Reader::Load(std::istream& filestream, StringView encoding) { +std::unique_ptr LMU_Reader::Load(std::istream& filestream, std::string_view encoding) { LcfReader reader(filestream, ToString(encoding)); if (!reader.IsOk()) { LcfReader::SetError("Couldn't parse map file."); @@ -83,7 +83,7 @@ std::unique_ptr LMU_Reader::Load(std::istream& filestream, StringView return map; } -bool LMU_Reader::Save(std::ostream& filestream, const rpg::Map& map, EngineVersion engine, StringView encoding, SaveOpt opt) { +bool LMU_Reader::Save(std::ostream& filestream, const rpg::Map& map, EngineVersion engine, std::string_view encoding, SaveOpt opt) { LcfWriter writer(filestream, engine, ToString(encoding)); if (!writer.IsOk()) { LcfReader::SetError("Couldn't parse map file."); diff --git a/src/log_handler.cpp b/src/log_handler.cpp index c7468028..5b9b63b7 100644 --- a/src/log_handler.cpp +++ b/src/log_handler.cpp @@ -16,7 +16,7 @@ namespace lcf { namespace LogHandler { namespace { - void DefaultHandler(LogHandler::Level level, StringView message, UserData) { + void DefaultHandler(LogHandler::Level level, std::string_view message, UserData) { switch (level) { case Level::Debug: std::cerr << "Debug: "; diff --git a/src/lsd_reader.cpp b/src/lsd_reader.cpp index 3b1896cc..e26d3cc7 100644 --- a/src/lsd_reader.cpp +++ b/src/lsd_reader.cpp @@ -41,7 +41,7 @@ void LSD_Reader::PrepareSave(rpg::Save& save, int32_t version, int32_t codepage) save.easyrpg_data.codepage = codepage; } -std::unique_ptr LSD_Reader::Load(StringView filename, StringView encoding) { +std::unique_ptr LSD_Reader::Load(std::string_view filename, std::string_view encoding) { std::ifstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LSD file '%s' for reading: %s", ToString(filename).c_str(), strerror(errno)); @@ -50,7 +50,7 @@ std::unique_ptr LSD_Reader::Load(StringView filename, StringView enco return LSD_Reader::Load(stream, encoding); } -bool LSD_Reader::Save(StringView filename, const rpg::Save& save, EngineVersion engine, StringView encoding) { +bool LSD_Reader::Save(std::string_view filename, const rpg::Save& save, EngineVersion engine, std::string_view encoding) { std::ofstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LSD file '%s' for reading: %s", ToString(filename).c_str(), strerror(errno)); @@ -59,7 +59,7 @@ bool LSD_Reader::Save(StringView filename, const rpg::Save& save, EngineVersion return LSD_Reader::Save(stream, save, engine, encoding); } -bool LSD_Reader::SaveXml(StringView filename, const rpg::Save& save, EngineVersion engine) { +bool LSD_Reader::SaveXml(std::string_view filename, const rpg::Save& save, EngineVersion engine) { std::ofstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LSD XML file '%s' for writing: %s", ToString(filename).c_str(), strerror(errno)); @@ -68,7 +68,7 @@ bool LSD_Reader::SaveXml(StringView filename, const rpg::Save& save, EngineVersi return LSD_Reader::SaveXml(stream, save, engine); } -std::unique_ptr LSD_Reader::LoadXml(StringView filename) { +std::unique_ptr LSD_Reader::LoadXml(std::string_view filename) { std::ifstream stream(ToString(filename), std::ios::binary); if (!stream.is_open()) { Log::Error("Failed to open LSD XML file `%s' for reading : %s", ToString(filename).c_str(), strerror(errno)); @@ -77,7 +77,7 @@ std::unique_ptr LSD_Reader::LoadXml(StringView filename) { return LSD_Reader::LoadXml(stream); } -std::unique_ptr LSD_Reader::Load(std::istream& filestream, StringView encoding) { +std::unique_ptr LSD_Reader::Load(std::istream& filestream, std::string_view encoding) { LcfReader reader(filestream, ToString(encoding)); if (!reader.IsOk()) { @@ -114,7 +114,7 @@ std::unique_ptr LSD_Reader::Load(std::istream& filestream, StringView return save; } -bool LSD_Reader::Save(std::ostream& filestream, const rpg::Save& save, EngineVersion engine, StringView encoding) { +bool LSD_Reader::Save(std::ostream& filestream, const rpg::Save& save, EngineVersion engine, std::string_view encoding) { std::string enc; if (save.easyrpg_data.codepage > 0) { diff --git a/src/reader_util.cpp b/src/reader_util.cpp index 8718d22c..8c084b03 100644 --- a/src/reader_util.cpp +++ b/src/reader_util.cpp @@ -124,7 +124,7 @@ std::vector ReaderUtil::DetectEncodings(lcf::rpg::Database& db) { #endif } -std::string ReaderUtil::DetectEncoding(StringView string) { +std::string ReaderUtil::DetectEncoding(std::string_view string) { std::vector encodings = DetectEncodings(string); if (encodings.empty()) { @@ -134,7 +134,7 @@ std::string ReaderUtil::DetectEncoding(StringView string) { return encodings.front(); } -std::vector ReaderUtil::DetectEncodings(StringView string) { +std::vector ReaderUtil::DetectEncodings(std::string_view string) { std::vector encodings; #if LCF_SUPPORT_ICU if (!string.empty()) { @@ -206,13 +206,13 @@ std::vector ReaderUtil::DetectEncodings(StringView string) { return encodings; } -std::string ReaderUtil::GetEncoding(StringView ini_file) { +std::string ReaderUtil::GetEncoding(std::string_view ini_file) { #if LCF_SUPPORT_INI INIReader ini(ToString(ini_file)); if (ini.ParseError() != -1) { - std::string encoding = ini.Get("EasyRPG", "Encoding", std::string()); + auto encoding = ini.Get("EasyRPG", "Encoding", ""); if (!encoding.empty()) { - return ReaderUtil::CodepageToEncoding(atoi(encoding.c_str())); + return ReaderUtil::CodepageToEncoding(atoi(std::string(encoding).c_str())); } } #else @@ -225,9 +225,9 @@ std::string ReaderUtil::GetEncoding(std::istream& filestream) { #if LCF_SUPPORT_INI INIReader ini(filestream); if (ini.ParseError() != -1) { - std::string encoding = ini.Get("EasyRPG", "Encoding", std::string()); + auto encoding = ini.Get("EasyRPG", "Encoding", ""); if (!encoding.empty()) { - return ReaderUtil::CodepageToEncoding(atoi(encoding.c_str())); + return ReaderUtil::CodepageToEncoding(atoi(std::string(encoding).c_str())); } } #else @@ -293,14 +293,14 @@ std::string ReaderUtil::GetLocaleEncoding() { return CodepageToEncoding(codepage); } -std::string ReaderUtil::Recode(StringView str_to_encode, StringView source_encoding) { +std::string ReaderUtil::Recode(std::string_view str_to_encode, std::string_view source_encoding) { lcf::Encoder enc(ToString(source_encoding)); std::string out = ToString(str_to_encode); enc.Encode(out); return out; } -std::string ReaderUtil::Normalize(StringView str) { +std::string ReaderUtil::Normalize(std::string_view str) { if (str.empty()) { return {}; } diff --git a/src/rpg_terms.cpp b/src/rpg_terms.cpp index ac02898e..d93b625a 100644 --- a/src/rpg_terms.cpp +++ b/src/rpg_terms.cpp @@ -11,7 +11,7 @@ namespace lcf { -std::string rpg::Terms::TermOrDefault(const DBString& db_term, StringView default_term) { +std::string rpg::Terms::TermOrDefault(const DBString& db_term, std::string_view default_term) { if (db_term == kDefaultTerm) { return ToString(default_term); } diff --git a/src/writer_lcf.cpp b/src/writer_lcf.cpp index b679b66b..f416d85f 100644 --- a/src/writer_lcf.cpp +++ b/src/writer_lcf.cpp @@ -144,7 +144,7 @@ bool LcfWriter::IsOk() const { return stream.good() && encoder.IsOk(); } -std::string LcfWriter::Decode(StringView str) { +std::string LcfWriter::Decode(std::string_view str) { auto copy = std::string(str); encoder.Decode(copy); return copy; diff --git a/src/writer_xml.cpp b/src/writer_xml.cpp index 205e1c70..6e8f7ed8 100644 --- a/src/writer_xml.cpp +++ b/src/writer_xml.cpp @@ -70,7 +70,7 @@ void XmlWriter::Write(const double& val) { stream << val; } -void XmlWriter::WriteString(StringView val) { +void XmlWriter::WriteString(std::string_view val) { Indent(); for (auto c: val) { switch (c) { diff --git a/tests/dbstring.cpp b/tests/dbstring.cpp index 1c53493b..1b331598 100644 --- a/tests/dbstring.cpp +++ b/tests/dbstring.cpp @@ -26,7 +26,7 @@ template void testConstruct(const T&) { } -TEST_CASE_TEMPLATE("Construct", T, StringView, std::string, char*, DBString) { +TEST_CASE_TEMPLATE("Construct", T, std::string_view, std::string, char*, DBString) { DBString x(T("abc")); REQUIRE_FALSE(x.empty()); diff --git a/tests/ini.cpp b/tests/ini.cpp new file mode 100644 index 00000000..cd13c78e --- /dev/null +++ b/tests/ini.cpp @@ -0,0 +1,107 @@ +/* + * This file is part of liblcf. Copyright (c) liblcf authors. + * https://github.com/EasyRPG/liblcf - https://easyrpg.org + * + * liblcf is Free/Libre Open Source Software, released under the MIT License. + * For the full copyright and license information, please view the COPYING + * file that was distributed with this source code. + */ + +#include "doctest.h" +#include "lcf/config.h" + +#if LCF_SUPPORT_INI + +#include +#include "lcf/inireader.h" + +using namespace lcf; + +INIReader load_ini() { + std::string ini = R"(" +[Section] +StrKey=StrValue +IntKey=-123 +RealKey=-1.234 +BoolKeyT=true +BoolKeyF=off +EmptyKey= + +[OtherSection] +SomeKey=XXX +DupeKey=A +DupeKey=B +DupeKey=C +)"; + + std::stringstream ss(ini); + return {ss}; +} + +TEST_SUITE_BEGIN("INI"); + +TEST_CASE("Get") { + auto ini = load_ini(); + + REQUIRE_EQ(ini.Get("Section", "StrKey", "Default"), "StrValue"); + REQUIRE_EQ(ini.Get("Section", "EmptyKey", "Default"), ""); + REQUIRE_EQ(ini.Get("Section", "MissingKey", "Default"), "Default"); + + REQUIRE_EQ(ini.Get("OtherSection", "SomeKey", "Default"), "XXX"); +} + +TEST_CASE("GetString") { + auto ini = load_ini(); + + REQUIRE_EQ(ini.GetString("Section", "StrKey", "Default"), "StrValue"); + REQUIRE_EQ(ini.GetString("Section", "EmptyKey", "Default"), "Default"); + REQUIRE_EQ(ini.GetString("Section", "MissingKey", "Default"), "Default"); +} + +TEST_CASE("GetInteger") { + auto ini = load_ini(); + + REQUIRE_EQ(ini.GetInteger("Section", "IntKey", -1), -123); + REQUIRE_EQ(ini.GetInteger("Section", "StrKey", -1), -1); + REQUIRE_EQ(ini.GetInteger("Section", "EmptyKey", -1), -1); + REQUIRE_EQ(ini.GetInteger("Section", "MissingKey", -1), -1); +} + +TEST_CASE("GetReal") { + auto ini = load_ini(); + + REQUIRE_EQ(ini.GetReal("Section", "RealKey", -1.), -1.234); + REQUIRE_EQ(ini.GetReal("Section", "StrKey", -1.), -1.); + REQUIRE_EQ(ini.GetReal("Section", "EmptyKey", -1.), -1.); + REQUIRE_EQ(ini.GetReal("Section", "MissingKey", -1.), -1.); +} + +TEST_CASE("GetBoolean") { + auto ini = load_ini(); + + REQUIRE_EQ(ini.GetBoolean("Section", "BoolKeyT", false), true); + REQUIRE_EQ(ini.GetBoolean("Section", "BoolKeyF", true), false); + REQUIRE_EQ(ini.GetBoolean("Section", "StrKey", true), true); + REQUIRE_EQ(ini.GetBoolean("Section", "EmptyKey", true), true); + REQUIRE_EQ(ini.GetBoolean("Section", "MissingKey", true), true); +} + +TEST_CASE("GetDupe") { + auto ini = load_ini(); + + REQUIRE_EQ(ini.GetString("OtherSection", "DupeKey", "Default"), "A\nB\nC"); +} + +TEST_CASE("HasValue") { + auto ini = load_ini(); + + REQUIRE(ini.HasValue("Section", "StrKey")); + REQUIRE(ini.HasValue("Section", "EmptyKey")); + REQUIRE_FALSE(ini.HasValue("Section", "MissingKey")); + + REQUIRE(ini.HasValue("OtherSection", "SomeKey")); +} + +TEST_SUITE_END(); + +#endif diff --git a/tests/string_view.cpp b/tests/string_view.cpp index 65395621..043a02d4 100644 --- a/tests/string_view.cpp +++ b/tests/string_view.cpp @@ -12,6 +12,7 @@ #include #include +#include using namespace lcf; @@ -31,4 +32,36 @@ TEST_CASE("SvAtoi") { REQUIRE_EQ(SvAtoi("0x55"), 0); } +TEST_CASE("StartsWith") { + std::string_view sv = "StringView"; + std::string in = "String"; + std::string notin = "NotFound"; + + REQUIRE(StartsWith(sv, in)); + REQUIRE(StartsWith(sv, std::string_view(in))); + REQUIRE(StartsWith(sv, 'S')); + REQUIRE(StartsWith(sv, "String")); + + REQUIRE_FALSE(StartsWith(sv, notin)); + REQUIRE_FALSE(StartsWith(sv, std::string_view(notin))); + REQUIRE_FALSE(StartsWith(sv, 'X')); + REQUIRE_FALSE(StartsWith(sv, "NotFound")); +} + +TEST_CASE("EndsWith") { + std::string_view sv = "StringView"; + std::string in = "View"; + std::string notin = "NotFound"; + + REQUIRE(EndsWith(sv, in)); + REQUIRE(EndsWith(sv, std::string_view(in))); + REQUIRE(EndsWith(sv, 'w')); + REQUIRE(EndsWith(sv, "View")); + + REQUIRE_FALSE(EndsWith(sv, notin)); + REQUIRE_FALSE(EndsWith(sv, std::string_view(notin))); + REQUIRE_FALSE(EndsWith(sv, 'X')); + REQUIRE_FALSE(EndsWith(sv, "NotFound")); +} + TEST_SUITE_END();