format: reformat project
Signed-off-by: Vyacheslav Ivanov <islavaivanov76@gmail.com>
This commit is contained in:
@@ -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
@@ -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
@@ -21,4 +21,4 @@ namespace util {
|
||||
};
|
||||
}
|
||||
|
||||
#endif // UTIL_CLOCK_HPP_
|
||||
#endif // UTIL_CLOCK_HPP_
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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
@@ -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_
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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_
|
||||
|
||||
@@ -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 << ", ";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -9,4 +9,4 @@ namespace platform {
|
||||
std::string detect_locale();
|
||||
}
|
||||
|
||||
#endif // UTIL_PLATFORM_HPP_
|
||||
#endif // UTIL_PLATFORM_HPP_
|
||||
|
||||
+100
-86
@@ -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
@@ -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_
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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_
|
||||
|
||||
Reference in New Issue
Block a user