format: reformat project

Signed-off-by: Vyacheslav Ivanov <islavaivanov76@gmail.com>
This commit is contained in:
Vyacheslav Ivanov
2024-08-03 19:53:48 +03:00
committed by Pugemon
parent 736cd175d5
commit bbf33e8e4d
202 changed files with 7389 additions and 5609 deletions
+8 -8
View File
@@ -1,17 +1,17 @@
#ifndef UTIL_BUFFER_POOL_HPP_
#define UTIL_BUFFER_POOL_HPP_
#include "../typedefs.hpp"
#include <queue>
#include <mutex>
#include <vector>
#include <memory>
#include <mutex>
#include <queue>
#include <vector>
#include "../typedefs.hpp"
namespace util {
/// @brief Thread-safe pool of same-sized buffers
/// @tparam T array type
template<class T>
template <class T>
class BufferPool {
std::vector<std::unique_ptr<T[]>> buffers;
std::queue<T*> freeBuffers;
@@ -27,7 +27,7 @@ namespace util {
std::lock_guard lock(mutex);
if (freeBuffers.empty()) {
buffers.emplace_back(std::make_unique<T[]>(bufferSize));
freeBuffers.push(buffers[buffers.size()-1].get());
freeBuffers.push(buffers[buffers.size() - 1].get());
}
auto* buffer = freeBuffers.front();
freeBuffers.pop();
@@ -39,4 +39,4 @@ namespace util {
};
}
#endif // UTIL_BUFFER_POOL_HPP_
#endif // UTIL_BUFFER_POOL_HPP_
+4 -5
View File
@@ -5,19 +5,18 @@
using namespace util;
Clock::Clock(int tickRate, int tickParts)
: tickRate(tickRate),
tickParts(tickParts) {
: tickRate(tickRate), tickParts(tickParts) {
}
bool Clock::update(float delta) {
tickTimer += delta;
float delay = 1.0f / float(tickRate);
float delay = 1.0f / float(tickRate);
if (tickTimer > delay || tickPartsUndone) {
if (tickPartsUndone) {
tickPartsUndone--;
} else {
tickTimer = std::fmod(tickTimer, delay);
tickPartsUndone = tickParts-1;
tickPartsUndone = tickParts - 1;
}
return true;
}
@@ -29,7 +28,7 @@ int Clock::getParts() const {
}
int Clock::getPart() const {
return tickParts-tickPartsUndone-1;
return tickParts - tickPartsUndone - 1;
}
int Clock::getTickRate() const {
+1 -1
View File
@@ -21,4 +21,4 @@ namespace util {
};
}
#endif // UTIL_CLOCK_HPP_
#endif // UTIL_CLOCK_HPP_
+4 -3
View File
@@ -1,15 +1,16 @@
#ifndef UTIL_OBJECTS_KEEPER_HPP_
#define UTIL_OBJECTS_KEEPER_HPP_
#include <vector>
#include <memory>
#include <vector>
namespace util {
/// @brief Keeps shared pointers alive until destruction
class ObjectsKeeper {
std::vector<std::shared_ptr<void>> ptrs;
public:
virtual ~ObjectsKeeper() {}
virtual ~ObjectsKeeper() {
}
virtual void keepAlive(std::shared_ptr<void> ptr) {
ptrs.push_back(ptr);
@@ -17,4 +18,4 @@ namespace util {
};
}
#endif // UTIL_OBJECTS_KEEPER_HPP_
#endif // UTIL_OBJECTS_KEEPER_HPP_
+4 -4
View File
@@ -1,13 +1,13 @@
#ifndef UTIL_RUNNABLES_LIST_HPP_
#define UTIL_RUNNABLES_LIST_HPP_
#include "../typedefs.hpp"
#include "../delegates.hpp"
#include <memory>
#include <unordered_map>
#include <utility>
#include "../delegates.hpp"
#include "../typedefs.hpp"
namespace util {
class RunnablesList {
int nextid = 1;
@@ -30,4 +30,4 @@ namespace util {
};
}
#endif // UTIL_RUNNABLES_LIST_HPP_
#endif // UTIL_RUNNABLES_LIST_HPP_
+222 -218
View File
@@ -1,255 +1,259 @@
#ifndef UTIL_THREAD_POOL_HPP_
#define UTIL_THREAD_POOL_HPP_
#include "../delegates.hpp"
#include "../debug/Logger.hpp"
#include "../interfaces/Task.hpp"
#include <queue>
#include <atomic>
#include <thread>
#include <chrono>
#include <iostream>
#include <functional>
#include <condition_variable>
#include <functional>
#include <iostream>
#include <queue>
#include <thread>
#include <utility>
#include "../debug/Logger.hpp"
#include "../delegates.hpp"
#include "../interfaces/Task.hpp"
namespace util {
template<class J, class T>
struct ThreadPoolResult {
std::shared_ptr<J> job;
std::condition_variable& variable;
int workerIndex;
bool& locked;
T entry;
};
template<class T, class R>
class Worker {
public:
Worker() = default;
virtual ~Worker() = default;
virtual R operator()(const std::shared_ptr<T>&) = 0;
};
template <class J, class T>
struct ThreadPoolResult {
std::shared_ptr<J> job;
std::condition_variable& variable;
int workerIndex;
bool& locked;
T entry;
};
template<class T, class R>
class ThreadPool : public Task {
debug::Logger logger;
std::queue<std::shared_ptr<T>> jobs;
std::queue<ThreadPoolResult<T, R>> results;
std::mutex resultsMutex;
std::vector<std::thread> threads;
std::condition_variable jobsMutexCondition;
std::mutex jobsMutex;
std::vector<std::unique_lock<std::mutex>> workersBlocked;
consumer<R&> resultConsumer;
consumer<std::shared_ptr<T>&> onJobFailed = nullptr;
runnable onComplete = nullptr;
std::atomic<int> busyWorkers = 0;
std::atomic<uint> jobsDone = 0;
std::atomic<bool> working = true;
bool failed = false;
bool standaloneResults = true;
bool stopOnFail = true;
template <class T, class R>
class Worker {
public:
Worker() = default;
virtual ~Worker() = default;
virtual R operator()(const std::shared_ptr<T>&) = 0;
};
void threadLoop(int index, std::shared_ptr<Worker<T, R>> worker) {
std::condition_variable variable;
std::mutex mutex;
bool locked = false;
while (working) {
std::shared_ptr<T> job;
{
std::unique_lock<std::mutex> lock(jobsMutex);
jobsMutexCondition.wait(lock, [this] {
return !jobs.empty() || !working;
});
if (!working || failed) {
break;
}
job = jobs.front();
jobs.pop();
template <class T, class R>
class ThreadPool : public Task {
debug::Logger logger;
std::queue<std::shared_ptr<T>> jobs;
std::queue<ThreadPoolResult<T, R>> results;
std::mutex resultsMutex;
std::vector<std::thread> threads;
std::condition_variable jobsMutexCondition;
std::mutex jobsMutex;
std::vector<std::unique_lock<std::mutex>> workersBlocked;
consumer<R&> resultConsumer;
consumer<std::shared_ptr<T>&> onJobFailed = nullptr;
runnable onComplete = nullptr;
std::atomic<int> busyWorkers = 0;
std::atomic<uint> jobsDone = 0;
std::atomic<bool> working = true;
bool failed = false;
bool standaloneResults = true;
bool stopOnFail = true;
busyWorkers++;
}
try {
R result = (*worker)(job);
void threadLoop(int index, std::shared_ptr<Worker<T, R>> worker) {
std::condition_variable variable;
std::mutex mutex;
bool locked = false;
while (working) {
std::shared_ptr<T> job;
{
std::lock_guard<std::mutex> lock(resultsMutex);
results.push(ThreadPoolResult<T, R> {job, variable, index, locked, result});
if (!standaloneResults) {
locked = true;
}
busyWorkers--;
}
if (!standaloneResults){
std::unique_lock<std::mutex> lock(mutex);
variable.wait(lock, [&] {
return !working || !locked;
std::unique_lock<std::mutex> lock(jobsMutex);
jobsMutexCondition.wait(lock, [this] {
return !jobs.empty() || !working;
});
if (!working || failed) {
break;
}
job = jobs.front();
jobs.pop();
busyWorkers++;
}
} catch (std::exception& err) {
busyWorkers--;
if (onJobFailed) {
onJobFailed(job);
}
if (stopOnFail) {
std::lock_guard<std::mutex> lock(jobsMutex);
failed = true;
}
logger.error() << "uncaught exception: " << err.what();
}
jobsDone++;
}
}
public:
ThreadPool(
std::string name,
supplier<std::shared_ptr<Worker<T, R>>> workersSupplier,
consumer<R&> resultConsumer
) : logger(std::move(name)), resultConsumer(resultConsumer) {
const uint num_threads = std::thread::hardware_concurrency();
for (uint i = 0; i < num_threads; i++) {
threads.emplace_back(&ThreadPool<T,R>::threadLoop, this, i, workersSupplier());
workersBlocked.emplace_back();
}
}
~ThreadPool(){
terminate();
}
bool isActive() const override {
return working;
}
void terminate() override {
if (!working) {
return;
}
{
std::lock_guard<std::mutex> lock(jobsMutex);
working = false;
}
{
std::lock_guard<std::mutex> lock(resultsMutex);
while (!results.empty()) {
ThreadPoolResult<T,R> entry = results.front();
results.pop();
if (!standaloneResults) {
entry.locked = false;
entry.variable.notify_all();
}
}
}
jobsMutexCondition.notify_all();
for (auto& thread : threads) {
thread.join();
}
}
void update() override {
if (!working) {
return;
}
if (failed) {
throw std::runtime_error("some job failed");
}
bool complete = false;
{
std::lock_guard<std::mutex> lock(resultsMutex);
while (!results.empty()) {
ThreadPoolResult<T,R> entry = results.front();
results.pop();
try {
resultConsumer(entry.entry);
R result = (*worker)(job);
{
std::lock_guard<std::mutex> lock(resultsMutex);
results.push(ThreadPoolResult<T, R> {
job, variable, index, locked, result});
if (!standaloneResults) {
locked = true;
}
busyWorkers--;
}
if (!standaloneResults) {
std::unique_lock<std::mutex> lock(mutex);
variable.wait(lock, [&] {
return !working || !locked;
});
}
} catch (std::exception& err) {
logger.error() << err.what();
busyWorkers--;
if (onJobFailed) {
onJobFailed(entry.job);
onJobFailed(job);
}
if (stopOnFail) {
std::lock_guard<std::mutex> jobsLock(jobsMutex);
std::lock_guard<std::mutex> lock(jobsMutex);
failed = true;
complete = false;
}
break;
}
if (!standaloneResults) {
entry.locked = false;
entry.variable.notify_all();
}
}
if (onComplete && busyWorkers == 0) {
std::lock_guard<std::mutex> jobsLock(jobsMutex);
if (jobs.empty()) {
onComplete();
complete = true;
logger.error() << "uncaught exception: " << err.what();
}
jobsDone++;
}
}
if (failed) {
throw std::runtime_error("some job failed");
public:
ThreadPool(
std::string name,
supplier<std::shared_ptr<Worker<T, R>>> workersSupplier,
consumer<R&> resultConsumer
)
: logger(std::move(name)), resultConsumer(resultConsumer) {
const uint num_threads = std::thread::hardware_concurrency();
for (uint i = 0; i < num_threads; i++) {
threads.emplace_back(
&ThreadPool<T, R>::threadLoop, this, i, workersSupplier()
);
workersBlocked.emplace_back();
}
}
if (complete) {
~ThreadPool() {
terminate();
}
}
void enqueueJob(const std::shared_ptr<T>& job) {
{
std::lock_guard<std::mutex> lock(jobsMutex);
jobs.push(job);
bool isActive() const override {
return working;
}
jobsMutexCondition.notify_one();
}
/// @brief If false: worker will be blocked until it's result performed
void setStandaloneResults(bool flag) {
standaloneResults = flag;
}
void terminate() override {
if (!working) {
return;
}
{
std::lock_guard<std::mutex> lock(jobsMutex);
working = false;
}
{
std::lock_guard<std::mutex> lock(resultsMutex);
while (!results.empty()) {
ThreadPoolResult<T, R> entry = results.front();
results.pop();
if (!standaloneResults) {
entry.locked = false;
entry.variable.notify_all();
}
}
}
void setStopOnFail(bool flag) {
stopOnFail = flag;
}
/// @brief onJobFailed called on exception thrown in worker thread.
/// Use engine.postRunnable when calling terminate()
void setOnJobFailed(consumer<T&> callback) {
this->onJobFailed = callback;
}
/// @brief onComplete called in ThreadPool.update() when all jobs done
/// if ThreadPool was not terminated
void setOnComplete(runnable callback) {
this->onComplete = callback;
}
uint getWorkTotal() const override {
return jobs.size()+jobsDone+busyWorkers;
}
uint getWorkDone() const override {
return jobsDone;
}
virtual void waitForEnd() override {
using namespace std::chrono_literals;
while (working) {
std::this_thread::sleep_for(2ms);
update();
jobsMutexCondition.notify_all();
for (auto& thread : threads) {
thread.join();
}
}
}
uint getWorkersCount() const {
return threads.size();
}
};
void update() override {
if (!working) {
return;
}
if (failed) {
throw std::runtime_error("some job failed");
}
} // namespace util
bool complete = false;
{
std::lock_guard<std::mutex> lock(resultsMutex);
while (!results.empty()) {
ThreadPoolResult<T, R> entry = results.front();
results.pop();
#endif // UTIL_THREAD_POOL_HPP_
try {
resultConsumer(entry.entry);
} catch (std::exception& err) {
logger.error() << err.what();
if (onJobFailed) {
onJobFailed(entry.job);
}
if (stopOnFail) {
std::lock_guard<std::mutex> jobsLock(jobsMutex);
failed = true;
complete = false;
}
break;
}
if (!standaloneResults) {
entry.locked = false;
entry.variable.notify_all();
}
}
if (onComplete && busyWorkers == 0) {
std::lock_guard<std::mutex> jobsLock(jobsMutex);
if (jobs.empty()) {
onComplete();
complete = true;
}
}
}
if (failed) {
throw std::runtime_error("some job failed");
}
if (complete) {
terminate();
}
}
void enqueueJob(const std::shared_ptr<T>& job) {
{
std::lock_guard<std::mutex> lock(jobsMutex);
jobs.push(job);
}
jobsMutexCondition.notify_one();
}
/// @brief If false: worker will be blocked until it's result performed
void setStandaloneResults(bool flag) {
standaloneResults = flag;
}
void setStopOnFail(bool flag) {
stopOnFail = flag;
}
/// @brief onJobFailed called on exception thrown in worker thread.
/// Use engine.postRunnable when calling terminate()
void setOnJobFailed(consumer<T&> callback) {
this->onJobFailed = callback;
}
/// @brief onComplete called in ThreadPool.update() when all jobs done
/// if ThreadPool was not terminated
void setOnComplete(runnable callback) {
this->onComplete = callback;
}
uint getWorkTotal() const override {
return jobs.size() + jobsDone + busyWorkers;
}
uint getWorkDone() const override {
return jobsDone;
}
virtual void waitForEnd() override {
using namespace std::chrono_literals;
while (working) {
std::this_thread::sleep_for(2ms);
update();
}
}
uint getWorkersCount() const {
return threads.size();
}
};
} // namespace util
#endif // UTIL_THREAD_POOL_HPP_
+11 -8
View File
@@ -1,12 +1,12 @@
#include "command_line.hpp"
#include "../files/engine_paths.hpp"
#include <iostream>
#include <filesystem>
#include <string>
#include <cstring>
#include <filesystem>
#include <iostream>
#include <stdexcept>
#include <string>
#include "../files/engine_paths.hpp"
namespace fs = std::filesystem;
@@ -16,7 +16,8 @@ class ArgsReader {
int argc;
int pos = 0;
public:
ArgsReader(int argc, char** argv) : argv(argv), argc(argc) {}
ArgsReader(int argc, char** argv) : argv(argv), argc(argc) {
}
void skip() {
pos++;
@@ -39,11 +40,13 @@ public:
}
};
bool perform_keyword(ArgsReader& reader, const std::string& keyword, EnginePaths& paths) {
bool perform_keyword(
ArgsReader& reader, const std::string& keyword, EnginePaths& paths
) {
if (keyword == "--res") {
auto token = reader.next();
if (!fs::is_directory(fs::path(token))) {
throw std::runtime_error(token+" is not a directory");
throw std::runtime_error(token + " is not a directory");
}
paths.setResources(fs::path(token));
std::cout << "resources folder: " << token << std::endl;
+1 -1
View File
@@ -6,4 +6,4 @@ class EnginePaths;
/// @return false if engine start can
bool parse_cmdline(int argc, char** argv, EnginePaths& paths);
#endif // UTIL_COMMAND_LINE_HPP_
#endif // UTIL_COMMAND_LINE_HPP_
+24 -29
View File
@@ -6,51 +6,46 @@
namespace dataio {
/* Read big-endian 16 bit signed integer from bytes */
inline int16_t read_int16_big(const ubyte* src, size_t offset) {
return (src[offset] << 8) |
(src[offset+1]);
return (src[offset] << 8) | (src[offset + 1]);
}
/* Read big-endian 32 bit signed integer from bytes */
inline int32_t read_int32_big(const ubyte* src, size_t offset) {
return (src[offset] << 24) |
(src[offset+1] << 16) |
(src[offset+2] << 8) |
(src[offset+3]);
return (src[offset] << 24) | (src[offset + 1] << 16) |
(src[offset + 2] << 8) | (src[offset + 3]);
}
/* Read big-endian 64 bit signed integer from bytes */
inline int64_t read_int64_big(const ubyte* src, size_t offset) {
return (int64_t(src[offset]) << 56) |
(int64_t(src[offset+1]) << 48) |
(int64_t(src[offset+2]) << 40) |
(int64_t(src[offset+3]) << 32) |
(int64_t(src[offset+4]) << 24) |
(int64_t(src[offset+5]) << 16) |
(int64_t(src[offset+6]) << 8) |
(int64_t(src[offset+7]));
return (int64_t(src[offset]) << 56) | (int64_t(src[offset + 1]) << 48) |
(int64_t(src[offset + 2]) << 40) |
(int64_t(src[offset + 3]) << 32) |
(int64_t(src[offset + 4]) << 24) |
(int64_t(src[offset + 5]) << 16) |
(int64_t(src[offset + 6]) << 8) | (int64_t(src[offset + 7]));
}
/* Write big-endian 16 bit signed integer to bytes */
inline void write_int16_big(int16_t value, ubyte* dest, size_t offset) {
dest[offset] = (char) (value >> 8 & 255);
dest[offset+1] = (char) (value >> 0 & 255);
dest[offset] = (char)(value >> 8 & 255);
dest[offset + 1] = (char)(value >> 0 & 255);
}
/* Write big-endian 32 bit signed integer to bytes */
inline void write_int32_big(int32_t value, ubyte* dest, size_t offset) {
dest[offset] = (char) (value >> 24 & 255);
dest[offset+1] = (char) (value >> 16 & 255);
dest[offset+2] = (char) (value >> 8 & 255);
dest[offset+3] = (char) (value >> 0 & 255);
dest[offset] = (char)(value >> 24 & 255);
dest[offset + 1] = (char)(value >> 16 & 255);
dest[offset + 2] = (char)(value >> 8 & 255);
dest[offset + 3] = (char)(value >> 0 & 255);
}
/* Write big-endian 64 bit signed integer to bytes */
inline void write_int64_big(int64_t value, ubyte* dest, size_t offset) {
dest[offset] = (char) (value >> 56 & 255);
dest[offset+1] = (char) (value >> 48 & 255);
dest[offset+2] = (char) (value >> 40 & 255);
dest[offset+3] = (char) (value >> 32 & 255);
dest[offset] = (char)(value >> 56 & 255);
dest[offset + 1] = (char)(value >> 48 & 255);
dest[offset + 2] = (char)(value >> 40 & 255);
dest[offset + 3] = (char)(value >> 32 & 255);
dest[offset+4] = (char) (value >> 24 & 255);
dest[offset+5] = (char) (value >> 16 & 255);
dest[offset+6] = (char) (value >> 8 & 255);
dest[offset+7] = (char) (value >> 0 & 255);
dest[offset + 4] = (char)(value >> 24 & 255);
dest[offset + 5] = (char)(value >> 16 & 255);
dest[offset + 6] = (char)(value >> 8 & 255);
dest[offset + 7] = (char)(value >> 0 & 255);
}
}
#endif // UTIL_DATA_IO_HPP_
#endif // UTIL_DATA_IO_HPP_
+3 -2
View File
@@ -1,14 +1,15 @@
#include "listutil.hpp"
#include "../util/stringutil.hpp"
#include <sstream>
#include "../util/stringutil.hpp"
std::string util::to_string(const std::vector<std::string>& vec) {
std::stringstream ss;
ss << "[";
for (size_t i = 0; i < vec.size(); i++) {
ss << util::quote(vec[1]);
if (i < vec.size()-1) {
if (i < vec.size() - 1) {
ss << ", ";
}
}
+4 -4
View File
@@ -2,12 +2,12 @@
#define UTIL_LISTUTIL_HPP_
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <string>
#include <vector>
namespace util {
template<class T>
template <class T>
bool contains(const std::vector<T>& vec, const T& value) {
return std::find(vec.begin(), vec.end(), value) != vec.end();
}
@@ -15,4 +15,4 @@ namespace util {
std::string to_string(const std::vector<std::string>& vec);
}
#endif // UTIL_LISTUTIL_HPP_
#endif // UTIL_LISTUTIL_HPP_
+20 -11
View File
@@ -1,11 +1,12 @@
#include "platform.hpp"
#include "../typedefs.hpp"
#include <sstream>
#include <iomanip>
#include <time.h>
#include <iomanip>
#include <iostream>
#include <sstream>
#include "../typedefs.hpp"
#ifdef _WIN32
#include <Windows.h>
@@ -20,22 +21,30 @@ void platform::configure_encoding() {
std::string platform::detect_locale() {
LCID lcid = GetThreadLocale();
wchar_t preferredLocaleName[LOCALE_NAME_MAX_LENGTH];//locale name format: ll-CC
if (LCIDToLocaleName(lcid, preferredLocaleName, LOCALE_NAME_MAX_LENGTH, 0) == 0) {
std::cerr << "error in platform::detect_locale! LCIDToLocaleName failed." << std::endl;
wchar_t preferredLocaleName[LOCALE_NAME_MAX_LENGTH]; // locale name format:
// ll-CC
if (LCIDToLocaleName(
lcid, preferredLocaleName, LOCALE_NAME_MAX_LENGTH, 0
) == 0) {
std::cerr
<< "error in platform::detect_locale! LCIDToLocaleName failed."
<< std::endl;
}
//ll_CC format
return util::wstr2str_utf8(preferredLocaleName).replace(2, 1, "_").substr(0, 5);
// ll_CC format
return util::wstr2str_utf8(preferredLocaleName)
.replace(2, 1, "_")
.substr(0, 5);
}
#else
void platform::configure_encoding(){
void platform::configure_encoding() {
}
std::string platform::detect_locale() {
std::string programLocaleName = setlocale(LC_ALL, nullptr);
std::string preferredLocaleName = setlocale(LC_ALL, ""); //locale name format: ll_CC.encoding
std::string preferredLocaleName =
setlocale(LC_ALL, ""); // locale name format: ll_CC.encoding
setlocale(LC_ALL, programLocaleName.c_str());
return preferredLocaleName.substr(0, 5);
+1 -1
View File
@@ -9,4 +9,4 @@ namespace platform {
std::string detect_locale();
}
#endif // UTIL_PLATFORM_HPP_
#endif // UTIL_PLATFORM_HPP_
+100 -86
View File
@@ -1,25 +1,39 @@
#include "stringutil.hpp"
#include <algorithm>
#include <cmath>
#include <locale>
#include <iomanip>
#include <locale>
#include <sstream>
#include <stdexcept>
#include <algorithm>
// TODO: finish
// TODO: finish
std::string util::escape(const std::string& s) {
std::stringstream ss;
ss << '"';
for (char c : s) {
switch (c) {
case '\n': ss << "\\n"; break;
case '\r': ss << "\\r"; break;
case '\t': ss << "\\t"; break;
case '\f': ss << "\\f"; break;
case '\b': ss << "\\b"; break;
case '"': ss << "\\\""; break;
case '\\': ss << "\\\\"; break;
case '\n':
ss << "\\n";
break;
case '\r':
ss << "\\r";
break;
case '\t':
ss << "\\t";
break;
case '\f':
ss << "\\f";
break;
case '\b':
ss << "\\b";
break;
case '"':
ss << "\\\"";
break;
case '\\':
ss << "\\\\";
break;
default:
if (c < ' ') {
ss << "\\" << std::oct << uint(ubyte(c));
@@ -42,7 +56,7 @@ std::wstring util::lfill(std::wstring s, uint length, wchar_t c) {
return s;
}
std::wstringstream ss;
for (uint i = 0; i < length-s.length(); i++) {
for (uint i = 0; i < length - s.length(); i++) {
ss << c;
}
ss << s;
@@ -55,7 +69,7 @@ std::wstring util::rfill(std::wstring s, uint length, wchar_t c) {
}
std::wstringstream ss;
ss << s;
for (uint i = 0; i < length-s.length(); i++) {
for (uint i = 0; i < length - s.length(); i++) {
ss << c;
}
return ss.str();
@@ -93,24 +107,23 @@ struct utf_t {
const utf_t utf[] = {
/* mask lead beg end bits */
{(char)0b00111111, (char)0b10000000, 0, 0, 6},
{(char)0b01111111, (char)0b00000000, 0000, 0177, 7},
{(char)0b00011111, (char)0b11000000, 0200, 03777, 5},
{(char)0b00001111, (char)0b11100000, 04000, 0177777, 4},
{(char)0b00111111, (char)0b10000000, 0, 0, 6},
{(char)0b01111111, (char)0b00000000, 0000, 0177, 7},
{(char)0b00011111, (char)0b11000000, 0200, 03777, 5},
{(char)0b00001111, (char)0b11100000, 04000, 0177777, 4},
{(char)0b00000111, (char)0b11110000, 0200000, 04177777, 3},
{0, 0, 0, 0, 0},
};
inline uint utf8_len(ubyte cp) {
uint len = 0;
for (const utf_t* u = utf; u->mask; ++u) {
if((cp >= u->beg) && (cp <= u->end)) {
if ((cp >= u->beg) && (cp <= u->end)) {
break;
}
++len;
}
if(len > 4) /* Out of bounds */
if (len > 4) /* Out of bounds */
throw std::runtime_error("utf-8 decode error");
return len;
@@ -121,7 +134,7 @@ extern uint32_t util::decode_utf8(uint& size, const char* chr) {
int shift = utf[0].bits_stored * (size - 1);
uint32_t code = (*chr++ & utf[size].mask) << shift;
for(uint i = 1; i < size; ++i, ++chr) {
for (uint i = 1; i < size; ++i, ++chr) {
shift -= utf[0].bits_stored;
code |= ((char)*chr & utf[0].mask) << shift;
}
@@ -153,16 +166,14 @@ std::wstring util::str2wstr_utf8(const std::string& s) {
bool util::is_integer(const std::string& text) {
for (char c : text) {
if (c < '0' || c > '9')
return false;
if (c < '0' || c > '9') return false;
}
return true;
}
bool util::is_integer(const std::wstring& text) {
for (wchar_t c : text) {
if (c < L'0' || c > L'9')
return false;
if (c < L'0' || c > L'9') return false;
}
return true;
}
@@ -170,26 +181,31 @@ bool util::is_integer(const std::wstring& text) {
bool util::is_valid_filename(const std::wstring& name) {
for (wchar_t c : name) {
if (c < 31 || c == '/' || c == '\\' || c == '<' || c == '>' ||
c == ':' || c == '"' || c == '|' || c == '?' || c == '*'){
c == ':' || c == '"' || c == '|' || c == '?' || c == '*') {
return false;
}
}
return true;
}
void util::ltrim(std::string &s) {
void util::ltrim(std::string& s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
return !std::isspace(ch);
}));
}
void util::rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
void util::rtrim(std::string& s) {
s.erase(
std::find_if(
s.rbegin(),
s.rend(),
[](unsigned char ch) { return !std::isspace(ch); }
).base(),
s.end()
);
}
void util::trim(std::string &s) {
void util::trim(std::string& s) {
rtrim(s);
ltrim(s);
}
@@ -198,7 +214,7 @@ std::string util::to_string(double x) {
std::stringstream ss;
ss << std::setprecision(6);
ss << x;
return ss.str();
return ss.str();
}
std::wstring util::to_wstring(double x, int precision) {
@@ -207,59 +223,56 @@ std::wstring util::to_wstring(double x, int precision) {
return ss.str();
}
const char B64ABC[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789"
"+/";
const char B64ABC[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789"
"+/";
inline ubyte base64_decode_char(char c) {
if (c >= 'A' && c <= 'Z')
return c - 'A';
if (c >= 'a' && c <= 'z')
return c - 'a' + 26;
if (c >= '0' && c <= '9')
return c - '0' + 52;
if (c == '+')
return 62;
if (c == '/')
return 63;
if (c >= 'A' && c <= 'Z') return c - 'A';
if (c >= 'a' && c <= 'z') return c - 'a' + 26;
if (c >= '0' && c <= '9') return c - '0' + 52;
if (c == '+') return 62;
if (c == '/') return 63;
return 0;
}
inline void base64_encode_(const ubyte* segment, char* output) {
output[0] = B64ABC[(segment[0] & 0b11111100) >> 2];
output[1] = B64ABC[((segment[0] & 0b11) << 4) | ((segment[1] & 0b11110000) >> 4)];
output[2] = B64ABC[((segment[1] & 0b1111) << 2) | ((segment[2] & 0b11000000) >> 6)];
output[1] =
B64ABC[((segment[0] & 0b11) << 4) | ((segment[1] & 0b11110000) >> 4)];
output[2] =
B64ABC[((segment[1] & 0b1111) << 2) | ((segment[2] & 0b11000000) >> 6)];
output[3] = B64ABC[segment[2] & 0b111111];
}
std::string util::base64_encode(const ubyte* data, size_t size) {
std::stringstream ss;
size_t fullsegments = (size/3)*3;
size_t fullsegments = (size / 3) * 3;
size_t i = 0;
for (; i < fullsegments; i+=3) {
for (; i < fullsegments; i += 3) {
char output[] = "====";
base64_encode_(data+i, output);
base64_encode_(data + i, output);
ss << output;
}
ubyte ending[3] {};
for (; i < size; i++) {
ending[i-fullsegments] = data[i];
ending[i - fullsegments] = data[i];
}
size_t trailing = size-fullsegments;
size_t trailing = size - fullsegments;
{
char output[] = "====";
output[0] = B64ABC[(ending[0] & 0b11111100) >> 2];
output[1] = B64ABC[((ending[0] & 0b11) << 4) |
((ending[1] & 0b11110000) >> 4)];
output[1] =
B64ABC[((ending[0] & 0b11) << 4) | ((ending[1] & 0b11110000) >> 4)];
if (trailing > 1)
output[2] = B64ABC[((ending[1] & 0b1111) << 2) |
((ending[2] & 0b11000000) >> 6)];
if (trailing > 2)
output[3] = B64ABC[ending[2] & 0b111111];
output[2] = B64ABC
[((ending[1] & 0b1111) << 2) | ((ending[2] & 0b11000000) >> 6)];
if (trailing > 2) output[3] = B64ABC[ending[2] & 0b111111];
ss << output;
}
return ss.str();
@@ -273,7 +286,7 @@ std::string util::mangleid(uint64_t value) {
}
std::vector<ubyte> util::base64_decode(const char* str, size_t size) {
std::vector<ubyte> bytes((size/4)*3);
std::vector<ubyte> bytes((size / 4) * 3);
ubyte* dst = bytes.data();
for (size_t i = 0; i < size;) {
ubyte a = base64_decode_char(ubyte(str[i++]));
@@ -286,8 +299,8 @@ std::vector<ubyte> util::base64_decode(const char* str, size_t size) {
}
if (size >= 2) {
size_t outsize = bytes.size();
if (str[size-1] == '=') outsize--;
if (str[size-2] == '=') outsize--;
if (str[size - 1] == '=') outsize--;
if (str[size - 2] == '=') outsize--;
bytes.resize(outsize);
}
return bytes;
@@ -297,13 +310,14 @@ std::vector<ubyte> util::base64_decode(const std::string& str) {
return base64_decode(str.c_str(), str.size());
}
int util::replaceAll(std::string& str, const std::string& from, const std::string& to) {
int util::replaceAll(
std::string& str, const std::string& from, const std::string& to
) {
int count = 0;
size_t offset = 0;
while (true) {
size_t start_pos = str.find(from, offset);
if(start_pos == std::string::npos)
break;
if (start_pos == std::string::npos) break;
str.replace(start_pos, from.length(), to);
offset = start_pos + to.length();
count++;
@@ -321,7 +335,7 @@ double util::parse_double(const std::string& str) {
if (ss.fail()) {
throw std::runtime_error("invalid number format");
}
return d;
return d;
}
double util::parse_double(const std::string& str, size_t offset, size_t len) {
@@ -347,15 +361,14 @@ std::wstring util::upper_case(const std::wstring& str) {
}
std::wstring util::capitalized(const std::wstring& str) {
if (str.empty())
return str;
if (str.empty()) return str;
static const std::locale loc("");
return std::wstring({static_cast<wchar_t>(std::toupper(str[0], loc))}) + str.substr(1);
return std::wstring({static_cast<wchar_t>(std::toupper(str[0], loc))}) +
str.substr(1);
}
std::wstring util::pascal_case(const std::wstring& str) {
if (str.empty())
return str;
if (str.empty()) return str;
static const std::locale loc("");
std::wstring result = str;
bool upper = true;
@@ -375,14 +388,15 @@ std::string util::id_to_caption(const std::string& id) {
std::string result = id;
size_t index = result.find(':');
if (index < result.length()-1) {
result = result.substr(index+1);
if (index < result.length() - 1) {
result = result.substr(index + 1);
} else {
return "";
}
size_t offset = 0;
for (; offset < result.length() && result[offset] == '_'; offset++) {}
for (; offset < result.length() && result[offset] == '_'; offset++) {
}
for (; offset < result.length(); offset++) {
if (result[offset] == '_') {
result[offset] = ' ';
@@ -427,11 +441,10 @@ std::vector<std::wstring> util::split(const std::wstring& str, char delimiter) {
std::string util::format_data_size(size_t size) {
if (size < 1024) {
return std::to_string(size)+" B";
return std::to_string(size) + " B";
}
const std::string postfixes[] {
" B", " KiB", " MiB", " GiB", " TiB", " EiB", " PiB"
};
" B", " KiB", " MiB", " GiB", " TiB", " EiB", " PiB"};
int group = 0;
size_t remainder = 0;
while (size >= 1024) {
@@ -439,18 +452,19 @@ std::string util::format_data_size(size_t size) {
remainder = size % 1024;
size /= 1024;
}
return std::to_string(size)+"."+
std::to_string(static_cast<int>(round(remainder/1024.0f)))+
return std::to_string(size) + "." +
std::to_string(static_cast<int>(round(remainder / 1024.0f))) +
postfixes[group];
}
std::pair<std::string, std::string> util::split_at(std::string_view view, char c) {
std::pair<std::string, std::string> util::split_at(
std::string_view view, char c
) {
size_t idx = view.find(c);
if (idx == std::string::npos) {
throw std::runtime_error(util::quote(std::string({c}))+" not found");
throw std::runtime_error(util::quote(std::string({c})) + " not found");
}
return std::make_pair(
std::string(view.substr(0, idx)),
std::string(view.substr(idx+1))
std::string(view.substr(0, idx)), std::string(view.substr(idx + 1))
);
}
+13 -11
View File
@@ -1,13 +1,13 @@
#ifndef UTIL_STRINGUTIL_HPP_
#define UTIL_STRINGUTIL_HPP_
#include "../typedefs.hpp"
#include <string>
#include <vector>
#include "../typedefs.hpp"
namespace util {
/// @brief Function used for string serialization in text formats
/// @brief Function used for string serialization in text formats
std::string escape(const std::string& s);
/// @brief Function used for error messages
@@ -18,15 +18,15 @@ namespace util {
uint encode_utf8(uint32_t c, ubyte* bytes);
uint32_t decode_utf8(uint& size, const char* bytes);
std::string wstr2str_utf8(const std::wstring &ws);
std::wstring str2wstr_utf8(const std::string &s);
std::string wstr2str_utf8(const std::wstring& ws);
std::wstring str2wstr_utf8(const std::string& s);
bool is_integer(const std::string& text);
bool is_integer(const std::wstring& text);
bool is_valid_filename(const std::wstring &name);
bool is_valid_filename(const std::wstring& name);
void ltrim(std::string &s);
void rtrim(std::string &s);
void trim(std::string &s);
void ltrim(std::string& s);
void rtrim(std::string& s);
void trim(std::string& s);
std::string to_string(double x);
std::wstring to_wstring(double x, int precision);
@@ -37,7 +37,9 @@ namespace util {
std::string mangleid(uint64_t value);
int replaceAll(std::string& str, const std::string& from, const std::string& to);
int replaceAll(
std::string& str, const std::string& from, const std::string& to
);
double parse_double(const std::string& str);
double parse_double(const std::string& str, size_t offset, size_t len);
@@ -61,4 +63,4 @@ namespace util {
std::pair<std::string, std::string> split_at(std::string_view view, char c);
}
#endif // UTIL_STRINGUTIL_HPP_
#endif // UTIL_STRINGUTIL_HPP_
+7 -4
View File
@@ -2,21 +2,24 @@
#include <iostream>
using std::chrono::high_resolution_clock;
using std::chrono::duration_cast;
using std::chrono::high_resolution_clock;
using std::chrono::microseconds;
timeutil::Timer::Timer() {
start = high_resolution_clock::now();
}
int64_t timeutil::Timer::stop() {
return duration_cast<microseconds>(high_resolution_clock::now()-start).count();
return duration_cast<microseconds>(high_resolution_clock::now() - start)
.count();
}
timeutil::ScopeLogTimer::ScopeLogTimer(long long id) : scopeid_(id) {}
timeutil::ScopeLogTimer::ScopeLogTimer(long long id) : scopeid_(id) {
}
timeutil::ScopeLogTimer::~ScopeLogTimer() {
std::cout << "Scope "<< scopeid_ <<" finished in "<< ScopeLogTimer::stop() << " micros. \n";
std::cout << "Scope " << scopeid_ << " finished in "
<< ScopeLogTimer::stop() << " micros. \n";
}
void timeutil::from_value(float value, int& hour, int& minute, int& second) {
+6 -5
View File
@@ -1,9 +1,10 @@
#ifndef UTIL_TIMEUTIL_HPP_
#define UTIL_TIMEUTIL_HPP_
#include "../typedefs.hpp"
#include <chrono>
#include "../typedefs.hpp"
namespace timeutil {
class Timer {
std::chrono::high_resolution_clock::time_point start;
@@ -12,13 +13,13 @@ namespace timeutil {
int64_t stop();
};
/**
/**
* Timer that stops and prints time when destructor called
* @example:
* { // some scope (custom, function, if/else, cycle etc.)
* timeutil::ScopeLogTimer scopeclock();
* ...
* }
* }
*/
class ScopeLogTimer : public Timer {
long long scopeid_;
@@ -30,8 +31,8 @@ namespace timeutil {
inline constexpr float time_value(float hour, float minute, float second) {
return (hour + (minute + second / 60.0f) / 60.0f) / 24.0f;
}
void from_value(float value, int& hour, int& minute, int& second);
}
#endif // UTIL_TIMEUTIL_HPP_
#endif // UTIL_TIMEUTIL_HPP_