Refactored namespaces

This commit is contained in:
emeric
2024-03-12 08:32:08 +01:00
parent 487960b413
commit 4b7c4295ec
501 changed files with 12605 additions and 12631 deletions
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2020 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <boost/crc.hpp> // for boost::crc_32_type
namespace lms::core
{
class Crc32Calculator
{
public:
void processBytes(const std::byte* _data, std::size_t dataSize)
{
_result.process_bytes(_data, dataSize);
}
std::uint32_t getResult() const
{
return _result.checksum();
}
private:
using Crc32Type = boost::crc_32_type;
Crc32Type _result;
};
}
+193
View File
@@ -0,0 +1,193 @@
/*
* Copyright (C) 2020 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <cassert>
#include <cstdint>
#include <initializer_list>
#include <limits>
#include <type_traits>
namespace lms::core
{
template <typename T, typename underlying_type = std::uint32_t>
class EnumSet
{
static_assert(std::is_enum<T>::value);
static_assert(std::is_same<underlying_type, std::uint64_t>::value || std::is_same<underlying_type, std::uint32_t>::value);
using IndexType = std::uint_fast8_t;
public:
using ValueType = underlying_type;
EnumSet() = default;
constexpr EnumSet(std::initializer_list<T> values)
{
for (T value : values)
insert(value);
}
template <typename It>
constexpr EnumSet(It begin, It end)
{
assign(begin, end);
}
template <typename It>
constexpr void assign(It begin, It end)
{
clear();
for (It it{ begin }; it != end; ++it)
insert(*it);
}
constexpr void insert(T value)
{
assert(static_cast<std::size_t>(value) < sizeof(_bitfield) * 8);
_bitfield |= (underlying_type{ 1 } << static_cast<underlying_type>(value));
}
constexpr void erase(T value)
{
assert(static_cast<std::size_t>(value) < sizeof(_bitfield) * 8);
_bitfield &= ~(underlying_type{ 1 } << static_cast<underlying_type>(value));
}
constexpr bool empty() const
{
return _bitfield == 0;
}
constexpr bool contains(T value) const
{
assert(static_cast<std::size_t>(value) < sizeof(_bitfield) * 8);
return _bitfield & (underlying_type{ 1 } << static_cast<underlying_type>(value));
}
constexpr void clear()
{
_bitfield = 0;
}
class iterator
{
public:
using value_type = T;
constexpr value_type operator*() const
{
return static_cast<value_type>(_index);
}
constexpr bool operator==(const iterator& _other) const
{
return &_container == &_other._container && _index == _other._index;
}
constexpr bool operator!=(const iterator& _other) const
{
return !(*this == _other);
}
constexpr iterator& operator++()
{
_index = _container.getFirstBitSetIndex(_index + 1);
return *this;
}
private:
friend class EnumSet;
constexpr iterator(const EnumSet& _container, IndexType _index)
: _container{ _container }
, _index{ _index }
{
}
const EnumSet& _container;
IndexType _index;
};
constexpr iterator begin() const
{
return iterator{ *this, getFirstBitSetIndex() };
}
constexpr iterator end() const
{
return iterator{ *this, npos };
}
constexpr underlying_type getBitfield() const
{
return _bitfield;
}
constexpr void setBitfield(underlying_type bitfield)
{
_bitfield = bitfield;
}
constexpr bool operator==(const EnumSet other) const
{
return _bitfield == other._bitfield;
}
constexpr bool operator!=(const EnumSet other) const
{
return _bitfield != other._bitfield;
}
private:
static_assert(std::numeric_limits<IndexType>::max() >= sizeof(underlying_type) * 8);
enum : IndexType { npos = sizeof(underlying_type) * 8 };
constexpr IndexType getFirstBitSetIndex(IndexType start = {}) const
{
assert(start < npos);
// return npos if no bit found
IndexType res{ countTrailingZero(_bitfield >> start) };
if (res == npos)
return res;
return res + start;
}
static constexpr IndexType countTrailingZero(underlying_type bitField)
{
IndexType res{};
while (res < (sizeof(underlying_type) * 8) && (bitField & 1) == 0)
{
++res;
bitField >>= 1;
}
if (res == sizeof(underlying_type) * 8)
res = npos;
return res;
}
underlying_type _bitfield{};
};
}
+34
View File
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2018 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdexcept>
#include <string>
#include <string_view>
namespace lms::core
{
// TODO, rename to Exception
class LmsException : public std::runtime_error
{
public:
LmsException(std::string_view error = "") : std::runtime_error{ std::string{ error } } {}
};
}
@@ -0,0 +1,31 @@
/*
* Copyright (C) 2020 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <filesystem>
#include <memory>
#include <string_view>
#include "core/IResourceHandler.hpp"
namespace lms
{
std::unique_ptr<IResourceHandler> createFileResourceHandler(const std::filesystem::path& path, std::string_view mimeType);
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2020 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <cstddef>
#include <functional>
#include <string>
#include <vector>
#include "core/Exception.hpp"
namespace lms::core
{
class ChildProcessException : public LmsException
{
public:
using LmsException::LmsException;
};
class IChildProcess
{
public:
using Args = std::vector<std::string>;
virtual ~IChildProcess() = default;
enum class ReadResult
{
Success,
Error,
EndOfFile,
};
using ReadCallback = std::function<void(ReadResult, std::size_t)>;
virtual void asyncRead(std::byte* data, std::size_t bufferSize, ReadCallback callback) = 0;
virtual std::size_t readSome(std::byte* data, std::size_t bufferSize) = 0;
virtual bool finished() const = 0;
};
}
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2020 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <filesystem>
#include <memory>
#include <boost/asio/io_service.hpp>
#include "IChildProcess.hpp"
namespace lms::core
{
class IChildProcessManager
{
public:
virtual ~IChildProcessManager() = default;
virtual std::unique_ptr<IChildProcess> spawnChildProcess(const std::filesystem::path& path, const IChildProcess::Args& args) = 0;
};
std::unique_ptr<IChildProcessManager> createChildProcessManager(boost::asio::io_service& ioService);
}
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2016 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <filesystem>
#include <functional>
#include <string_view>
namespace lms::core
{
// Used to get config values from configuration files
class IConfig
{
public:
virtual ~IConfig() = default;
// Default values are returned in case of setting not found
virtual std::string_view getString(std::string_view setting, std::string_view def = "") = 0;
virtual void visitStrings(std::string_view setting, std::function<void(std::string_view)> _func, std::initializer_list<std::string_view> def = {}) = 0;
virtual std::filesystem::path getPath(std::string_view setting, const std::filesystem::path& def = std::filesystem::path()) = 0;
virtual unsigned long getULong(std::string_view setting, unsigned long def = 0) = 0;
virtual long getLong(std::string_view setting, long def = 0) = 0;
virtual bool getBool(std::string_view setting, bool def = false) = 0;
};
std::unique_ptr<IConfig> createConfig(const std::filesystem::path& p);
}
+103
View File
@@ -0,0 +1,103 @@
/*
* Copyright (C) 2013 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <string>
#include <sstream>
#include "core/String.hpp"
#include "Service.hpp"
namespace lms::core::logging
{
enum class Severity
{
FATAL,
ERROR,
WARNING,
INFO,
DEBUG,
};
enum class Module
{
API_SUBSONIC,
AUTH,
AV,
CHILDPROCESS,
COVER,
DB,
DBUPDATER,
FEATURE,
FEEDBACK,
HTTP,
MAIN,
METADATA,
REMOTE,
SCROBBLING,
SERVICE,
RECOMMENDATION,
TRANSCODING,
UI,
UTILS,
};
const char* getModuleName(Module mod);
const char* getSeverityName(Severity sev);
class ILogger;
class Log
{
public:
Log(ILogger& logger, Module module, Severity severity);
~Log();
Module getModule() const { return _module; }
Severity getSeverity() const { return _severity; }
std::string getMessage() const;
std::ostringstream& getOstream() { return _oss; }
private:
Log(const Log&) = delete;
Log& operator=(const Log&) = delete;
ILogger& _logger;
Module _module;
Severity _severity;
std::ostringstream _oss;
};
class ILogger
{
public:
virtual ~ILogger() = default;
virtual bool isSeverityActive(Severity severity) const = 0;
virtual void processLog(const Log& log) = 0;
};
}
#define LMS_LOG(module, severity, message) \
do \
{ \
if (auto* logger_ {::lms::core::Service<::lms::core::logging::ILogger>::get()}; logger_ && logger_->isSeverityActive(::lms::core::logging::Severity::severity)) \
::lms::core::logging::Log{ *logger_, ::lms::core::logging::Module::module, ::lms::core::logging::Severity::severity }.getOstream() << message; \
} while(0)
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2021 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <optional>
#include <thread>
#include <boost/asio/io_service.hpp>
namespace lms::core
{
class IOContextRunner
{
public:
IOContextRunner(boost::asio::io_service& ioService, std::size_t threadCount, std::string_view name);
~IOContextRunner();
void stop();
std::size_t getThreadCount() const;
private:
IOContextRunner(const IOContextRunner&) = delete;
IOContextRunner& operator=(const IOContextRunner&) = delete;
boost::asio::io_service& _ioService;
std::optional<boost::asio::io_service::work> _work;
std::vector<std::thread> _threads;
};
}
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2020 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <Wt/Http/Request.h>
#include <Wt/Http/Response.h>
// TODO, move elsewhere
namespace lms
{
// Helper class to serve a resource (must be saved as continuation data if not complete)
class IResourceHandler
{
public:
virtual ~IResourceHandler() = default;
[[nodiscard]] virtual Wt::Http::ResponseContinuation* processRequest(const Wt::Http::Request& request, Wt::Http::Response& response) = 0;
virtual void abort() = 0;
};
}
+115
View File
@@ -0,0 +1,115 @@
/*
* Copyright (C) 2024 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <chrono>
#include <memory>
#include <ostream>
#include <string_view>
#include <thread>
#include "LiteralString.hpp"
#include "Service.hpp"
#define LMS_SUPPORT_TRACING 1
#define LMS_CONCAT_IMPL(x, y) x##y
#define LMS_CONCAT(x, y) LMS_CONCAT_IMPL(x, y)
#if LMS_SUPPORT_TRACING
#define LMS_SCOPED_TRACE(CATEGORY, LEVEL, NAME) ::lms::core::tracing::ScopedTrace LMS_CONCAT(ScopedTrace_, __LINE__){ CATEGORY, LEVEL, NAME }
#else
#define LMS_SCOPED_TRACE(CATEGORY, LEVEL, NAME) (void)0
#endif
#define LMS_SCOPED_TRACE_OVERVIEW(CATEGORY, NAME) LMS_SCOPED_TRACE(CATEGORY, ::lms::core::tracing::Level::Overview, NAME)
#define LMS_SCOPED_TRACE_DETAILED(CATEGORY, NAME) LMS_SCOPED_TRACE(CATEGORY, ::lms::core::tracing::Level::Detailed, NAME)
namespace lms::core::tracing
{
using clock = std::chrono::steady_clock;
enum class Level
{
Overview,
Detailed,
};
class ITraceLogger
{
public:
struct CompleteEvent
{
clock::time_point start;
clock::duration duration;
std::thread::id threadId;
LiteralString name;
LiteralString category;
};
virtual ~ITraceLogger() = default;
virtual bool isLevelActive(Level level) const = 0;
virtual void write(const CompleteEvent& entry) = 0;
virtual void dumpCurrentBuffer(std::ostream& os) = 0;
virtual void setThreadName(std::thread::id id, std::string_view threadName) = 0;
};
static constexpr std::size_t MinBufferSizeInMBytes = 16;
std::unique_ptr<ITraceLogger> createTraceLogger(Level minLevel = Level::Overview, std::size_t bufferSizeInMbytes = MinBufferSizeInMBytes);
class ScopedTrace
{
public:
ScopedTrace(LiteralString category, Level level, LiteralString name, ITraceLogger* traceLogger = Service<ITraceLogger>::get())
{
if (traceLogger && traceLogger->isLevelActive(level))
{
_traceLogger = traceLogger;
_event.start = clock::now();
_event.threadId = std::this_thread::get_id();
_event.name = name;
_event.category = category;
}
else
{
_traceLogger = nullptr;
}
}
~ScopedTrace()
{
if (_traceLogger)
{
_event.duration = clock::now() - _event.start;
_traceLogger->write(_event);
}
}
private:
ScopedTrace(const ScopedTrace&) = delete;
ScopedTrace& operator=(const ScopedTrace&) = delete;
ITraceLogger* _traceLogger;
ITraceLogger::CompleteEvent _event;
};
}
+54
View File
@@ -0,0 +1,54 @@
/*
* Copyright (C) 2020 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <filesystem>
#include <memory>
#include <vector>
#include "Exception.hpp"
// TODO, move elsewhere?
namespace lms::zip
{
struct Entry
{
std::string fileName;
std::filesystem::path filePath;
};
using EntryContainer = std::vector<Entry>;
class Exception : public core::LmsException
{
using core::LmsException::LmsException;
};
class IZipper
{
public:
virtual ~IZipper() = default;
virtual std::uint64_t writeSome(std::ostream& output) = 0;
virtual bool isComplete() const = 0;
virtual void abort() = 0;
};
std::unique_ptr<IZipper> createArchiveZipper(const EntryContainer& entries);
}
@@ -0,0 +1,101 @@
/*
* Copyright (C) 2024 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <cstddef>
#include <string>
#include <string_view>
namespace lms::core
{
class LiteralString
{
public:
constexpr LiteralString() noexcept = default;
template<std::size_t N>
constexpr LiteralString(const char(&str)[N]) noexcept : _str{ str, N - 1 } { static_assert(N > 0); }
constexpr const char* c_str() const noexcept { return _str.data(); }
constexpr std::size_t length() const noexcept { return _str.length(); }
constexpr std::string_view str() const noexcept { return _str; }
constexpr auto operator<=>(const LiteralString& other) const = default;
private:
std::string_view _str;
};
}
namespace std
{
template<>
struct hash<lms::core::LiteralString>
{
size_t operator()(const lms::core::LiteralString& str) const
{
return hash<std::string_view>{}(str.str());
}
};
}
namespace lms::core
{
struct LiteralStringHash
{
using hash_type = std::hash<std::string_view>;
using is_transparent = void;
[[nodiscard]] size_t operator()(const LiteralString& str) const {
return hash_type{}(str.str());
}
[[nodiscard]] size_t operator()(std::string_view str) const {
return hash_type{}(str);
}
[[nodiscard]] size_t operator()(const std::string& str) const {
return hash_type{}(str);
}
};
struct LiteralStringEqual
{
using is_transparent = void;
[[nodiscard]] bool operator()(const LiteralString& lhs, const LiteralString& rhs) const {
return lhs == rhs;
}
[[nodiscard]] bool operator()(const LiteralString& lhs, const std::string& rhs) const {
return lhs.str() == rhs;
}
[[nodiscard]] bool operator()(const LiteralString& lhs, std::string_view rhs) const {
return lhs.str() == rhs;
}
[[nodiscard]] bool operator()(const std::string_view& lhs, LiteralString rhs) const {
return lhs == rhs.str();
}
[[nodiscard]] bool operator()(const std::string& lhs, const LiteralString& rhs) const {
return lhs == rhs.str();
}
};
}
+36
View File
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2019 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <boost/asio/ip/address.hpp>
#ifndef BOOST_ASIO_HAS_STD_HASH
#include <functional>
namespace std
{
template<> struct hash<boost::asio::ip::address>
{
std::size_t operator()(const boost::asio::ip::address& ipAddr) const;
};
}
#endif // BOOST_ASIO_HAS_STD_HASH
+67
View File
@@ -0,0 +1,67 @@
/*
* Copyright (C) 2016 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <filesystem>
#include <functional>
#include <string>
#include <vector>
#include <Wt/WDateTime.h>
namespace lms::core::pathUtils
{
std::uint32_t computeCrc32(const std::filesystem::path& p);
// Make sure the given path is a directory
// Create it if needed
bool ensureDirectory(const std::filesystem::path& dir);
// Get the last write time since Epoch
Wt::WDateTime getLastWriteTime(const std::filesystem::path& dir);
// returns false if aborted by user
bool exploreFilesRecursive(const std::filesystem::path& directory, std::function<bool(std::error_code, const std::filesystem::path&)> cb, const std::filesystem::path* excludeDirFileName = {});
// Check if file's extension is one of provided extensions
bool hasFileAnyExtension(const std::filesystem::path& file, const std::vector<std::filesystem::path>& extensions);
// Check if a path is within a directory (excludeDirFileName is a relative can be used to exclude a whole directory and its subdirectory, must not have parent_path)
// Caller responsibility to call with normalized paths
bool isPathInRootPath(const std::filesystem::path& path, const std::filesystem::path& rootPath, const std::filesystem::path* excludeDirFileName = {});
std::filesystem::path getLongestCommonPath(const std::filesystem::path& path1, const std::filesystem::path& path2);
template <typename Iterator>
std::filesystem::path getLongestCommonPath(Iterator first, Iterator last)
{
std::filesystem::path longestCommonPath;
if (first == last)
return longestCommonPath;
longestCommonPath = *first++;
while (first != last)
longestCommonPath = core::pathUtils::getLongestCommonPath(*first++, longestCommonPath);
return longestCommonPath;
}
}
+60
View File
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2020 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <algorithm>
#include <random>
namespace lms::core::random
{
using RandGenerator = std::mt19937;
RandGenerator& getRandGenerator();
RandGenerator createSeededGenerator(uint_fast32_t seed);
template <typename T>
T getRandom(T min, T max)
{
std::uniform_int_distribution<> dist{ min, max };
return dist(getRandGenerator());
}
template <typename T>
T getRealRandom(T min, T max)
{
std::uniform_real_distribution<> dist{ min, max };
return dist(getRandGenerator());
}
template <typename Container>
void shuffleContainer(Container& container)
{
std::shuffle(std::begin(container), std::end(container), getRandGenerator());
}
template <typename Container>
typename Container::const_iterator pickRandom(const Container& container)
{
if (container.empty())
return std::end(container);
return std::next(std::begin(container), getRandom(0, static_cast<int>(container.size() - 1)));
}
}
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2021 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <mutex>
#include <shared_mutex>
#include <thread>
#include <unordered_map>
namespace lms::core
{
// API compatible with shared_mutex
class RecursiveSharedMutex
{
public:
void lock();
void unlock();
void lock_shared();
void unlock_shared();
#ifndef NDEBUG
bool isSharedLocked();
bool isUniqueLocked();
#endif // NDEBUG
private:
std::shared_mutex _mutex;
std::thread::id _uniqueOwner;
std::size_t _uniqueCount{};
std::mutex _sharedCountMutex;
std::unordered_map<std::thread::id, std::size_t> _sharedCounts;
};
}
+73
View File
@@ -0,0 +1,73 @@
/*
* Copyright (C) 2019 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <cassert>
#include <memory>
namespace lms::core
{
template <typename Class>
class Service
{
public:
Service() = default;
Service(std::unique_ptr<Class> service)
{
assign(std::move(service));
}
~Service()
{
clear();
}
Service(const Service&) = delete;
Service(Service&&) = delete;
Service& operator=(const Service&) = delete;
Service& operator=(Service&&) = delete;
Class* operator->() const
{
return Service<Class>::get();
}
Class& operator*() const
{
return *Service<Class>::get();
}
static Class* get() { return _service.get(); }
static bool exists() { return _service.get(); }
template <typename SubClass>
static Class& assign(std::unique_ptr<SubClass> service)
{
assert(!_service);
_service = std::move(service);
return *get();
}
private:
static void clear() { _service.reset(); }
static inline std::unique_ptr<Class> _service;
};
}
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2019 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "core/EnumSet.hpp"
#include "core/ILogger.hpp"
namespace lms::core::logging
{
class StreamLogger final : public ILogger
{
public:
static constexpr EnumSet<Severity> allSeverities{ Severity::FATAL, Severity::ERROR, Severity::WARNING, Severity::INFO, Severity::DEBUG };
static constexpr EnumSet<Severity> defaultSeverities{ Severity::FATAL, Severity::ERROR, Severity::WARNING, Severity::INFO };
StreamLogger(std::ostream& oss, EnumSet<Severity> severities = defaultSeverities);
bool isSeverityActive(Severity severity) const override { return _severities.contains(severity); }
void processLog(const Log& log) override;
private:
std::ostream& _os;
const EnumSet<Severity> _severities;
};
}
+103
View File
@@ -0,0 +1,103 @@
/*
* Copyright (C) 2020 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <initializer_list>
#include <optional>
#include <span>
#include <string>
#include <string_view>
#include <sstream>
#include <vector>
#define QUOTEME(x) QUOTEME_1(x)
#define QUOTEME_1(x) #x
namespace Wt
{
class WDate;
class WDateTime;
}
namespace lms::core::stringUtils
{
[[nodiscard]] std::vector<std::string_view> splitString(std::string_view string, char separator);
[[nodiscard]] std::vector<std::string_view> splitString(std::string_view string, std::string_view separator);
[[nodiscard]] std::string joinStrings(std::span<const std::string> strings, std::string_view delimiter);
[[nodiscard]] std::string joinStrings(std::span<const std::string_view> strings, std::string_view delimiter);
[[nodiscard]] std::string joinStrings(std::span<const std::string> strings, char delimiter);
[[nodiscard]] std::string joinStrings(std::span<const std::string_view> strings, char delimiter);
[[nodiscard]] std::string escapeAndJoinStrings(std::span<const std::string_view> strings, char delimiter, char escapeChar);
[[nodiscard]] std::vector<std::string> splitEscapedStrings(std::string_view string, char delimiter, char escapeChar);
[[nodiscard]] std::string_view stringTrim(std::string_view str, std::string_view whitespaces = " \t");
[[nodiscard]] std::string_view stringTrimEnd(std::string_view str, std::string_view whitespaces = " \t");
[[nodiscard]] std::string stringToLower(std::string_view str);
void stringToLower(std::string& str);
[[nodiscard]] std::string stringToUpper(const std::string& str);
[[nodiscard]] std::string bufferToString(std::span<const unsigned char> data);
[[nodiscard]] bool stringCaseInsensitiveEqual(std::string_view strA, std::string_view strB);
void capitalize(std::string& str);
template<typename T>
[[nodiscard]] std::optional<T> readAs(std::string_view str)
{
T res;
std::istringstream iss{ std::string {str} };
iss >> res;
if (iss.fail())
return std::nullopt;
return res;
}
template<>
[[nodiscard]] std::optional<std::string> readAs(std::string_view str);
template<>
[[nodiscard]] std::optional<std::string_view> readAs(std::string_view str);
template<>
[[nodiscard]] std::optional<bool> readAs(std::string_view str);
[[nodiscard]] std::string replaceInString(std::string_view str, const std::string& from, const std::string& to);
[[nodiscard]] std::string jsEscape(std::string_view str);
[[nodiscard]] std::string jsonEscape(std::string_view str);
void writeJSEscapedString(std::ostream& os, std::string_view str);
void writeJsonEscapedString(std::ostream& os, std::string_view str);
[[nodiscard]] std::string escapeString(std::string_view str, std::string_view charsToEscape, char escapeChar);
[[nodiscard]] std::string unescapeString(std::string_view str, char escapeChar);
[[nodiscard]] bool stringEndsWith(std::string_view str, std::string_view ending);
[[nodiscard]] std::optional<std::string> stringFromHex(const std::string& str);
[[nodiscard]] std::string toISO8601String(const Wt::WDateTime& dateTime);
[[nodiscard]] std::string toISO8601String(const Wt::WDate& date);
}
+49
View File
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2015 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <tuple>
namespace lms::core
{
namespace details
{
template<int... Is>
struct Seq { };
template<int N, int... Is>
struct GenSeq : GenSeq<N - 1, N - 1, Is...> { };
template<int... Is>
struct GenSeq<0, Is...> : Seq<Is...> { };
template<typename T, typename Func, int... Is>
void forEachTypeInTuple(T&& t, Func f, Seq<Is...>)
{
auto l = { (f(std::get<Is>(t)), 0)... };
}
}
template<typename... Ts, typename Func>
void forEachTypeInTuple(std::tuple<Ts...> const& t, Func f)
{
details::forEachTypeInTuple(t, f, details::GenSeq<sizeof...(Ts)>());
}
}
+51
View File
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2020 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <optional>
#include <string>
#include <string_view>
#include "core/String.hpp"
namespace lms::core
{
class UUID
{
public:
static std::optional<UUID> fromString(std::string_view str);
static UUID generate();
std::string_view getAsString() const { return _value; }
bool operator<=>(const core::UUID&) const = default;
private:
UUID(std::string_view value);
std::string _value;
};
}
namespace lms::core::stringUtils
{
template <>
std::optional<UUID>
readAs(std::string_view str);
}
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2015 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <algorithm>
#include <functional>
namespace lms::core::utils
{
template<class T, class Compare = std::less<>>
constexpr T clamp(T v, T lo, T hi, Compare comp = {})
{
assert(!comp(hi, lo));
return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
}
template <typename Container, typename T>
void
push_back_if_not_present(Container& container, const T& val)
{
if (std::find(std::cbegin(container), std::cend(container), val) == std::cend(container))
container.push_back(val);
}
}
+40
View File
@@ -0,0 +1,40 @@
/*
* Copyright (C) 2019 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <string>
#include "core/ILogger.hpp"
namespace lms::core::logging
{
class WtLogger final : public ILogger
{
public:
WtLogger(Severity minSeverity);
static std::string computeLogConfig(Severity minSeverity);
private:
bool isSeverityActive(Severity severity) const override;
void processLog(const Log& log) override;
const Severity _minSeverity;
};
}
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2020 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <memory>
#include "core/IResourceHandler.hpp"
#include "core/IZipper.hpp"
namespace lms::zip
{
std::unique_ptr<IResourceHandler> createZipperResourceHandler(std::unique_ptr<IZipper> zipper);
}
@@ -0,0 +1,59 @@
/*
* Copyright (C) 2021 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <functional>
#include <string_view>
#include <vector>
#include <Wt/Http/Message.h>
namespace lms::core::http
{
struct ClientRequestParameters
{
enum class Priority
{
High,
Normal,
Low,
};
Priority priority{ Priority::Normal };
std::string relativeUrl; // relative to baseUrl used by the client
using OnSuccessFunc = std::function<void(std::string_view msgBody)>;
OnSuccessFunc onSuccessFunc;
using OnFailureFunc = std::function<void()>;
OnFailureFunc onFailureFunc;
};
struct ClientGETRequestParameters final : public ClientRequestParameters
{
std::vector<Wt::Http::Message::Header> headers;
};
struct ClientPOSTRequestParameters final : public ClientRequestParameters
{
Wt::Http::Message message;
};
}
@@ -0,0 +1,39 @@
/*
* Copyright (C) 2021 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <string_view>
#include <boost/asio/io_context.hpp>
#include "core/http/ClientRequestParameters.hpp"
namespace lms::core::http
{
class IClient
{
public:
virtual ~IClient() = default;
virtual void sendGETRequest(ClientGETRequestParameters&& request) = 0;
virtual void sendPOSTRequest(ClientPOSTRequestParameters&& request) = 0;
};
std::unique_ptr<IClient> createClient(boost::asio::io_context& ioContext, std::string_view baseUrl);
}