aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorElias Fleckenstein <eliasfleckenstein@web.de>2022-05-17 22:12:00 +0200
committerElias Fleckenstein <eliasfleckenstein@web.de>2022-05-17 22:12:00 +0200
commit21df26984da91143c15587f5a03c98d68c3adc4e (patch)
treeaaa707a628ad331f67890023dffe1b4f60dd01d3 /src/util
parentb09fc5de5cdb021f43ad32b7e3f50dc75c0bc622 (diff)
parenteabf05758e3ba5f6f4bb1b8d1d1f02179b84e410 (diff)
downloaddragonfireclient-21df26984da91143c15587f5a03c98d68c3adc4e.tar.xz
Merge branch 'master' of https://github.com/minetest/minetest
Diffstat (limited to 'src/util')
-rw-r--r--src/util/Optional.h32
-rw-r--r--src/util/areastore.cpp1
-rw-r--r--src/util/basic_macros.h8
-rw-r--r--src/util/ieee_float.cpp2
-rw-r--r--src/util/metricsbackend.cpp96
-rw-r--r--src/util/metricsbackend.h84
-rwxr-xr-xsrc/util/png.cpp8
-rw-r--r--src/util/pointer.h58
-rw-r--r--src/util/srp.cpp4
-rw-r--r--src/util/stream.h70
-rw-r--r--src/util/string.cpp70
-rw-r--r--src/util/string.h47
12 files changed, 331 insertions, 149 deletions
diff --git a/src/util/Optional.h b/src/util/Optional.h
index 9c2842b43..eda7fff89 100644
--- a/src/util/Optional.h
+++ b/src/util/Optional.h
@@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
+#include <utility>
#include "debug.h"
struct nullopt_t
@@ -43,18 +44,38 @@ class Optional
public:
Optional() noexcept {}
Optional(nullopt_t) noexcept {}
+
Optional(const T &value) noexcept : m_has_value(true), m_value(value) {}
+ Optional(T &&value) noexcept : m_has_value(true), m_value(std::move(value)) {}
+
Optional(const Optional<T> &other) noexcept :
m_has_value(other.m_has_value), m_value(other.m_value)
+ {}
+ Optional(Optional<T> &&other) noexcept :
+ m_has_value(other.m_has_value), m_value(std::move(other.m_value))
{
+ other.m_has_value = false;
}
- void operator=(nullopt_t) noexcept { m_has_value = false; }
+ Optional<T> &operator=(nullopt_t) noexcept { m_has_value = false; return *this; }
- void operator=(const Optional<T> &other) noexcept
+ Optional<T> &operator=(const Optional<T> &other) noexcept
{
+ if (&other == this)
+ return *this;
m_has_value = other.m_has_value;
m_value = other.m_value;
+ return *this;
+ }
+
+ Optional<T> &operator=(Optional<T> &&other) noexcept
+ {
+ if (&other == this)
+ return *this;
+ m_has_value = other.m_has_value;
+ m_value = std::move(other.m_value);
+ other.m_has_value = false;
+ return *this;
}
T &value()
@@ -71,6 +92,13 @@ public:
const T &value_or(const T &def) const { return m_has_value ? m_value : def; }
+ // Unchecked access consistent with std::optional
+ T* operator->() { return &m_value; }
+ const T* operator->() const { return &m_value; }
+
+ T& operator*() { return m_value; }
+ const T& operator*() const { return m_value; }
+
bool has_value() const noexcept { return m_has_value; }
explicit operator bool() const { return m_has_value; }
diff --git a/src/util/areastore.cpp b/src/util/areastore.cpp
index 67bfef0c0..bf751476f 100644
--- a/src/util/areastore.cpp
+++ b/src/util/areastore.cpp
@@ -308,6 +308,7 @@ void SpatialAreaStore::getAreasInArea(std::vector<Area *> *result,
SpatialAreaStore::~SpatialAreaStore()
{
delete m_tree;
+ delete m_storagemanager;
}
SpatialAreaStore::SpatialAreaStore()
diff --git a/src/util/basic_macros.h b/src/util/basic_macros.h
index 334e342e0..3910c6185 100644
--- a/src/util/basic_macros.h
+++ b/src/util/basic_macros.h
@@ -29,13 +29,19 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define CONTAINS(c, v) (std::find((c).begin(), (c).end(), (v)) != (c).end())
// To disable copy constructors and assignment operations for some class
-// 'Foobar', add the macro DISABLE_CLASS_COPY(Foobar) as a private member.
+// 'Foobar', add the macro DISABLE_CLASS_COPY(Foobar) in the class definition.
// Note this also disables copying for any classes derived from 'Foobar' as well
// as classes having a 'Foobar' member.
#define DISABLE_CLASS_COPY(C) \
C(const C &) = delete; \
C &operator=(const C &) = delete;
+// If you have used DISABLE_CLASS_COPY with a class but still want to permit moving
+// use this macro to add the default move constructors back.
+#define ALLOW_CLASS_MOVE(C) \
+ C(C &&other) = default; \
+ C &operator=(C &&) = default;
+
#ifndef _MSC_VER
#define UNUSED_ATTRIBUTE __attribute__ ((unused))
#else
diff --git a/src/util/ieee_float.cpp b/src/util/ieee_float.cpp
index 887258921..b73763c55 100644
--- a/src/util/ieee_float.cpp
+++ b/src/util/ieee_float.cpp
@@ -39,7 +39,7 @@ f32 u32Tof32Slow(u32 i)
if (exp == 0xFF) {
// Inf/NaN
if (imant == 0) {
- if (std::numeric_limits<f32>::has_infinity)
+ if (std::numeric_limits<f32>::has_infinity)
return sign ? -std::numeric_limits<f32>::infinity() :
std::numeric_limits<f32>::infinity();
return sign ? std::numeric_limits<f32>::max() :
diff --git a/src/util/metricsbackend.cpp b/src/util/metricsbackend.cpp
index 4454557a3..63b49ac0a 100644
--- a/src/util/metricsbackend.cpp
+++ b/src/util/metricsbackend.cpp
@@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include "metricsbackend.h"
+#include "util/thread.h"
#if USE_PROMETHEUS
#include <prometheus/exposer.h>
#include <prometheus/registry.h>
@@ -27,18 +28,78 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "settings.h"
#endif
+/* Plain implementation */
+
+class SimpleMetricCounter : public MetricCounter
+{
+public:
+ SimpleMetricCounter() : MetricCounter(), m_counter(0.0) {}
+
+ virtual ~SimpleMetricCounter() {}
+
+ void increment(double number) override
+ {
+ MutexAutoLock lock(m_mutex);
+ m_counter += number;
+ }
+ double get() const override
+ {
+ MutexAutoLock lock(m_mutex);
+ return m_counter;
+ }
+
+private:
+ mutable std::mutex m_mutex;
+ double m_counter;
+};
+
+class SimpleMetricGauge : public MetricGauge
+{
+public:
+ SimpleMetricGauge() : MetricGauge(), m_gauge(0.0) {}
+
+ virtual ~SimpleMetricGauge() {}
+
+ void increment(double number) override
+ {
+ MutexAutoLock lock(m_mutex);
+ m_gauge += number;
+ }
+ void decrement(double number) override
+ {
+ MutexAutoLock lock(m_mutex);
+ m_gauge -= number;
+ }
+ void set(double number) override
+ {
+ MutexAutoLock lock(m_mutex);
+ m_gauge = number;
+ }
+ double get() const override
+ {
+ MutexAutoLock lock(m_mutex);
+ return m_gauge;
+ }
+
+private:
+ mutable std::mutex m_mutex;
+ double m_gauge;
+};
+
MetricCounterPtr MetricsBackend::addCounter(
- const std::string &name, const std::string &help_str)
+ const std::string &name, const std::string &help_str, Labels labels)
{
- return std::make_shared<SimpleMetricCounter>(name, help_str);
+ return std::make_shared<SimpleMetricCounter>();
}
MetricGaugePtr MetricsBackend::addGauge(
- const std::string &name, const std::string &help_str)
+ const std::string &name, const std::string &help_str, Labels labels)
{
- return std::make_shared<SimpleMetricGauge>(name, help_str);
+ return std::make_shared<SimpleMetricGauge>();
}
+/* Prometheus backend */
+
#if USE_PROMETHEUS
class PrometheusMetricCounter : public MetricCounter
@@ -47,13 +108,14 @@ public:
PrometheusMetricCounter() = delete;
PrometheusMetricCounter(const std::string &name, const std::string &help_str,
+ MetricsBackend::Labels labels,
std::shared_ptr<prometheus::Registry> registry) :
MetricCounter(),
m_family(prometheus::BuildCounter()
.Name(name)
.Help(help_str)
.Register(*registry)),
- m_counter(m_family.Add({}))
+ m_counter(m_family.Add(labels))
{
}
@@ -73,13 +135,14 @@ public:
PrometheusMetricGauge() = delete;
PrometheusMetricGauge(const std::string &name, const std::string &help_str,
+ MetricsBackend::Labels labels,
std::shared_ptr<prometheus::Registry> registry) :
MetricGauge(),
m_family(prometheus::BuildGauge()
.Name(name)
.Help(help_str)
.Register(*registry)),
- m_gauge(m_family.Add({}))
+ m_gauge(m_family.Add(labels))
{
}
@@ -99,8 +162,7 @@ class PrometheusMetricsBackend : public MetricsBackend
{
public:
PrometheusMetricsBackend(const std::string &addr) :
- MetricsBackend(), m_exposer(std::unique_ptr<prometheus::Exposer>(
- new prometheus::Exposer(addr))),
+ MetricsBackend(), m_exposer(std::make_unique<prometheus::Exposer>(addr)),
m_registry(std::make_shared<prometheus::Registry>())
{
m_exposer->RegisterCollectable(m_registry);
@@ -108,10 +170,12 @@ public:
virtual ~PrometheusMetricsBackend() {}
- virtual MetricCounterPtr addCounter(
- const std::string &name, const std::string &help_str);
- virtual MetricGaugePtr addGauge(
- const std::string &name, const std::string &help_str);
+ MetricCounterPtr addCounter(
+ const std::string &name, const std::string &help_str,
+ Labels labels = {}) override;
+ MetricGaugePtr addGauge(
+ const std::string &name, const std::string &help_str,
+ Labels labels = {}) override;
private:
std::unique_ptr<prometheus::Exposer> m_exposer;
@@ -119,15 +183,15 @@ private:
};
MetricCounterPtr PrometheusMetricsBackend::addCounter(
- const std::string &name, const std::string &help_str)
+ const std::string &name, const std::string &help_str, Labels labels)
{
- return std::make_shared<PrometheusMetricCounter>(name, help_str, m_registry);
+ return std::make_shared<PrometheusMetricCounter>(name, help_str, labels, m_registry);
}
MetricGaugePtr PrometheusMetricsBackend::addGauge(
- const std::string &name, const std::string &help_str)
+ const std::string &name, const std::string &help_str, Labels labels)
{
- return std::make_shared<PrometheusMetricGauge>(name, help_str, m_registry);
+ return std::make_shared<PrometheusMetricGauge>(name, help_str, labels, m_registry);
}
MetricsBackend *createPrometheusMetricsBackend()
diff --git a/src/util/metricsbackend.h b/src/util/metricsbackend.h
index c37306392..644c73325 100644
--- a/src/util/metricsbackend.h
+++ b/src/util/metricsbackend.h
@@ -19,8 +19,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include <memory>
+#include <string>
+#include <utility>
#include "config.h"
-#include "util/thread.h"
class MetricCounter
{
@@ -35,38 +36,6 @@ public:
typedef std::shared_ptr<MetricCounter> MetricCounterPtr;
-class SimpleMetricCounter : public MetricCounter
-{
-public:
- SimpleMetricCounter() = delete;
-
- virtual ~SimpleMetricCounter() {}
-
- SimpleMetricCounter(const std::string &name, const std::string &help_str) :
- MetricCounter(), m_name(name), m_help_str(help_str),
- m_counter(0.0)
- {
- }
-
- virtual void increment(double number)
- {
- MutexAutoLock lock(m_mutex);
- m_counter += number;
- }
- virtual double get() const
- {
- MutexAutoLock lock(m_mutex);
- return m_counter;
- }
-
-private:
- std::string m_name;
- std::string m_help_str;
-
- mutable std::mutex m_mutex;
- double m_counter;
-};
-
class MetricGauge
{
public:
@@ -81,47 +50,6 @@ public:
typedef std::shared_ptr<MetricGauge> MetricGaugePtr;
-class SimpleMetricGauge : public MetricGauge
-{
-public:
- SimpleMetricGauge() = delete;
-
- SimpleMetricGauge(const std::string &name, const std::string &help_str) :
- MetricGauge(), m_name(name), m_help_str(help_str), m_gauge(0.0)
- {
- }
-
- virtual ~SimpleMetricGauge() {}
-
- virtual void increment(double number)
- {
- MutexAutoLock lock(m_mutex);
- m_gauge += number;
- }
- virtual void decrement(double number)
- {
- MutexAutoLock lock(m_mutex);
- m_gauge -= number;
- }
- virtual void set(double number)
- {
- MutexAutoLock lock(m_mutex);
- m_gauge = number;
- }
- virtual double get() const
- {
- MutexAutoLock lock(m_mutex);
- return m_gauge;
- }
-
-private:
- std::string m_name;
- std::string m_help_str;
-
- mutable std::mutex m_mutex;
- double m_gauge;
-};
-
class MetricsBackend
{
public:
@@ -129,10 +57,14 @@ public:
virtual ~MetricsBackend() {}
+ typedef std::initializer_list<std::pair<const std::string, std::string>> Labels;
+
virtual MetricCounterPtr addCounter(
- const std::string &name, const std::string &help_str);
+ const std::string &name, const std::string &help_str,
+ Labels labels = {});
virtual MetricGaugePtr addGauge(
- const std::string &name, const std::string &help_str);
+ const std::string &name, const std::string &help_str,
+ Labels labels = {});
};
#if USE_PROMETHEUS
diff --git a/src/util/png.cpp b/src/util/png.cpp
index 7ac2e94a1..698cbc9a5 100755
--- a/src/util/png.cpp
+++ b/src/util/png.cpp
@@ -37,11 +37,11 @@ static void writeChunk(std::ostringstream &target, const std::string &chunk_str)
std::string encodePNG(const u8 *data, u32 width, u32 height, s32 compression)
{
- auto file = std::ostringstream(std::ios::binary);
+ std::ostringstream file(std::ios::binary);
file << "\x89PNG\r\n\x1a\n";
{
- auto IHDR = std::ostringstream(std::ios::binary);
+ std::ostringstream IHDR(std::ios::binary);
IHDR << "IHDR";
writeU32(IHDR, width);
writeU32(IHDR, height);
@@ -51,9 +51,9 @@ std::string encodePNG(const u8 *data, u32 width, u32 height, s32 compression)
}
{
- auto IDAT = std::ostringstream(std::ios::binary);
+ std::ostringstream IDAT(std::ios::binary);
IDAT << "IDAT";
- auto scanlines = std::ostringstream(std::ios::binary);
+ std::ostringstream scanlines(std::ios::binary);
for(u32 i = 0; i < height; i++) {
scanlines.write("\x00", 1); // Null predictor
scanlines.write((const char*) data + width * 4 * i, width * 4);
diff --git a/src/util/pointer.h b/src/util/pointer.h
index 7fc5de551..245ac85bf 100644
--- a/src/util/pointer.h
+++ b/src/util/pointer.h
@@ -22,6 +22,21 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes.h"
#include "debug.h" // For assert()
#include <cstring>
+#include <memory> // std::shared_ptr
+
+
+template<typename T> class ConstSharedPtr {
+public:
+ ConstSharedPtr(T *ptr) : ptr(ptr) {}
+ ConstSharedPtr(const std::shared_ptr<T> &ptr) : ptr(ptr) {}
+
+ const T* get() const noexcept { return ptr.get(); }
+ const T& operator*() const noexcept { return *ptr.get(); }
+ const T* operator->() const noexcept { return ptr.get(); }
+
+private:
+ std::shared_ptr<T> ptr;
+};
template <typename T>
class Buffer
@@ -40,17 +55,11 @@ public:
else
data = NULL;
}
- Buffer(const Buffer &buffer)
- {
- m_size = buffer.m_size;
- if(m_size != 0)
- {
- data = new T[buffer.m_size];
- memcpy(data, buffer.data, buffer.m_size);
- }
- else
- data = NULL;
- }
+
+ // Disable class copy
+ Buffer(const Buffer &) = delete;
+ Buffer &operator=(const Buffer &) = delete;
+
Buffer(Buffer &&buffer)
{
m_size = buffer.m_size;
@@ -81,21 +90,6 @@ public:
drop();
}
- Buffer& operator=(const Buffer &buffer)
- {
- if(this == &buffer)
- return *this;
- drop();
- m_size = buffer.m_size;
- if(m_size != 0)
- {
- data = new T[buffer.m_size];
- memcpy(data, buffer.data, buffer.m_size);
- }
- else
- data = NULL;
- return *this;
- }
Buffer& operator=(Buffer &&buffer)
{
if(this == &buffer)
@@ -113,6 +107,18 @@ public:
return *this;
}
+ void copyTo(Buffer &buffer) const
+ {
+ buffer.drop();
+ buffer.m_size = m_size;
+ if (m_size != 0) {
+ buffer.data = new T[m_size];
+ memcpy(buffer.data, data, m_size);
+ } else {
+ buffer.data = nullptr;
+ }
+ }
+
T & operator[](unsigned int i) const
{
return data[i];
diff --git a/src/util/srp.cpp b/src/util/srp.cpp
index ceb2fef9e..daa7f332b 100644
--- a/src/util/srp.cpp
+++ b/src/util/srp.cpp
@@ -354,7 +354,7 @@ static size_t hash_length(SRP_HashAlgorithm alg)
case SRP_SHA384: return SHA384_DIGEST_LENGTH;
case SRP_SHA512: return SHA512_DIGEST_LENGTH;
*/
- default: return -1;
+ default: return 0;
};
}
// clang-format on
@@ -422,7 +422,7 @@ static SRP_Result H_nn(
}
static SRP_Result H_ns(mpz_t result, SRP_HashAlgorithm alg, const unsigned char *n,
- size_t len_n, const unsigned char *bytes, uint32_t len_bytes)
+ size_t len_n, const unsigned char *bytes, size_t len_bytes)
{
unsigned char buff[SHA512_DIGEST_LENGTH];
size_t nbytes = len_n + len_bytes;
diff --git a/src/util/stream.h b/src/util/stream.h
new file mode 100644
index 000000000..2e61b46d2
--- /dev/null
+++ b/src/util/stream.h
@@ -0,0 +1,70 @@
+/*
+Minetest
+Copyright (C) 2022 Minetest Authors
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#pragma once
+
+#include <iostream>
+#include <string>
+#include <functional>
+
+template<int BufferLength, typename Emitter = std::function<void(const std::string &)> >
+class StringStreamBuffer : public std::streambuf {
+public:
+ StringStreamBuffer(Emitter emitter) : m_emitter(emitter) {
+ buffer_index = 0;
+ }
+
+ int overflow(int c) {
+ push_back(c);
+ return c;
+ }
+
+ void push_back(char c) {
+ if (c == '\n' || c == '\r') {
+ if (buffer_index)
+ m_emitter(std::string(buffer, buffer_index));
+ buffer_index = 0;
+ } else {
+ buffer[buffer_index++] = c;
+ if (buffer_index >= BufferLength) {
+ m_emitter(std::string(buffer, buffer_index));
+ buffer_index = 0;
+ }
+ }
+ }
+
+ std::streamsize xsputn(const char *s, std::streamsize n) {
+ for (int i = 0; i < n; ++i)
+ push_back(s[i]);
+ return n;
+ }
+private:
+ Emitter m_emitter;
+ char buffer[BufferLength];
+ int buffer_index;
+};
+
+class DummyStreamBuffer : public std::streambuf {
+ int overflow(int c) {
+ return c;
+ }
+ std::streamsize xsputn(const char *s, std::streamsize n) {
+ return n;
+ }
+};
diff --git a/src/util/string.cpp b/src/util/string.cpp
index eec5ab4cd..b805b2f78 100644
--- a/src/util/string.cpp
+++ b/src/util/string.cpp
@@ -39,8 +39,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <windows.h>
#endif
-#if defined(_ICONV_H_) && (defined(__FreeBSD__) || defined(__NetBSD__) || \
- defined(__OpenBSD__) || defined(__DragonFly__))
+#ifdef __NetBSD__
+ #include <sys/param.h>
+ #if __NetBSD_Version__ <= 999001500
+ #define BSD_ICONV_USED
+ #endif
+#elif defined(_ICONV_H_) && (defined(__FreeBSD__) || defined(__OpenBSD__) || \
+ defined(__DragonFly__))
#define BSD_ICONV_USED
#endif
@@ -79,6 +84,14 @@ static bool convert(const char *to, const char *from, char *outbuf,
#ifdef __ANDROID__
// On Android iconv disagrees how big a wchar_t is for whatever reason
const char *DEFAULT_ENCODING = "UTF-32LE";
+#elif defined(__NetBSD__)
+ // NetBSD does not allow "WCHAR_T" as a charset input to iconv.
+ #include <sys/endian.h>
+ #if BYTE_ORDER == BIG_ENDIAN
+ const char *DEFAULT_ENCODING = "UTF-32BE";
+ #else
+ const char *DEFAULT_ENCODING = "UTF-32LE";
+ #endif
#else
const char *DEFAULT_ENCODING = "WCHAR_T";
#endif
@@ -94,7 +107,7 @@ std::wstring utf8_to_wide(const std::string &input)
std::wstring out;
out.resize(outbuf_size / sizeof(wchar_t));
-#ifdef __ANDROID__
+#if defined(__ANDROID__) || defined(__NetBSD__)
SANITY_CHECK(sizeof(wchar_t) == 4);
#endif
@@ -481,6 +494,7 @@ const static std::unordered_map<std::string, u32> s_named_colors = {
{"plum", 0xdda0dd},
{"powderblue", 0xb0e0e6},
{"purple", 0x800080},
+ {"rebeccapurple", 0x663399},
{"red", 0xff0000},
{"rosybrown", 0xbc8f8f},
{"royalblue", 0x4169e1},
@@ -808,9 +822,11 @@ std::wstring translate_string(const std::wstring &s)
#endif
}
-static const std::array<std::wstring, 22> disallowed_dir_names = {
+static const std::array<std::wstring, 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:
+ // https://googleprojectzero.blogspot.com/2016/02/the-definitive-guide-on-win32-to-nt.html
L"CON",
L"PRN",
L"AUX",
@@ -824,6 +840,9 @@ static const std::array<std::wstring, 22> disallowed_dir_names = {
L"COM7",
L"COM8",
L"COM9",
+ L"COM\u00B2",
+ L"COM\u00B3",
+ L"COM\u00B9",
L"LPT1",
L"LPT2",
L"LPT3",
@@ -833,6 +852,11 @@ static const std::array<std::wstring, 22> disallowed_dir_names = {
L"LPT7",
L"LPT8",
L"LPT9",
+ L"LPT\u00B2",
+ L"LPT\u00B3",
+ L"LPT\u00B9",
+ L"CONIN$",
+ L"CONOUT$",
};
/**
@@ -840,12 +864,7 @@ static const std::array<std::wstring, 22> disallowed_dir_names = {
*/
static const std::wstring disallowed_path_chars = L"<>:\"/\\|?*.";
-/**
- * Sanitize the name of a new directory. This consists of two stages:
- * 1. Check for 'reserved filenames' that can't be used on some filesystems
- * 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::wstring safe_name = utf8_to_wide(str);
@@ -857,7 +876,18 @@ std::string sanitizeDirName(const std::string &str, const std::string &optional_
}
}
- for (unsigned long i = 0; i < safe_name.length(); i++) {
+ // Replace leading and trailing spaces with underscores.
+ size_t start = safe_name.find_first_not_of(L' ');
+ size_t end = safe_name.find_last_not_of(L' ');
+ if (start == std::wstring::npos || end == std::wstring::npos)
+ start = end = safe_name.size();
+ for (size_t i = 0; i < start; i++)
+ safe_name[i] = L'_';
+ for (size_t i = end + 1; i < safe_name.size(); i++)
+ safe_name[i] = L'_';
+
+ // Replace other disallowed characters with underscores
+ for (size_t i = 0; i < safe_name.length(); i++) {
bool is_valid = true;
// Unlikely, but control characters should always be blacklisted
@@ -869,8 +899,24 @@ std::string sanitizeDirName(const std::string &str, const std::string &optional_
}
if (!is_valid)
- safe_name[i] = '_';
+ safe_name[i] = L'_';
}
return wide_to_utf8(safe_name);
}
+
+
+void safe_print_string(std::ostream &os, const std::string &str)
+{
+ std::ostream::fmtflags flags = os.flags();
+ os << std::hex;
+ for (const char c : str) {
+ if (IS_ASCII_PRINTABLE_CHAR(c) || IS_UTF8_MULTB_START(c) ||
+ IS_UTF8_MULTB_INNER(c) || c == '\n' || c == '\t') {
+ os << c;
+ } else {
+ os << '<' << std::setw(2) << (int)c << '>';
+ }
+ }
+ os.setf(flags);
+}
diff --git a/src/util/string.h b/src/util/string.h
index 21f1d6877..aa4329f2f 100644
--- a/src/util/string.h
+++ b/src/util/string.h
@@ -295,11 +295,11 @@ inline std::string lowercase(const std::string &str)
inline std::string trim(const std::string &str)
{
size_t front = 0;
+ size_t back = str.size();
- while (std::isspace(str[front]))
+ while (front < back && std::isspace(str[front]))
++front;
- size_t back = str.size();
while (back > front && std::isspace(str[back - 1]))
--back;
@@ -410,7 +410,7 @@ DEFINE_STD_TOSTRING_FLOATINGPOINT(long double)
template <typename T>
inline wstring to_wstring(T val)
{
- return utf8_to_wide(to_string(val));
+ return utf8_to_wide(to_string(val));
}
}
#endif
@@ -661,28 +661,49 @@ inline const char *bool_to_cstr(bool val)
return val ? "true" : "false";
}
+/**
+ * Converts a duration in seconds to a pretty-printed duration in
+ * days, hours, minutes and seconds.
+ *
+ * @param sec duration in seconds
+ * @return pretty-printed duration
+ */
inline const std::string duration_to_string(int sec)
{
+ std::ostringstream ss;
+ const char *neg = "";
+ if (sec < 0) {
+ sec = -sec;
+ neg = "-";
+ }
+ int total_sec = sec;
int min = sec / 60;
sec %= 60;
int hour = min / 60;
min %= 60;
+ int day = hour / 24;
+ hour %= 24;
+
+ if (day > 0) {
+ ss << neg << day << "d";
+ if (hour > 0 || min > 0 || sec > 0)
+ ss << " ";
+ }
- std::stringstream ss;
if (hour > 0) {
- ss << hour << "h";
+ ss << neg << hour << "h";
if (min > 0 || sec > 0)
ss << " ";
}
if (min > 0) {
- ss << min << "min";
+ ss << neg << min << "min";
if (sec > 0)
ss << " ";
}
- if (sec > 0) {
- ss << sec << "s";
+ if (sec > 0 || total_sec == 0) {
+ ss << neg << sec << "s";
}
return ss.str();
@@ -728,7 +749,15 @@ inline irr::core::stringw utf8_to_stringw(const std::string &input)
/**
* Sanitize the name of a new directory. This consists of two stages:
* 1. Check for 'reserved filenames' that can't be used on some filesystems
- * and prefix them
+ * 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);
+
+/**
+ * Prints a sanitized version of a string without control characters.
+ * '\t' and '\n' are allowed, as are UTF-8 control characters (e.g. RTL).
+ * 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);