mirror of
https://github.com/luanti-org/luanti.git
synced 2025-09-15 18:57:08 +00:00
Introduce std::string_view
into wider use (#14368)
This commit is contained in:
parent
fa47af737f
commit
6ca214fefc
74 changed files with 501 additions and 456 deletions
|
@ -39,10 +39,9 @@ std::string translate_password(const std::string &name,
|
|||
|
||||
std::string slt = name + password;
|
||||
SHA1 sha1;
|
||||
sha1.addBytes(slt.c_str(), slt.length());
|
||||
unsigned char *digest = sha1.getDigest();
|
||||
std::string pwd = base64_encode(digest, 20);
|
||||
free(digest);
|
||||
sha1.addBytes(slt);
|
||||
std::string digest = sha1.getDigest();
|
||||
std::string pwd = base64_encode(digest);
|
||||
return pwd;
|
||||
}
|
||||
|
||||
|
@ -112,8 +111,8 @@ std::string encode_srp_verifier(const std::string &verifier,
|
|||
{
|
||||
std::ostringstream ret_str;
|
||||
ret_str << "#1#"
|
||||
<< base64_encode((unsigned char *)salt.c_str(), salt.size()) << "#"
|
||||
<< base64_encode((unsigned char *)verifier.c_str(), verifier.size());
|
||||
<< base64_encode(salt) << "#"
|
||||
<< base64_encode(verifier);
|
||||
return ret_str.str();
|
||||
}
|
||||
|
||||
|
|
|
@ -45,15 +45,15 @@ static inline bool is_base64(unsigned char c)
|
|||
|| c == '+' || c == '/';
|
||||
}
|
||||
|
||||
bool base64_is_valid(std::string const& s)
|
||||
bool base64_is_valid(std::string_view s)
|
||||
{
|
||||
size_t i = 0;
|
||||
for (; i < s.size(); ++i)
|
||||
if (!is_base64(s[i]))
|
||||
break;
|
||||
unsigned char padding = 3 - ((i + 3) % 4);
|
||||
if ((padding == 1 && base64_chars_padding_1.find(s[i - 1]) == std::string::npos)
|
||||
|| (padding == 2 && base64_chars_padding_2.find(s[i - 1]) == std::string::npos)
|
||||
if ((padding == 1 && base64_chars_padding_1.find(s[i - 1]) == s.npos)
|
||||
|| (padding == 2 && base64_chars_padding_2.find(s[i - 1]) == s.npos)
|
||||
|| padding == 3)
|
||||
return false;
|
||||
int actual_padding = s.size() - i;
|
||||
|
@ -69,8 +69,14 @@ bool base64_is_valid(std::string const& s)
|
|||
return padding == actual_padding;
|
||||
}
|
||||
|
||||
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
|
||||
std::string base64_encode(std::string_view s)
|
||||
{
|
||||
const unsigned char *bytes_to_encode = reinterpret_cast<const unsigned char*>(s.data());
|
||||
size_t in_len = s.size();
|
||||
|
||||
std::string ret;
|
||||
ret.reserve(in_len + in_len / 3);
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
unsigned char char_array_3[3];
|
||||
|
@ -110,16 +116,17 @@ std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_
|
|||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
std::string base64_decode(std::string const& encoded_string) {
|
||||
std::string base64_decode(std::string_view encoded_string)
|
||||
{
|
||||
int in_len = encoded_string.size();
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int in_ = 0;
|
||||
unsigned char char_array_4[4], char_array_3[3];
|
||||
std::string ret;
|
||||
ret.reserve(in_len / 4 * 3);
|
||||
|
||||
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
|
||||
char_array_4[i++] = encoded_string[in_]; in_++;
|
||||
|
|
|
@ -29,7 +29,8 @@ René Nyffenegger rene.nyffenegger@adp-gmbh.ch
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
bool base64_is_valid(std::string const& s);
|
||||
std::string base64_encode(unsigned char const* , unsigned int len);
|
||||
std::string base64_decode(std::string const& s);
|
||||
bool base64_is_valid(std::string_view s);
|
||||
std::string base64_encode(std::string_view s);
|
||||
std::string base64_decode(std::string_view s);
|
||||
|
|
|
@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
static const char hex_chars[] = "0123456789abcdef";
|
||||
|
||||
|
@ -41,9 +42,9 @@ static inline std::string hex_encode(const char *data, unsigned int data_size)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static inline std::string hex_encode(const std::string &data)
|
||||
static inline std::string hex_encode(std::string_view data)
|
||||
{
|
||||
return hex_encode(data.c_str(), data.size());
|
||||
return hex_encode(data.data(), data.size());
|
||||
}
|
||||
|
||||
static inline bool hex_digit_decode(char hexdigit, unsigned char &value)
|
||||
|
|
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "debug.h" // For assert()
|
||||
#include <cstring>
|
||||
#include <memory> // std::shared_ptr
|
||||
#include <string_view>
|
||||
|
||||
|
||||
template<typename T> class ConstSharedPtr {
|
||||
|
@ -133,6 +134,13 @@ public:
|
|||
return m_size;
|
||||
}
|
||||
|
||||
operator std::string_view() const
|
||||
{
|
||||
if (!data)
|
||||
return std::string_view();
|
||||
return std::string_view(reinterpret_cast<char*>(data), m_size);
|
||||
}
|
||||
|
||||
private:
|
||||
void drop()
|
||||
{
|
||||
|
|
|
@ -34,7 +34,7 @@ FloatType g_serialize_f32_type = FLOATTYPE_UNKNOWN;
|
|||
//// String
|
||||
////
|
||||
|
||||
std::string serializeString16(const std::string &plain)
|
||||
std::string serializeString16(std::string_view plain)
|
||||
{
|
||||
std::string s;
|
||||
char buf[2];
|
||||
|
@ -76,7 +76,7 @@ std::string deSerializeString16(std::istream &is)
|
|||
//// Long String
|
||||
////
|
||||
|
||||
std::string serializeString32(const std::string &plain)
|
||||
std::string serializeString32(std::string_view plain)
|
||||
{
|
||||
std::string s;
|
||||
char buf[4];
|
||||
|
@ -122,7 +122,7 @@ std::string deSerializeString32(std::istream &is)
|
|||
//// JSON-like strings
|
||||
////
|
||||
|
||||
std::string serializeJsonString(const std::string &plain)
|
||||
std::string serializeJsonString(std::string_view plain)
|
||||
{
|
||||
std::string tmp;
|
||||
|
||||
|
@ -263,13 +263,13 @@ std::string deSerializeJsonString(std::istream &is)
|
|||
return tmp;
|
||||
}
|
||||
|
||||
std::string serializeJsonStringIfNeeded(const std::string &s)
|
||||
std::string serializeJsonStringIfNeeded(std::string_view s)
|
||||
{
|
||||
for (size_t i = 0; i < s.size(); ++i) {
|
||||
if (s[i] <= 0x1f || s[i] >= 0x7f || s[i] == ' ' || s[i] == '\"')
|
||||
return serializeJsonString(s);
|
||||
}
|
||||
return s;
|
||||
return std::string(s);
|
||||
}
|
||||
|
||||
std::string deSerializeJsonStringIfNeeded(std::istream &is)
|
||||
|
|
|
@ -41,7 +41,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include <cstring> // for memcpy
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <string_view>
|
||||
|
||||
#define FIXEDPOINT_FACTOR 1000.0f
|
||||
|
||||
|
@ -450,26 +450,26 @@ inline v3f clampToF1000(v3f v)
|
|||
}
|
||||
|
||||
// Creates a string with the length as the first two bytes
|
||||
std::string serializeString16(const std::string &plain);
|
||||
std::string serializeString16(std::string_view plain);
|
||||
|
||||
// Reads a string with the length as the first two bytes
|
||||
std::string deSerializeString16(std::istream &is);
|
||||
|
||||
// Creates a string with the length as the first four bytes
|
||||
std::string serializeString32(const std::string &plain);
|
||||
std::string serializeString32(std::string_view plain);
|
||||
|
||||
// Reads a string with the length as the first four bytes
|
||||
std::string deSerializeString32(std::istream &is);
|
||||
|
||||
// Creates a string encoded in JSON format (almost equivalent to a C string literal)
|
||||
std::string serializeJsonString(const std::string &plain);
|
||||
std::string serializeJsonString(std::string_view plain);
|
||||
|
||||
// Reads a string encoded in JSON format
|
||||
std::string deSerializeJsonString(std::istream &is);
|
||||
|
||||
// If the string contains spaces, quotes or control characters, encodes as JSON.
|
||||
// Else returns the string unmodified.
|
||||
std::string serializeJsonStringIfNeeded(const std::string &s);
|
||||
std::string serializeJsonStringIfNeeded(std::string_view s);
|
||||
|
||||
// Parses a string serialized by serializeJsonStringIfNeeded.
|
||||
std::string deSerializeJsonStringIfNeeded(std::istream &is);
|
||||
|
|
|
@ -65,7 +65,7 @@ void SHA1::storeBigEndianUint32( unsigned char* byte, Uint32 num )
|
|||
SHA1::SHA1()
|
||||
{
|
||||
// make sure that the data type is the right size
|
||||
assert( sizeof( Uint32 ) * 5 == 20 );
|
||||
static_assert( sizeof( Uint32 ) * 5 == 20 );
|
||||
}
|
||||
|
||||
// Destructor ********************************************************
|
||||
|
@ -134,20 +134,19 @@ void SHA1::process()
|
|||
}
|
||||
|
||||
// addBytes **********************************************************
|
||||
void SHA1::addBytes( const char* data, int num )
|
||||
void SHA1::addBytes( const char* data, Uint32 num )
|
||||
{
|
||||
assert( data );
|
||||
assert( num >= 0 );
|
||||
// add these bytes to the running total
|
||||
size += num;
|
||||
// repeat until all data is processed
|
||||
while( num > 0 )
|
||||
{
|
||||
// number of bytes required to complete block
|
||||
int needed = 64 - unprocessedBytes;
|
||||
assert( needed > 0 );
|
||||
Uint32 needed = 64 - unprocessedBytes;
|
||||
assert( needed <= 64 );
|
||||
// number of bytes to copy (use smaller of two)
|
||||
int toCopy = (num < needed) ? num : needed;
|
||||
Uint32 toCopy = (num < needed) ? num : needed;
|
||||
// Copy the bytes
|
||||
memcpy( bytes + unprocessedBytes, data, toCopy );
|
||||
// Bytes have been copied
|
||||
|
@ -161,7 +160,7 @@ void SHA1::addBytes( const char* data, int num )
|
|||
}
|
||||
|
||||
// digest ************************************************************
|
||||
unsigned char* SHA1::getDigest()
|
||||
void SHA1::getDigest(unsigned char *digest)
|
||||
{
|
||||
// save the message size
|
||||
Uint32 totalBitsL = size << 3;
|
||||
|
@ -179,20 +178,16 @@ unsigned char* SHA1::getDigest()
|
|||
addBytes( (char*)footer, 64 - unprocessedBytes);
|
||||
assert( unprocessedBytes <= 56 );
|
||||
// how many zeros do we need
|
||||
int neededZeros = 56 - unprocessedBytes;
|
||||
Uint32 neededZeros = 56 - unprocessedBytes;
|
||||
// store file size (in bits) in big-endian format
|
||||
storeBigEndianUint32( footer + neededZeros , totalBitsH );
|
||||
storeBigEndianUint32( footer + neededZeros + 4, totalBitsL );
|
||||
// finish the final block
|
||||
addBytes( (char*)footer, neededZeros + 8 );
|
||||
// allocate memory for the digest bytes
|
||||
unsigned char* digest = (unsigned char*)malloc( 20 );
|
||||
// copy the digest bytes
|
||||
storeBigEndianUint32( digest, H0 );
|
||||
storeBigEndianUint32( digest + 4, H1 );
|
||||
storeBigEndianUint32( digest + 8, H2 );
|
||||
storeBigEndianUint32( digest + 12, H3 );
|
||||
storeBigEndianUint32( digest + 16, H4 );
|
||||
// return the digest
|
||||
return digest;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,11 @@ SOFTWARE.
|
|||
|
||||
#pragma once
|
||||
|
||||
typedef unsigned int Uint32;
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
typedef uint32_t Uint32;
|
||||
|
||||
class SHA1
|
||||
{
|
||||
|
@ -38,15 +42,24 @@ private:
|
|||
Uint32 H3 = 0x10325476;
|
||||
Uint32 H4 = 0xc3d2e1f0;
|
||||
unsigned char bytes[64];
|
||||
int unprocessedBytes = 0;
|
||||
Uint32 unprocessedBytes = 0;
|
||||
Uint32 size = 0;
|
||||
void process();
|
||||
|
||||
public:
|
||||
SHA1();
|
||||
~SHA1();
|
||||
void addBytes(const char *data, int num);
|
||||
unsigned char *getDigest();
|
||||
void addBytes(const char *data, Uint32 num);
|
||||
inline void addBytes(std::string_view data) {
|
||||
addBytes(data.data(), data.size());
|
||||
}
|
||||
void getDigest(unsigned char *to);
|
||||
inline std::string getDigest() {
|
||||
std::string ret(20, '\000');
|
||||
getDigest(reinterpret_cast<unsigned char*>(ret.data()));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// utility methods
|
||||
static Uint32 lrot(Uint32 x, int bits);
|
||||
static void storeBigEndianUint32(unsigned char *byte, Uint32 num);
|
||||
|
|
|
@ -20,14 +20,19 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
// FIXME: convert this class to string_view
|
||||
template <typename T>
|
||||
class BasicStrfnd {
|
||||
typedef std::basic_string<T> String;
|
||||
String str;
|
||||
size_t pos;
|
||||
public:
|
||||
BasicStrfnd(const String &s) : str(s), pos(0) {}
|
||||
BasicStrfnd(const String &s) { start(s); }
|
||||
BasicStrfnd(const T *ptr) { str = ptr; pos = 0; }
|
||||
BasicStrfnd(std::basic_string_view<T> sv) { str = sv; pos = 0; }
|
||||
|
||||
void start(const String &s) { str = s; pos = 0; }
|
||||
size_t where() { return pos; }
|
||||
void to(size_t i) { pos = i; }
|
||||
|
|
|
@ -82,14 +82,14 @@ const char *DEFAULT_ENCODING = "UTF-32LE";
|
|||
const char *DEFAULT_ENCODING = "WCHAR_T";
|
||||
#endif
|
||||
|
||||
std::wstring utf8_to_wide(const std::string &input)
|
||||
std::wstring utf8_to_wide(std::string_view input)
|
||||
{
|
||||
const size_t inbuf_size = input.length();
|
||||
// maximum possible size, every character is sizeof(wchar_t) bytes
|
||||
size_t outbuf_size = input.length() * sizeof(wchar_t);
|
||||
|
||||
char *inbuf = new char[inbuf_size]; // intentionally NOT null-terminated
|
||||
memcpy(inbuf, input.c_str(), inbuf_size);
|
||||
memcpy(inbuf, input.data(), inbuf_size);
|
||||
std::wstring out;
|
||||
out.resize(outbuf_size / sizeof(wchar_t));
|
||||
|
||||
|
@ -110,14 +110,14 @@ std::wstring utf8_to_wide(const std::string &input)
|
|||
return out;
|
||||
}
|
||||
|
||||
std::string wide_to_utf8(const std::wstring &input)
|
||||
std::string wide_to_utf8(std::wstring_view input)
|
||||
{
|
||||
const size_t inbuf_size = input.length() * sizeof(wchar_t);
|
||||
// maximum possible size: utf-8 encodes codepoints using 1 up to 4 bytes
|
||||
size_t outbuf_size = input.length() * 4;
|
||||
|
||||
char *inbuf = new char[inbuf_size]; // intentionally NOT null-terminated
|
||||
memcpy(inbuf, input.c_str(), inbuf_size);
|
||||
memcpy(inbuf, input.data(), inbuf_size);
|
||||
std::string out;
|
||||
out.resize(outbuf_size);
|
||||
|
||||
|
@ -135,24 +135,24 @@ std::string wide_to_utf8(const std::wstring &input)
|
|||
|
||||
#else // _WIN32
|
||||
|
||||
std::wstring utf8_to_wide(const std::string &input)
|
||||
std::wstring utf8_to_wide(std::string_view input)
|
||||
{
|
||||
size_t outbuf_size = input.size() + 1;
|
||||
wchar_t *outbuf = new wchar_t[outbuf_size];
|
||||
memset(outbuf, 0, outbuf_size * sizeof(wchar_t));
|
||||
MultiByteToWideChar(CP_UTF8, 0, input.c_str(), input.size(),
|
||||
MultiByteToWideChar(CP_UTF8, 0, input.data(), input.size(),
|
||||
outbuf, outbuf_size);
|
||||
std::wstring out(outbuf);
|
||||
delete[] outbuf;
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string wide_to_utf8(const std::wstring &input)
|
||||
std::string wide_to_utf8(std::wstring_view input)
|
||||
{
|
||||
size_t outbuf_size = (input.size() + 1) * 6;
|
||||
char *outbuf = new char[outbuf_size];
|
||||
memset(outbuf, 0, outbuf_size);
|
||||
WideCharToMultiByte(CP_UTF8, 0, input.c_str(), input.size(),
|
||||
WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(),
|
||||
outbuf, outbuf_size, NULL, NULL);
|
||||
std::string out(outbuf);
|
||||
delete[] outbuf;
|
||||
|
@ -162,9 +162,9 @@ std::string wide_to_utf8(const std::wstring &input)
|
|||
#endif // _WIN32
|
||||
|
||||
|
||||
std::string urlencode(const std::string &str)
|
||||
std::string urlencode(std::string_view str)
|
||||
{
|
||||
// Encodes non-unreserved URI characters by a percent sign
|
||||
// Encodes reserved URI characters by a percent sign
|
||||
// followed by two hex digits. See RFC 3986, section 2.3.
|
||||
static const char url_hex_chars[] = "0123456789ABCDEF";
|
||||
std::ostringstream oss(std::ios::binary);
|
||||
|
@ -180,7 +180,7 @@ std::string urlencode(const std::string &str)
|
|||
return oss.str();
|
||||
}
|
||||
|
||||
std::string urldecode(const std::string &str)
|
||||
std::string urldecode(std::string_view str)
|
||||
{
|
||||
// Inverse of urlencode
|
||||
std::ostringstream oss(std::ios::binary);
|
||||
|
@ -615,10 +615,10 @@ void str_replace(std::string &str, char from, char to)
|
|||
* before filling it again.
|
||||
*/
|
||||
|
||||
void translate_all(const std::wstring &s, size_t &i,
|
||||
static void translate_all(const std::wstring &s, size_t &i,
|
||||
Translations *translations, std::wstring &res);
|
||||
|
||||
void translate_string(const std::wstring &s, Translations *translations,
|
||||
static void translate_string(const std::wstring &s, Translations *translations,
|
||||
const std::wstring &textdomain, size_t &i, std::wstring &res)
|
||||
{
|
||||
std::wostringstream output;
|
||||
|
@ -732,14 +732,15 @@ void translate_string(const std::wstring &s, Translations *translations,
|
|||
res = result.str();
|
||||
}
|
||||
|
||||
void translate_all(const std::wstring &s, size_t &i,
|
||||
static void translate_all(const std::wstring &s, size_t &i,
|
||||
Translations *translations, std::wstring &res)
|
||||
{
|
||||
std::wostringstream output;
|
||||
res.clear();
|
||||
res.reserve(s.length());
|
||||
while (i < s.length()) {
|
||||
// Not an escape sequence: just add the character.
|
||||
if (s[i] != '\x1b') {
|
||||
output.put(s[i]);
|
||||
res.append(1, s[i]);
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
@ -747,7 +748,7 @@ void translate_all(const std::wstring &s, size_t &i,
|
|||
// We have an escape sequence: locate it and its data
|
||||
// It is either a single character, or it begins with '('
|
||||
// and extends up to the following ')', with '\' as an escape character.
|
||||
size_t escape_start = i;
|
||||
const size_t escape_start = i;
|
||||
++i;
|
||||
size_t start_index = i;
|
||||
size_t length;
|
||||
|
@ -784,14 +785,12 @@ void translate_all(const std::wstring &s, size_t &i,
|
|||
textdomain = parts[1];
|
||||
std::wstring translated;
|
||||
translate_string(s, translations, textdomain, i, translated);
|
||||
output << translated;
|
||||
res.append(translated);
|
||||
} else {
|
||||
// Another escape sequence, such as colors. Preserve it.
|
||||
output << std::wstring(s, escape_start, i - escape_start);
|
||||
res.append(&s[escape_start], i - escape_start);
|
||||
}
|
||||
}
|
||||
|
||||
res = output.str();
|
||||
}
|
||||
|
||||
// Translate string server side
|
||||
|
@ -813,7 +812,7 @@ std::wstring translate_string(const std::wstring &s)
|
|||
#endif
|
||||
}
|
||||
|
||||
static const std::array<std::wstring, 30> disallowed_dir_names = {
|
||||
static const std::array<std::wstring_view, 30> disallowed_dir_names = {
|
||||
// Problematic filenames from here:
|
||||
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#file-and-directory-names
|
||||
// Plus undocumented values from here:
|
||||
|
@ -853,10 +852,10 @@ static const std::array<std::wstring, 30> disallowed_dir_names = {
|
|||
/**
|
||||
* List of characters that are blacklisted from created directories
|
||||
*/
|
||||
static const std::wstring disallowed_path_chars = L"<>:\"/\\|?*.";
|
||||
static const std::wstring_view disallowed_path_chars = L"<>:\"/\\|?*.";
|
||||
|
||||
|
||||
std::string sanitizeDirName(const std::string &str, const std::string &optional_prefix)
|
||||
std::string sanitizeDirName(std::string_view str, std::string_view optional_prefix)
|
||||
{
|
||||
std::wstring safe_name = utf8_to_wide(str);
|
||||
|
||||
|
@ -897,7 +896,7 @@ std::string sanitizeDirName(const std::string &str, const std::string &optional_
|
|||
}
|
||||
|
||||
|
||||
void safe_print_string(std::ostream &os, const std::string &str)
|
||||
void safe_print_string(std::ostream &os, std::string_view str)
|
||||
{
|
||||
std::ostream::fmtflags flags = os.flags();
|
||||
os << std::hex;
|
||||
|
@ -913,7 +912,7 @@ void safe_print_string(std::ostream &os, const std::string &str)
|
|||
}
|
||||
|
||||
|
||||
v3f str_to_v3f(const std::string &str)
|
||||
v3f str_to_v3f(std::string_view str)
|
||||
{
|
||||
v3f value;
|
||||
Strfnd f(str);
|
||||
|
|
|
@ -23,10 +23,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "irrString.h"
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <cctype>
|
||||
|
@ -76,15 +76,18 @@ struct FlagDesc {
|
|||
|
||||
// Try to avoid converting between wide and UTF-8 unless you need to
|
||||
// input/output stuff via Irrlicht
|
||||
std::wstring utf8_to_wide(const std::string &input);
|
||||
std::string wide_to_utf8(const std::wstring &input);
|
||||
std::wstring utf8_to_wide(std::string_view input);
|
||||
std::string wide_to_utf8(std::wstring_view input);
|
||||
|
||||
std::string urlencode(std::string_view str);
|
||||
std::string urldecode(std::string_view str);
|
||||
|
||||
std::string urlencode(const std::string &str);
|
||||
std::string urldecode(const std::string &str);
|
||||
u32 readFlagString(std::string str, const FlagDesc *flagdesc, u32 *flagmask);
|
||||
std::string writeFlagString(u32 flags, const FlagDesc *flagdesc, u32 flagmask);
|
||||
|
||||
size_t mystrlcpy(char *dst, const char *src, size_t size) noexcept;
|
||||
char *mystrtok_r(char *s, const char *sep, char **lasts) noexcept;
|
||||
|
||||
u64 read_seed(const char *str);
|
||||
bool parseColorString(const std::string &value, video::SColor &color, bool quiet,
|
||||
unsigned char default_alpha = 0xff);
|
||||
|
@ -115,23 +118,32 @@ inline std::string padStringRight(std::string str, size_t len)
|
|||
*
|
||||
* @return If no end could be removed then "" is returned.
|
||||
*/
|
||||
inline std::string removeStringEnd(const std::string &str,
|
||||
inline std::string_view removeStringEnd(std::string_view str,
|
||||
const char *ends[])
|
||||
{
|
||||
const char **p = ends;
|
||||
|
||||
for (; *p && (*p)[0] != '\0'; p++) {
|
||||
std::string end = *p;
|
||||
std::string_view end(*p);
|
||||
if (str.size() < end.size())
|
||||
continue;
|
||||
if (str.compare(str.size() - end.size(), end.size(), end) == 0)
|
||||
return str.substr(0, str.size() - end.size());
|
||||
}
|
||||
|
||||
return "";
|
||||
return std::string_view();
|
||||
}
|
||||
|
||||
|
||||
#define MAKE_VARIANT(_name, _t0, _t1) \
|
||||
template <typename T, typename... Args> \
|
||||
inline auto _name(_t0 arg1, _t1 arg2, Args&&... args) \
|
||||
{ \
|
||||
return (_name)(std::basic_string_view<T>(arg1), std::basic_string_view<T>(arg2), \
|
||||
std::forward<Args>(args)...); \
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check two strings for equivalence. If \p case_insensitive is true
|
||||
* then the case of the strings is ignored (default is false).
|
||||
|
@ -142,8 +154,8 @@ inline std::string removeStringEnd(const std::string &str,
|
|||
* @return true if the strings match
|
||||
*/
|
||||
template <typename T>
|
||||
inline bool str_equal(const std::basic_string<T> &s1,
|
||||
const std::basic_string<T> &s2,
|
||||
inline bool str_equal(std::basic_string_view<T> s1,
|
||||
std::basic_string_view<T> s2,
|
||||
bool case_insensitive = false)
|
||||
{
|
||||
if (!case_insensitive)
|
||||
|
@ -159,6 +171,16 @@ inline bool str_equal(const std::basic_string<T> &s1,
|
|||
return true;
|
||||
}
|
||||
|
||||
// For some reason an std::string will not implicitly get converted
|
||||
// to an std::basic_string_view<char> in the template case above, so we need
|
||||
// these three wrappers. It works if you take out the template parameters.
|
||||
// see also <https://stackoverflow.com/questions/68380141/>
|
||||
MAKE_VARIANT(str_equal, const std::basic_string<T> &, const std::basic_string<T> &)
|
||||
|
||||
MAKE_VARIANT(str_equal, std::basic_string_view<T>, const std::basic_string<T> &)
|
||||
|
||||
MAKE_VARIANT(str_equal, const std::basic_string<T> &, std::basic_string_view<T>)
|
||||
|
||||
|
||||
/**
|
||||
* Check whether \p str begins with the string prefix. If \p case_insensitive
|
||||
|
@ -171,8 +193,8 @@ inline bool str_equal(const std::basic_string<T> &s1,
|
|||
* @return true if the str begins with prefix
|
||||
*/
|
||||
template <typename T>
|
||||
inline bool str_starts_with(const std::basic_string<T> &str,
|
||||
const std::basic_string<T> &prefix,
|
||||
inline bool str_starts_with(std::basic_string_view<T> str,
|
||||
std::basic_string_view<T> prefix,
|
||||
bool case_insensitive = false)
|
||||
{
|
||||
if (str.size() < prefix.size())
|
||||
|
@ -187,24 +209,17 @@ inline bool str_starts_with(const std::basic_string<T> &str,
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether \p str begins with the string prefix. If \p case_insensitive
|
||||
* is true then the check is case insensitve (default is false; i.e. case is
|
||||
* significant).
|
||||
*
|
||||
* @param str
|
||||
* @param prefix
|
||||
* @param case_insensitive
|
||||
* @return true if the str begins with prefix
|
||||
*/
|
||||
template <typename T>
|
||||
inline bool str_starts_with(const std::basic_string<T> &str,
|
||||
const T *prefix,
|
||||
bool case_insensitive = false)
|
||||
{
|
||||
return str_starts_with(str, std::basic_string<T>(prefix),
|
||||
case_insensitive);
|
||||
}
|
||||
// (same conversion issue here)
|
||||
MAKE_VARIANT(str_starts_with, const std::basic_string<T> &, const std::basic_string<T> &)
|
||||
|
||||
MAKE_VARIANT(str_starts_with, std::basic_string_view<T>, const std::basic_string<T> &)
|
||||
|
||||
MAKE_VARIANT(str_starts_with, const std::basic_string<T> &, std::basic_string_view<T>)
|
||||
|
||||
// (the same but with char pointers, only for the prefix argument)
|
||||
MAKE_VARIANT(str_starts_with, const std::basic_string<T> &, const T*)
|
||||
|
||||
MAKE_VARIANT(str_starts_with, std::basic_string_view<T>, const T*)
|
||||
|
||||
|
||||
/**
|
||||
|
@ -218,8 +233,8 @@ inline bool str_starts_with(const std::basic_string<T> &str,
|
|||
* @return true if the str begins with suffix
|
||||
*/
|
||||
template <typename T>
|
||||
inline bool str_ends_with(const std::basic_string<T> &str,
|
||||
const std::basic_string<T> &suffix,
|
||||
inline bool str_ends_with(std::basic_string_view<T> str,
|
||||
std::basic_string_view<T> suffix,
|
||||
bool case_insensitive = false)
|
||||
{
|
||||
if (str.size() < suffix.size())
|
||||
|
@ -235,25 +250,20 @@ inline bool str_ends_with(const std::basic_string<T> &str,
|
|||
return true;
|
||||
}
|
||||
|
||||
// (same conversion issue here)
|
||||
MAKE_VARIANT(str_ends_with, const std::basic_string<T> &, const std::basic_string<T> &)
|
||||
|
||||
/**
|
||||
* Check whether \p str ends with the string suffix. If \p case_insensitive
|
||||
* is true then the check is case insensitve (default is false; i.e. case is
|
||||
* significant).
|
||||
*
|
||||
* @param str
|
||||
* @param suffix
|
||||
* @param case_insensitive
|
||||
* @return true if the str begins with suffix
|
||||
*/
|
||||
template <typename T>
|
||||
inline bool str_ends_with(const std::basic_string<T> &str,
|
||||
const T *suffix,
|
||||
bool case_insensitive = false)
|
||||
{
|
||||
return str_ends_with(str, std::basic_string<T>(suffix),
|
||||
case_insensitive);
|
||||
}
|
||||
MAKE_VARIANT(str_ends_with, std::basic_string_view<T>, const std::basic_string<T> &)
|
||||
|
||||
MAKE_VARIANT(str_ends_with, const std::basic_string<T> &, std::basic_string_view<T>)
|
||||
|
||||
// (the same but with char pointers, only for the suffix argument)
|
||||
MAKE_VARIANT(str_ends_with, const std::basic_string<T> &, const T*)
|
||||
|
||||
MAKE_VARIANT(str_ends_with, std::basic_string_view<T>, const T*)
|
||||
|
||||
|
||||
#undef MAKE_VARIANT
|
||||
|
||||
|
||||
/**
|
||||
|
@ -282,24 +292,21 @@ inline std::vector<std::basic_string<T> > str_split(
|
|||
* @param str
|
||||
* @return A copy of \p str converted to all lowercase characters.
|
||||
*/
|
||||
inline std::string lowercase(const std::string &str)
|
||||
inline std::string lowercase(std::string_view str)
|
||||
{
|
||||
std::string s2;
|
||||
|
||||
s2.reserve(str.size());
|
||||
|
||||
for (char i : str)
|
||||
s2 += tolower(i);
|
||||
|
||||
s2.resize(str.size());
|
||||
for (size_t i = 0; i < str.size(); i++)
|
||||
s2[i] = tolower(str[i]);
|
||||
return s2;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param str
|
||||
* @return A copy of \p str with leading and trailing whitespace removed.
|
||||
* @return A view of \p str with leading and trailing whitespace removed.
|
||||
*/
|
||||
inline std::string trim(const std::string &str)
|
||||
inline std::string_view trim(std::string_view str)
|
||||
{
|
||||
size_t front = 0;
|
||||
size_t back = str.size();
|
||||
|
@ -313,6 +320,26 @@ inline std::string trim(const std::string &str)
|
|||
return str.substr(front, back - front);
|
||||
}
|
||||
|
||||
// If input was a temporary string keep it one to make sure patterns like
|
||||
// trim(func_that_returns_str()) are predictable regarding memory allocation
|
||||
// and don't lead to UAF. ↓ ↓ ↓
|
||||
|
||||
/**
|
||||
* @param str
|
||||
* @return A copy of \p str with leading and trailing whitespace removed.
|
||||
*/
|
||||
inline std::string trim(std::string &&str)
|
||||
{
|
||||
std::string ret(trim(std::string_view(str)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// The above declaration causes ambiguity with char pointers so we have to fix that:
|
||||
inline std::string_view trim(const char *str)
|
||||
{
|
||||
return trim(std::string_view(str));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether \p str should be regarded as (bool) true. Case and leading
|
||||
|
@ -320,7 +347,7 @@ inline std::string trim(const std::string &str)
|
|||
* true are "y", "yes", "true" and any number that is not 0.
|
||||
* @param str
|
||||
*/
|
||||
inline bool is_yes(const std::string &str)
|
||||
inline bool is_yes(std::string_view str)
|
||||
{
|
||||
std::string s2 = lowercase(trim(str));
|
||||
|
||||
|
@ -377,7 +404,7 @@ inline float mystof(const std::string &str)
|
|||
template <typename T>
|
||||
inline T from_string(const std::string &str)
|
||||
{
|
||||
std::stringstream tmp(str);
|
||||
std::istringstream tmp(str);
|
||||
T t;
|
||||
tmp >> t;
|
||||
return t;
|
||||
|
@ -386,42 +413,6 @@ inline T from_string(const std::string &str)
|
|||
/// Returns a 64-bit signed value represented by the string \p str (decimal).
|
||||
inline s64 stoi64(const std::string &str) { return from_string<s64>(str); }
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
namespace std {
|
||||
|
||||
/// Returns a string representing the value \p val.
|
||||
template <typename T>
|
||||
inline string to_string(T val)
|
||||
{
|
||||
ostringstream oss;
|
||||
oss << val;
|
||||
return oss.str();
|
||||
}
|
||||
#define DEFINE_STD_TOSTRING_FLOATINGPOINT(T) \
|
||||
template <> \
|
||||
inline string to_string<T>(T val) \
|
||||
{ \
|
||||
ostringstream oss; \
|
||||
oss << std::fixed \
|
||||
<< std::setprecision(6) \
|
||||
<< val; \
|
||||
return oss.str(); \
|
||||
}
|
||||
DEFINE_STD_TOSTRING_FLOATINGPOINT(float)
|
||||
DEFINE_STD_TOSTRING_FLOATINGPOINT(double)
|
||||
DEFINE_STD_TOSTRING_FLOATINGPOINT(long double)
|
||||
|
||||
#undef DEFINE_STD_TOSTRING_FLOATINGPOINT
|
||||
|
||||
/// Returns a wide string representing the value \p val
|
||||
template <typename T>
|
||||
inline wstring to_wstring(T val)
|
||||
{
|
||||
return utf8_to_wide(to_string(val));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Returns a string representing the decimal value of the 32-bit value \p i.
|
||||
inline std::string itos(s32 i) { return std::to_string(i); }
|
||||
/// Returns a string representing the decimal value of the 64-bit value \p i.
|
||||
|
@ -443,8 +434,8 @@ inline std::string ftos(float f)
|
|||
* @param pattern The pattern to replace.
|
||||
* @param replacement What to replace the pattern with.
|
||||
*/
|
||||
inline void str_replace(std::string &str, const std::string &pattern,
|
||||
const std::string &replacement)
|
||||
inline void str_replace(std::string &str, std::string_view pattern,
|
||||
std::string_view replacement)
|
||||
{
|
||||
std::string::size_type start = str.find(pattern, 0);
|
||||
while (start != str.npos) {
|
||||
|
@ -454,7 +445,7 @@ inline void str_replace(std::string &str, const std::string &pattern,
|
|||
}
|
||||
|
||||
/**
|
||||
* Escapes characters [ ] \ , ; that cannot be used in formspecs
|
||||
* Escapes characters that cannot be used in formspecs
|
||||
*/
|
||||
inline void str_formspec_escape(std::string &str)
|
||||
{
|
||||
|
@ -486,7 +477,7 @@ void str_replace(std::string &str, char from, char to);
|
|||
*
|
||||
* @see string_allowed_blacklist()
|
||||
*/
|
||||
inline bool string_allowed(const std::string &str, const std::string &allowed_chars)
|
||||
inline bool string_allowed(std::string_view str, std::string_view allowed_chars)
|
||||
{
|
||||
return str.find_first_not_of(allowed_chars) == str.npos;
|
||||
}
|
||||
|
@ -502,8 +493,8 @@ inline bool string_allowed(const std::string &str, const std::string &allowed_ch
|
|||
|
||||
* @see string_allowed()
|
||||
*/
|
||||
inline bool string_allowed_blacklist(const std::string &str,
|
||||
const std::string &blacklisted_chars)
|
||||
inline bool string_allowed_blacklist(std::string_view str,
|
||||
std::string_view blacklisted_chars)
|
||||
{
|
||||
return str.find_first_of(blacklisted_chars) == str.npos;
|
||||
}
|
||||
|
@ -524,12 +515,12 @@ inline bool string_allowed_blacklist(const std::string &str,
|
|||
* @param row_len The row length (in characters).
|
||||
* @return A new string with the wrapping applied.
|
||||
*/
|
||||
inline std::string wrap_rows(const std::string &from,
|
||||
unsigned row_len)
|
||||
inline std::string wrap_rows(std::string_view from, unsigned row_len)
|
||||
{
|
||||
std::string to;
|
||||
to.reserve(from.size());
|
||||
|
||||
size_t character_idx = 0;
|
||||
unsigned character_idx = 0;
|
||||
for (size_t i = 0; i < from.size(); i++) {
|
||||
if (!IS_UTF8_MULTB_INNER(from[i])) {
|
||||
// Wrap string after last inner byte of char
|
||||
|
@ -551,6 +542,7 @@ template <typename T>
|
|||
inline std::basic_string<T> unescape_string(const std::basic_string<T> &s)
|
||||
{
|
||||
std::basic_string<T> res;
|
||||
res.reserve(s.size());
|
||||
|
||||
for (size_t i = 0; i < s.length(); i++) {
|
||||
if (s[i] == '\\') {
|
||||
|
@ -574,6 +566,7 @@ template <typename T>
|
|||
std::basic_string<T> unescape_enriched(const std::basic_string<T> &s)
|
||||
{
|
||||
std::basic_string<T> output;
|
||||
output.reserve(s.size());
|
||||
size_t i = 0;
|
||||
while (i < s.length()) {
|
||||
if (s[i] == '\x1b') {
|
||||
|
@ -646,7 +639,7 @@ inline std::wstring unescape_translate(const std::wstring &s) {
|
|||
* @return true if to_check is not empty and all characters in to_check are
|
||||
* decimal digits, otherwise false
|
||||
*/
|
||||
inline bool is_number(const std::string &to_check)
|
||||
inline bool is_number(std::string_view to_check)
|
||||
{
|
||||
for (char i : to_check)
|
||||
if (!std::isdigit(i))
|
||||
|
@ -720,7 +713,7 @@ inline const std::string duration_to_string(int sec)
|
|||
* @return A std::string
|
||||
*/
|
||||
inline std::string str_join(const std::vector<std::string> &list,
|
||||
const std::string &delimiter)
|
||||
std::string_view delimiter)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
bool first = true;
|
||||
|
@ -738,17 +731,17 @@ inline std::string str_join(const std::vector<std::string> &list,
|
|||
*/
|
||||
inline std::string stringw_to_utf8(const irr::core::stringw &input)
|
||||
{
|
||||
std::wstring str(input.c_str());
|
||||
return wide_to_utf8(str);
|
||||
std::wstring_view sv(input.c_str(), input.size());
|
||||
return wide_to_utf8(sv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an irr::core:stringw from a UTF8 std::string.
|
||||
*/
|
||||
inline irr::core::stringw utf8_to_stringw(const std::string &input)
|
||||
inline irr::core::stringw utf8_to_stringw(std::string_view input)
|
||||
{
|
||||
std::wstring str = utf8_to_wide(input);
|
||||
return irr::core::stringw(str.c_str());
|
||||
return irr::core::stringw(str.c_str(), str.size());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -757,7 +750,7 @@ inline irr::core::stringw utf8_to_stringw(const std::string &input)
|
|||
* and add a prefix to them
|
||||
* 2. Remove 'unsafe' characters from the name by replacing them with '_'
|
||||
*/
|
||||
std::string sanitizeDirName(const std::string &str, const std::string &optional_prefix);
|
||||
std::string sanitizeDirName(std::string_view str, std::string_view optional_prefix);
|
||||
|
||||
/**
|
||||
* Prints a sanitized version of a string without control characters.
|
||||
|
@ -765,12 +758,12 @@ std::string sanitizeDirName(const std::string &str, const std::string &optional_
|
|||
* ASCII control characters are replaced with their hex encoding in angle
|
||||
* brackets (e.g. "a\x1eb" -> "a<1e>b").
|
||||
*/
|
||||
void safe_print_string(std::ostream &os, const std::string &str);
|
||||
void safe_print_string(std::ostream &os, std::string_view str);
|
||||
|
||||
/**
|
||||
* Parses a string of form `(1, 2, 3)` to a v3f
|
||||
*
|
||||
* @param str String
|
||||
* @return
|
||||
* @param str string
|
||||
* @return float vector
|
||||
*/
|
||||
v3f str_to_v3f(const std::string &str);
|
||||
v3f str_to_v3f(std::string_view str);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue