From e274c0ca899c5eb200af70474bf9c06099dd6b02 Mon Sep 17 00:00:00 2001 From: emeric Date: Sat, 8 Feb 2020 17:44:12 +0100 Subject: [PATCH] Split the utils file --- src/Makefile.am | 6 +- src/api/subsonic/SubsonicId.cpp | 6 +- src/api/subsonic/SubsonicResource.cpp | 119 +++++++++-------- src/auth/AuthTokenService.cpp | 1 - src/auth/LoginThrottler.cpp | 4 +- src/auth/PasswordService.cpp | 1 - src/av/AvInfo.cpp | 9 +- src/database/Artist.hpp | 2 +- src/database/Release.hpp | 2 +- src/database/ScanSettings.cpp | 6 +- src/database/Track.hpp | 2 +- src/metadata/AvFormat.cpp | 36 ++--- src/metadata/MetaData.hpp | 2 +- src/metadata/TagLibParser.cpp | 39 +++--- src/scanner/MediaScanner.cpp | 1 - .../cluster/SimilarityClusterSearcher.cpp | 1 - .../features/SimilarityFeaturesCache.cpp | 1 - .../features/SimilarityFeaturesSearcher.cpp | 1 - src/ui/LmsApplication.cpp | 4 +- src/ui/MediaPlayer.cpp | 8 +- src/ui/PlayQueueView.cpp | 6 +- src/ui/admin/DatabaseSettingsView.cpp | 6 +- src/ui/admin/UserView.cpp | 4 +- src/ui/explore/ArtistInfoView.cpp | 4 +- src/ui/explore/ArtistView.cpp | 4 +- src/ui/explore/ArtistsInfoView.cpp | 1 - src/ui/explore/ArtistsView.cpp | 4 +- src/ui/explore/ReleaseInfoView.cpp | 4 +- src/ui/explore/ReleaseLink.cpp | 1 - src/ui/explore/ReleaseView.cpp | 4 +- src/ui/explore/ReleasesView.cpp | 4 +- src/ui/explore/TracksInfoView.cpp | 2 - src/ui/explore/TracksView.cpp | 4 +- src/ui/resource/ImageResource.cpp | 8 +- .../MetaData.cpp => utils/Random.cpp} | 15 ++- src/utils/Random.hpp | 64 +++++++++ src/utils/{Utils.cpp => String.cpp} | 18 +-- src/utils/String.hpp | 73 +++++++++++ src/utils/UUID.cpp | 17 ++- src/utils/UUID.hpp | 18 +-- src/utils/Utils.hpp | 124 +----------------- test/Makefile.am | 2 +- tools/metadata/Makefile.am | 3 +- .../GeneticAlgorithm.hpp | 7 +- .../LmsSimilarityParameters.cpp | 8 +- tools/similarity-parameters/Makefile.am | 3 +- tools/similarity/Makefile.am | 2 +- 47 files changed, 343 insertions(+), 318 deletions(-) rename src/{metadata/MetaData.cpp => utils/Random.cpp} (73%) create mode 100644 src/utils/Random.hpp rename src/utils/{Utils.cpp => String.cpp} (93%) create mode 100644 src/utils/String.hpp diff --git a/src/Makefile.am b/src/Makefile.am index b89df341..4fd65f58 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -55,7 +55,6 @@ lms_SOURCES = \ $(srcdir)/main/main.cpp \ $(srcdir)/metadata/AvFormat.cpp \ $(srcdir)/metadata/AvFormat.hpp \ - $(srcdir)/metadata/MetaData.cpp \ $(srcdir)/metadata/MetaData.hpp \ $(srcdir)/metadata/TagLibParser.cpp \ $(srcdir)/metadata/TagLibParser.hpp \ @@ -155,10 +154,13 @@ lms_SOURCES = \ $(srcdir)/utils/NetAddress.hpp \ $(srcdir)/utils/Path.cpp \ $(srcdir)/utils/Path.hpp \ + $(srcdir)/utils/Random.cpp \ + $(srcdir)/utils/Random.hpp \ $(srcdir)/utils/Service.hpp \ $(srcdir)/utils/StreamLogger.cpp \ $(srcdir)/utils/StreamLogger.hpp \ - $(srcdir)/utils/Utils.cpp \ + $(srcdir)/utils/String.cpp \ + $(srcdir)/utils/String.hpp \ $(srcdir)/utils/Utils.hpp \ $(srcdir)/utils/UUID.cpp \ $(srcdir)/utils/UUID.hpp \ diff --git a/src/api/subsonic/SubsonicId.cpp b/src/api/subsonic/SubsonicId.cpp index 64cbc6eb..6f9e7c19 100644 --- a/src/api/subsonic/SubsonicId.cpp +++ b/src/api/subsonic/SubsonicId.cpp @@ -22,7 +22,7 @@ #include "SubsonicResponse.hpp" #include "utils/Logger.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" namespace API::Subsonic { @@ -33,7 +33,7 @@ IdFromString(const std::string& id) if (id == "root") return Id {Id::Type::Root}; - std::vector values {splitString(id, "-")}; + std::vector values {StringUtils::splitString(id, "-")}; if (values.size() != 2) return std::nullopt; @@ -51,7 +51,7 @@ IdFromString(const std::string& id) else return std::nullopt; - auto optId {readAs(values[1])}; + auto optId {StringUtils::readAs(values[1])}; if (!optId) return std::nullopt; diff --git a/src/api/subsonic/SubsonicResource.cpp b/src/api/subsonic/SubsonicResource.cpp index f78118aa..a52f5d22 100644 --- a/src/api/subsonic/SubsonicResource.cpp +++ b/src/api/subsonic/SubsonicResource.cpp @@ -41,6 +41,7 @@ #include "similarity/SimilaritySearcher.hpp" #include "utils/Logger.hpp" #include "utils/Service.hpp" +#include "utils/String.hpp" #include "utils/Utils.hpp" #include "SubsonicId.hpp" #include "SubsonicResponse.hpp" @@ -52,65 +53,69 @@ static const std::string reportedStarredDate {"2000-01-01T00:00:00"}; static const std::string reportedCreatedBookmarkDate {"2000-01-01T00:00:00"}; static const std::string reportedChangedBookmarkDate {"2000-01-01T00:00:00"}; -template<> -std::optional -readAs(const std::string& str) -{ - return API::Subsonic::IdFromString(str); -} - -template<> -std::optional -readAs(const std::string& str) -{ - if (str == "true") - return true; - else if (str == "false") - return false; - - return {}; -} - namespace API::Subsonic { -struct ClientVersion -{ - unsigned major {}; - unsigned minor {}; - unsigned patch {}; -}; + struct ClientVersion + { + unsigned major {}; + unsigned minor {}; + unsigned patch {}; + }; } -template<> -std::optional -readAs(const std::string& str) +namespace StringUtils { - // Expects "X.Y.Z" - const auto numbers {splitString(str, ".")}; - if (numbers.size() < 2 || numbers.size() > 3) - return std::nullopt; - - API::Subsonic::ClientVersion version; - - auto number {readAs(numbers[0])}; - if (!number) - return std::nullopt; - version.major = *number; - - number = {readAs(numbers[1])}; - if (!number) - return std::nullopt; - version.minor = *number; - - if (numbers.size() == 3) + template<> + std::optional + StringUtils::readAs(const std::string& str) { - number = {readAs(numbers[2])}; - if (!number) - return std::nullopt; - version.patch = *number; + return API::Subsonic::IdFromString(str); + } + + template<> + std::optional + StringUtils::readAs(const std::string& str) + { + if (str == "true") + return true; + else if (str == "false") + return false; + + return {}; + } + + template<> + std::optional + StringUtils::readAs(const std::string& str) + { + // Expects "X.Y.Z" + const auto numbers {StringUtils::splitString(str, ".")}; + if (numbers.size() < 2 || numbers.size() > 3) + return std::nullopt; + + API::Subsonic::ClientVersion version; + + auto number {StringUtils::readAs(numbers[0])}; + if (!number) + return std::nullopt; + version.major = *number; + + number = {StringUtils::readAs(numbers[1])}; + if (!number) + return std::nullopt; + version.minor = *number; + + if (numbers.size() == 3) + { + number = {StringUtils::readAs(numbers[2])}; + if (!number) + return std::nullopt; + version.patch = *number; + } + + return version; } - return version; } @@ -136,7 +141,7 @@ static std::string makeNameFilesystemCompatible(const std::string& name) { - return replaceInString(name, "/", "_"); + return StringUtils::replaceInString(name, "/", "_"); } template @@ -151,7 +156,7 @@ getMultiParametersAs(const Wt::Http::ParameterMap& parameterMap, const std::stri for (const std::string& param : it->second) { - auto value {readAs(param)}; + auto value {StringUtils::readAs(param)}; if (!value) throw BadParameterFormatGenericError {paramName}; @@ -201,7 +206,7 @@ decodePasswordIfNeeded(const std::string& password) { if (password.find("enc:") == 0) { - auto decodedPassword {stringFromHex(password.substr(4))}; + auto decodedPassword {StringUtils::stringFromHex(password.substr(4))}; if (!decodedPassword) return password; // fallback on plain password @@ -310,7 +315,7 @@ getArtistNames(const std::vector& artists) return artist->getName(); }); - return joinStrings(names, ", "); + return StringUtils::joinStrings(names, ", "); } static @@ -1386,7 +1391,7 @@ handleSearchRequestCommon(RequestContext& context, bool id3) // Mandatory params std::string query {getMandatoryParameterAs(context.parameters, "query")}; - std::vector keywords {splitString(query, " ")}; + std::vector keywords {StringUtils::splitString(query, " ")}; // Optional params std::size_t artistCount {getParameterAs(context.parameters, "artistCount").value_or(20)}; @@ -2035,7 +2040,7 @@ SubsonicResource::handleRequest(const Wt::Http::Request &request, Wt::Http::Resp LMS_LOG(API_SUBSONIC, DEBUG) << "Handling request " << requestId << " '" << request.pathInfo() << "', continuation = " << (request.continuation() ? "true" : "false") << ", params = " << parameterMapToDebugString(request.getParameterMap()); std::string requestPath {request.pathInfo()}; - if (stringEndsWith(requestPath, ".view")) + if (StringUtils::stringEndsWith(requestPath, ".view")) requestPath.resize(requestPath.length() - 5); const Wt::Http::ParameterMap& parameters {request.getParameterMap()}; diff --git a/src/auth/AuthTokenService.cpp b/src/auth/AuthTokenService.cpp index 99105959..14cb933c 100644 --- a/src/auth/AuthTokenService.cpp +++ b/src/auth/AuthTokenService.cpp @@ -27,7 +27,6 @@ #include "database/Session.hpp" #include "utils/Exception.hpp" -#include "utils/Utils.hpp" #include "utils/Logger.hpp" namespace Auth { diff --git a/src/auth/LoginThrottler.cpp b/src/auth/LoginThrottler.cpp index 5d49167e..6a7470ed 100644 --- a/src/auth/LoginThrottler.cpp +++ b/src/auth/LoginThrottler.cpp @@ -22,7 +22,7 @@ #include "LoginThrottler.hpp" #include "utils/Logger.hpp" -#include "utils/Utils.hpp" +#include "utils/Random.hpp" namespace Auth { @@ -71,7 +71,7 @@ LoginThrottler::onBadClientAttempt(const boost::asio::ip::address& address) if (_attemptsInfo.size() >= _maxEntries) removeOutdatedEntries(); if (_attemptsInfo.size() >= _maxEntries) - _attemptsInfo.erase(pickRandom(_attemptsInfo)); + _attemptsInfo.erase(Random::pickRandom(_attemptsInfo)); _attemptsInfo[address] = now.addSecs(3); diff --git a/src/auth/PasswordService.cpp b/src/auth/PasswordService.cpp index 383c667d..1c592f45 100644 --- a/src/auth/PasswordService.cpp +++ b/src/auth/PasswordService.cpp @@ -27,7 +27,6 @@ #include "database/Session.hpp" #include "utils/Exception.hpp" -#include "utils/Utils.hpp" #include "utils/Logger.hpp" namespace Auth { diff --git a/src/av/AvInfo.cpp b/src/av/AvInfo.cpp index e39dcca9..2f7d9ee8 100644 --- a/src/av/AvInfo.cpp +++ b/src/av/AvInfo.cpp @@ -24,7 +24,7 @@ #include #include "utils/Logger.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" namespace Av { @@ -230,19 +230,20 @@ MediaFile::getAttachedPictures(std::size_t nbMaxPictures) const return pictures; } -std::optional guessMediaFileFormat(const std::filesystem::path& file) +std::optional +guessMediaFileFormat(const std::filesystem::path& file) { AVOutputFormat* format {av_guess_format(NULL,file.string().c_str(),NULL)}; if (!format || !format->name) return {}; - auto formats {splitString(format->name, ",")}; + auto formats {StringUtils::splitString(format->name, ",")}; if (formats.size() > 1) LMS_LOG(AV, INFO) << "File '" << file.string() << "' reported several formats: '" << format->name << "'"; std::vector mimeTypes; if (format->mime_type) - mimeTypes = splitString(format->mime_type, ","); + mimeTypes = StringUtils::splitString(format->mime_type, ","); if (mimeTypes.empty()) LMS_LOG(AV, INFO) << "File '" << file.string() << "', no mime type found!"; diff --git a/src/database/Artist.hpp b/src/database/Artist.hpp index 078932c5..01d261b3 100644 --- a/src/database/Artist.hpp +++ b/src/database/Artist.hpp @@ -71,7 +71,7 @@ class Artist : public Wt::Dbo::Dbo // Accessors const std::string& getName(void) const { return _name; } - std::optional getMBID(void) const { return readAs(_MBID); } + std::optional getMBID(void) const { return UUID::fromString(_MBID); } std::vector> getReleases(const std::set& clusterIds = {}) const; // if non empty, get the releases that match all these clusters std::size_t getReleaseCount() const; diff --git a/src/database/Release.hpp b/src/database/Release.hpp index fdaa3ae5..c0a638f3 100644 --- a/src/database/Release.hpp +++ b/src/database/Release.hpp @@ -89,7 +89,7 @@ class Release : public Wt::Dbo::Dbo // Accessors std::string getName() const { return _name; } - std::optional getMBID() const { return readAs(_MBID); } + std::optional getMBID() const { return UUID::fromString(_MBID); } std::optional getTotalTrackNumber() const; std::optional getTotalDiscNumber() const; std::chrono::milliseconds getDuration() const; diff --git a/src/database/ScanSettings.cpp b/src/database/ScanSettings.cpp index 805cf434..1c024353 100644 --- a/src/database/ScanSettings.cpp +++ b/src/database/ScanSettings.cpp @@ -22,7 +22,7 @@ #include #include "utils/Logger.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" #include "Cluster.hpp" #include "Session.hpp" @@ -65,7 +65,7 @@ ScanSettings::get(Session& session) std::set ScanSettings::getAudioFileExtensions() const { - auto extensions = splitString(_audioFileExtensions, " "); + auto extensions = StringUtils::splitString(_audioFileExtensions, " "); return std::set(std::cbegin(extensions), std::cend(extensions)); } @@ -84,7 +84,7 @@ ScanSettings::getClusterTypes() const void ScanSettings::setMediaDirectory(const std::filesystem::path& p) { - _mediaDirectory = stringTrimEnd(p.string(), "/\\"); + _mediaDirectory = StringUtils::stringTrimEnd(p.string(), "/\\"); } template diff --git a/src/database/Track.hpp b/src/database/Track.hpp index 880a6057..d3bcd824 100644 --- a/src/database/Track.hpp +++ b/src/database/Track.hpp @@ -113,7 +113,7 @@ class Track : public Wt::Dbo::Dbo Wt::WDateTime getLastWriteTime() const { return _fileLastWrite; } Wt::WDateTime getAddedTime() const { return _fileAdded; } bool hasCover() const { return _hasCover; } - std::optional getMBID() const { return readAs(_MBID); } + std::optional getMBID() const { return UUID::fromString(_MBID); } std::optional getCopyright() const; std::optional getCopyrightURL() const; std::vector> getArtists(TrackArtistLink::Type type = TrackArtistLink::Type::Artist) const; diff --git a/src/metadata/AvFormat.cpp b/src/metadata/AvFormat.cpp index 1e53d6c8..38790589 100644 --- a/src/metadata/AvFormat.cpp +++ b/src/metadata/AvFormat.cpp @@ -19,10 +19,14 @@ #include "AvFormat.hpp" +#include +#include + #include "av/AvInfo.hpp" #include "utils/Logger.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" + namespace MetaData { @@ -37,7 +41,7 @@ findFirstValueOfAs(const MetadataMap& metadataMap, std::initializer_list(stringTrim(it->second)); + return StringUtils::readAs(StringUtils::stringTrim(it->second)); } template <> @@ -48,12 +52,12 @@ findFirstValueOfAs(const MetadataMap& metadataMap, std::initializer_list strUuids = splitString(*str, "/"); + std::vector strUuids = StringUtils::splitString(*str, "/"); std::vector res; for (const std::string strUuid : strUuids) { - std::optional uuid {readAs(strUuid)}; + std::optional uuid {UUID::fromString(strUuid)}; if (!uuid) return std::nullopt; @@ -103,7 +107,7 @@ getArtists(const MetadataMap& metadataMap) std::vector artistNames; if (metadataMap.find("ARTISTS") != metadataMap.end()) { - artistNames = splitString(metadataMap.find("ARTISTS")->second, "/;"); + artistNames = StringUtils::splitString(metadataMap.find("ARTISTS")->second, "/;"); } else if (metadataMap.find("ARTIST") != metadataMap.end()) { @@ -163,54 +167,54 @@ AvFormat::parse(const std::filesystem::path& p, bool debug) else if (tag == "TRACK") { // Expecting 'Number/Total' - std::vector strings {splitString(value, "/") }; + std::vector strings {StringUtils::splitString(value, "/") }; if (strings.size() > 0) { - track.trackNumber = readAs(strings[0]); + track.trackNumber = StringUtils::readAs(strings[0]); if (strings.size() > 1) - track.totalTrack = readAs(strings[1]); + track.totalTrack = StringUtils::readAs(strings[1]); } } else if (tag == "DISC") { // Expecting 'Number/Total' - std::vector strings {splitString(value, "/")}; + std::vector strings {StringUtils::splitString(value, "/")}; if (strings.size() > 0) { - track.discNumber = readAs(strings[0]); + track.discNumber = StringUtils::readAs(strings[0]); if (strings.size() > 1) - track.totalDisc = readAs(strings[1]); + track.totalDisc = StringUtils::readAs(strings[1]); } } else if (tag == "DATE" || tag == "YEAR" || tag == "WM/Year") { - track.year = readAs(value); + track.year = StringUtils::readAs(value); } else if (tag == "TDOR" // Original release time (ID3v2 2.4) || tag == "TORY") // Original release year { - track.originalYear = readAs(value); + track.originalYear = StringUtils::readAs(value); } else if (tag == "ACOUSTID ID") { - track.acoustID = readAs(value); + track.acoustID = UUID::fromString(value); } else if (tag == "MUSICBRAINZ RELEASE TRACK ID" || tag == "MUSICBRAINZ_RELEASETRACKID" || tag == "MUSICBRAINZ_TRACKID" || tag == "MUSICBRAINZ/TRACK ID") { - track.musicBrainzTrackID = readAs(value); + track.musicBrainzTrackID = UUID::fromString(value); } else if (_clusterTypeNames.find(tag) != _clusterTypeNames.end()) { - std::vector clusterNames {splitString(value, "/,;")}; + std::vector clusterNames {StringUtils::splitString(value, "/,;")}; if (!clusterNames.empty()) track.clusters[tag] = std::set{clusterNames.begin(), clusterNames.end()}; diff --git a/src/metadata/MetaData.hpp b/src/metadata/MetaData.hpp index 011a8729..b4f652ad 100644 --- a/src/metadata/MetaData.hpp +++ b/src/metadata/MetaData.hpp @@ -26,7 +26,7 @@ #include #include -#include "utils/Utils.hpp" +//#include "utils/Utils.hpp" #include "utils/UUID.hpp" namespace MetaData diff --git a/src/metadata/TagLibParser.cpp b/src/metadata/TagLibParser.cpp index add1ab55..5f430e14 100644 --- a/src/metadata/TagLibParser.cpp +++ b/src/metadata/TagLibParser.cpp @@ -28,7 +28,8 @@ #include #include "utils/Logger.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" + namespace MetaData { @@ -49,7 +50,7 @@ getPropertyValuesFirstMatchAs(const TagLib::PropertyMap& properties, const std:: for (const auto& value : values) { - auto val {readAs(stringTrim(value.to8Bit(true)))}; + auto val {StringUtils::readAs(StringUtils::stringTrim(value.to8Bit(true)))}; if (!val) continue; @@ -75,9 +76,9 @@ splitAndTrimString(const std::string& str, const std::string& delimiters) { std::vector res; - std::vector strings {splitString(str, delimiters)}; + std::vector strings {StringUtils::splitString(str, delimiters)}; for (const std::string& s : strings) - res.emplace_back(stringTrim(s)); + res.emplace_back(StringUtils::stringTrim(s)); return res; } @@ -224,29 +225,29 @@ TagLibParser::parse(const std::filesystem::path& p, bool debug) std::vector strs; std::transform(values.begin(), values.end(), std::back_inserter(strs), [](const auto& value) { return value.to8Bit(true); }); - std::cout << "[" << tag << "] = " << joinStrings(strs, "*SEP*") << std::endl; + std::cout << "[" << tag << "] = " << StringUtils::joinStrings(strs, "*SEP*") << std::endl; } if (tag.empty() || values.isEmpty() || values.front().isEmpty()) continue; - std::string value {stringTrim(values.front().to8Bit(true))}; + std::string value {StringUtils::stringTrim(values.front().to8Bit(true))}; if (tag == "TITLE") track.title = value; else if (tag == "MUSICBRAINZ_RELEASETRACKID" || tag == "MUSICBRAINZ RELEASE TRACK ID") { - track.musicBrainzTrackID = readAs(value); + track.musicBrainzTrackID = UUID::fromString(value); } else if (tag == "MUSICBRAINZ_TRACKID" || tag == "MUSICBRAINZ TRACK ID") - track.musicBrainzRecordID = readAs(value); + track.musicBrainzRecordID = UUID::fromString(value); else if (tag == "ACOUSTID_ID") - track.acoustID = readAs(value); + track.acoustID = UUID::fromString(value); else if (tag == "TRACKTOTAL") { - auto totalTrack = readAs(value); + auto totalTrack = StringUtils::readAs(value); if (totalTrack) track.totalTrack = totalTrack; } @@ -257,44 +258,44 @@ TagLibParser::parse(const std::filesystem::path& p, bool debug) if (!strings.empty()) { - track.trackNumber = readAs(strings[0]); + track.trackNumber = StringUtils::readAs(strings[0]); // Lower priority than TRACKTOTAL if (strings.size() > 1 && !track.totalTrack) - track.totalTrack = readAs(strings[1]); + track.totalTrack = StringUtils::readAs(strings[1]); } } else if (tag == "DISCTOTAL") { - auto totalDisc = readAs(value); + auto totalDisc = StringUtils::readAs(value); if (totalDisc) track.totalDisc = totalDisc; } else if (tag == "DISCNUMBER") { // Expecting 'Number/Total' - std::vector strings {splitString(value, "/")}; + std::vector strings {StringUtils::splitString(value, "/")}; if (!strings.empty()) { - track.discNumber = readAs(strings[0]); + track.discNumber = StringUtils::readAs(strings[0]); // Lower priority than DISCTOTAL if (strings.size() > 1 && !track.totalDisc) - track.totalDisc = readAs(strings[1]); + track.totalDisc = StringUtils::readAs(strings[1]); } } else if (tag == "DATE") - track.year = readAs(value); + track.year = StringUtils::readAs(value); else if (tag == "ORIGINALDATE" && !track.originalYear) { // Lower priority than ORIGINALYEAR - track.originalYear = readAs(value); + track.originalYear = StringUtils::readAs(value); } else if (tag == "ORIGINALYEAR") { // Higher priority than ORIGINALDATE - auto originalYear = readAs(value); + auto originalYear = StringUtils::readAs(value); if (originalYear) track.originalYear = originalYear; } diff --git a/src/scanner/MediaScanner.cpp b/src/scanner/MediaScanner.cpp index f928331f..fb835855 100644 --- a/src/scanner/MediaScanner.cpp +++ b/src/scanner/MediaScanner.cpp @@ -32,7 +32,6 @@ #include "utils/Exception.hpp" #include "utils/Logger.hpp" #include "utils/Path.hpp" -#include "utils/Utils.hpp" using namespace Database; diff --git a/src/similarity/cluster/SimilarityClusterSearcher.cpp b/src/similarity/cluster/SimilarityClusterSearcher.cpp index c4a7e1aa..037dd3c4 100644 --- a/src/similarity/cluster/SimilarityClusterSearcher.cpp +++ b/src/similarity/cluster/SimilarityClusterSearcher.cpp @@ -28,7 +28,6 @@ #include "database/Session.hpp" #include "database/Track.hpp" #include "database/TrackList.hpp" -#include "utils/Utils.hpp" namespace Similarity { namespace ClusterSearcher { diff --git a/src/similarity/features/SimilarityFeaturesCache.cpp b/src/similarity/features/SimilarityFeaturesCache.cpp index 8c5589ab..1f81c010 100644 --- a/src/similarity/features/SimilarityFeaturesCache.cpp +++ b/src/similarity/features/SimilarityFeaturesCache.cpp @@ -25,7 +25,6 @@ #include "utils/Config.hpp" #include "utils/Logger.hpp" #include "utils/Service.hpp" -#include "utils/Utils.hpp" namespace Similarity { diff --git a/src/similarity/features/SimilarityFeaturesSearcher.cpp b/src/similarity/features/SimilarityFeaturesSearcher.cpp index 60414b31..a1ab5987 100644 --- a/src/similarity/features/SimilarityFeaturesSearcher.cpp +++ b/src/similarity/features/SimilarityFeaturesSearcher.cpp @@ -29,7 +29,6 @@ #include "database/TrackFeatures.hpp" #include "som/DataNormalizer.hpp" #include "utils/Logger.hpp" -#include "utils/Utils.hpp" namespace Similarity { diff --git a/src/ui/LmsApplication.cpp b/src/ui/LmsApplication.cpp index e3585d8d..ebc16ae0 100644 --- a/src/ui/LmsApplication.cpp +++ b/src/ui/LmsApplication.cpp @@ -39,7 +39,7 @@ #include "explore/Explore.hpp" #include "utils/Logger.hpp" #include "utils/Service.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" #include "admin/InitWizardView.hpp" #include "admin/DatabaseSettingsView.hpp" @@ -639,7 +639,7 @@ LmsApplication::notifyMsg(MsgType type, const Wt::WString& message, std::chrono: std::ostringstream oss; oss << "$.notify({" - "message: '" << jsEscape(message.toUTF8()) << "'" + "message: '" << StringUtils::jsEscape(message.toUTF8()) << "'" "},{" "type: '" << msgTypeToString(type) << "'," "placement: {from: 'top', align: 'center'}," diff --git a/src/ui/MediaPlayer.cpp b/src/ui/MediaPlayer.cpp index f2302a9f..8b376ad1 100644 --- a/src/ui/MediaPlayer.cpp +++ b/src/ui/MediaPlayer.cpp @@ -29,7 +29,7 @@ #include "resource/ImageResource.hpp" #include "resource/AudioResource.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" #include "LmsApplication.hpp" @@ -73,9 +73,9 @@ MediaPlayer::loadTrack(Database::IdType trackId, bool play) << "var params = {" << " resource: \"" << resource << "\"," << " duration: " << std::chrono::duration_cast(track->getDuration()).count() << "," - << " title: \"" << jsEscape(track->getName()) << "\"," - << " artist: \"" << (!artists.empty() ? jsEscape(artists.front()->getName()) : "") << "\"," - << " release: \"" << (track->getRelease() ? jsEscape(track->getRelease()->getName()) : "") << "\"," + << " title: \"" << StringUtils::jsEscape(track->getName()) << "\"," + << " artist: \"" << (!artists.empty() ? StringUtils::jsEscape(artists.front()->getName()) : "") << "\"," + << " release: \"" << (track->getRelease() ? StringUtils::jsEscape(track->getRelease()->getName()) : "") << "\"," << " artwork: [" << " { src: \"" << LmsApp->getImageResource()->getTrackUrl(trackId, 96) << "\", sizes: \"96x96\", type: \"" << imgResourceMimeType << "\" }," << " { src: \"" << LmsApp->getImageResource()->getTrackUrl(trackId, 256) << "\", sizes: \"256x256\", type: \"" << imgResourceMimeType << "\" }," diff --git a/src/ui/PlayQueueView.cpp b/src/ui/PlayQueueView.cpp index 34b4305b..91dc4c1b 100644 --- a/src/ui/PlayQueueView.cpp +++ b/src/ui/PlayQueueView.cpp @@ -28,8 +28,10 @@ #include "database/User.hpp" #include "similarity/SimilaritySearcher.hpp" #include "utils/Logger.hpp" +#include "utils/Random.hpp" #include "utils/Service.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" + #include "TrackStringUtils.hpp" #include "LmsApplication.hpp" @@ -72,7 +74,7 @@ PlayQueue::PlayQueue() Database::TrackList::pointer trackList {getTrackList()}; auto entries {trackList->getEntries()}; - shuffleContainer(entries); + Random::shuffleContainer(entries); getTrackList().modify()->clear(); for (const auto& entry : entries) diff --git a/src/ui/admin/DatabaseSettingsView.cpp b/src/ui/admin/DatabaseSettingsView.cpp index d6e44833..d4ac7200 100644 --- a/src/ui/admin/DatabaseSettingsView.cpp +++ b/src/ui/admin/DatabaseSettingsView.cpp @@ -29,7 +29,7 @@ #include "database/Cluster.hpp" #include "utils/Logger.hpp" #include "utils/Service.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" #include "common/Validators.hpp" #include "common/ValueStringModel.hpp" @@ -104,7 +104,7 @@ class DatabaseSettingsModel : public Wt::WFormModel { std::vector names; std::transform(clusterTypes.begin(), clusterTypes.end(), std::back_inserter(names), [](auto clusterType) { return clusterType->getName(); }); - setValue(TagsField, joinStrings(names, " ")); + setValue(TagsField, StringUtils::joinStrings(names, " ")); } } @@ -128,7 +128,7 @@ class DatabaseSettingsModel : public Wt::WFormModel if (similarityEngineTypeRow) scanSettings.modify()->setSimilarityEngineType(_similarityEngineTypeModel->getValue(*similarityEngineTypeRow)); - auto clusterTypes {splitString(valueText(TagsField).toUTF8(), " ")}; + auto clusterTypes {StringUtils::splitString(valueText(TagsField).toUTF8(), " ")}; scanSettings.modify()->setClusterTypes(LmsApp->getDbSession(), std::set(clusterTypes.begin(), clusterTypes.end())); } diff --git a/src/ui/admin/UserView.cpp b/src/ui/admin/UserView.cpp index dd438f88..dc1dd83c 100644 --- a/src/ui/admin/UserView.cpp +++ b/src/ui/admin/UserView.cpp @@ -34,7 +34,7 @@ #include "utils/Exception.hpp" #include "utils/Logger.hpp" #include "utils/Service.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" #include "common/Validators.hpp" #include "common/ValueStringModel.hpp" @@ -229,7 +229,7 @@ UserView::refreshView() if (!wApp->internalPathMatches("/admin/user")) return; - auto userId = readAs(wApp->internalPathNextPart("/admin/user/")); + auto userId = StringUtils::readAs(wApp->internalPathNextPart("/admin/user/")); clear(); diff --git a/src/ui/explore/ArtistInfoView.cpp b/src/ui/explore/ArtistInfoView.cpp index 5b260cc2..8f806eba 100644 --- a/src/ui/explore/ArtistInfoView.cpp +++ b/src/ui/explore/ArtistInfoView.cpp @@ -22,7 +22,7 @@ #include "database/Artist.hpp" #include "similarity/SimilaritySearcher.hpp" #include "utils/Service.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" #include "ArtistLink.hpp" #include "LmsApplication.hpp" @@ -59,7 +59,7 @@ ArtistInfo::refresh() if (!wApp->internalPathMatches("/artist/")) return; - auto artistId = readAs(wApp->internalPathNextPart("/artist/")); + auto artistId = StringUtils::readAs(wApp->internalPathNextPart("/artist/")); if (!artistId) return; diff --git a/src/ui/explore/ArtistView.cpp b/src/ui/explore/ArtistView.cpp index 35837d72..7b40bd85 100644 --- a/src/ui/explore/ArtistView.cpp +++ b/src/ui/explore/ArtistView.cpp @@ -28,7 +28,7 @@ #include "database/Release.hpp" #include "utils/Logger.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" #include "resource/ImageResource.hpp" @@ -63,7 +63,7 @@ Artist::refresh() clear(); - auto artistId = readAs(wApp->internalPathNextPart("/artist/")); + const auto artistId {StringUtils::readAs(wApp->internalPathNextPart("/artist/"))}; if (!artistId) return; diff --git a/src/ui/explore/ArtistsInfoView.cpp b/src/ui/explore/ArtistsInfoView.cpp index ec1bebbd..18e8d118 100644 --- a/src/ui/explore/ArtistsInfoView.cpp +++ b/src/ui/explore/ArtistsInfoView.cpp @@ -24,7 +24,6 @@ #include "database/Artist.hpp" #include "database/TrackList.hpp" #include "database/User.hpp" -#include "utils/Utils.hpp" #include "ArtistLink.hpp" #include "LmsApplication.hpp" diff --git a/src/ui/explore/ArtistsView.cpp b/src/ui/explore/ArtistsView.cpp index 8fbceefb..2798a3a6 100644 --- a/src/ui/explore/ArtistsView.cpp +++ b/src/ui/explore/ArtistsView.cpp @@ -29,7 +29,7 @@ #include "common/ValueStringModel.hpp" #include "database/Artist.hpp" #include "utils/Logger.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" #include "LmsApplication.hpp" #include "Filters.hpp" @@ -83,7 +83,7 @@ Artists::refresh() void Artists::addSome() { - auto searchKeywords = splitString(_search->text().toUTF8(), " "); + const auto searchKeywords {StringUtils::splitString(_search->text().toUTF8(), " ")}; auto clusterIds = _filters->getClusterIds(); auto linkModel = static_cast(_linkType->model().get()); diff --git a/src/ui/explore/ReleaseInfoView.cpp b/src/ui/explore/ReleaseInfoView.cpp index 16d14969..7293a678 100644 --- a/src/ui/explore/ReleaseInfoView.cpp +++ b/src/ui/explore/ReleaseInfoView.cpp @@ -24,7 +24,7 @@ #include "database/Release.hpp" #include "similarity/SimilaritySearcher.hpp" #include "utils/Service.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" #include "ReleaseLink.hpp" #include "LmsApplication.hpp" @@ -64,7 +64,7 @@ ReleaseInfo::refresh() if (!wApp->internalPathMatches("/release/")) return; - auto releaseId {readAs(wApp->internalPathNextPart("/release/"))}; + auto releaseId {StringUtils::readAs(wApp->internalPathNextPart("/release/"))}; if (!releaseId) return; diff --git a/src/ui/explore/ReleaseLink.cpp b/src/ui/explore/ReleaseLink.cpp index 4930698b..83a40325 100644 --- a/src/ui/explore/ReleaseLink.cpp +++ b/src/ui/explore/ReleaseLink.cpp @@ -25,7 +25,6 @@ #include "database/Release.hpp" #include "resource/ImageResource.hpp" -#include "utils/Utils.hpp" #include "LmsApplication.hpp" diff --git a/src/ui/explore/ReleaseView.cpp b/src/ui/explore/ReleaseView.cpp index d98f4a45..8cb45f8d 100644 --- a/src/ui/explore/ReleaseView.cpp +++ b/src/ui/explore/ReleaseView.cpp @@ -29,7 +29,7 @@ #include "database/Track.hpp" #include "utils/Logger.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" #include "resource/ImageResource.hpp" @@ -65,7 +65,7 @@ Release::refresh() return; clear(); - auto releaseId {readAs(wApp->internalPathNextPart("/release/"))}; + auto releaseId {StringUtils::readAs(wApp->internalPathNextPart("/release/"))}; if (!releaseId) return; diff --git a/src/ui/explore/ReleasesView.cpp b/src/ui/explore/ReleasesView.cpp index 48a653dc..1d6f868a 100644 --- a/src/ui/explore/ReleasesView.cpp +++ b/src/ui/explore/ReleasesView.cpp @@ -27,7 +27,7 @@ #include "database/Release.hpp" #include "utils/Logger.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" #include "resource/ImageResource.hpp" @@ -137,7 +137,7 @@ Releases::addSome() std::vector Releases::getReleases(std::optional offset, std::optional limit, bool& moreResults) const { - const auto searchKeywords {splitString(_search->text().toUTF8(), " ")}; + const auto searchKeywords {StringUtils::splitString(_search->text().toUTF8(), " ")}; auto transaction {LmsApp->getDbSession().createSharedTransaction()}; diff --git a/src/ui/explore/TracksInfoView.cpp b/src/ui/explore/TracksInfoView.cpp index 4c4cd471..58469612 100644 --- a/src/ui/explore/TracksInfoView.cpp +++ b/src/ui/explore/TracksInfoView.cpp @@ -26,8 +26,6 @@ #include "database/TrackList.hpp" #include "database/User.hpp" -#include "utils/Utils.hpp" - #include "LmsApplication.hpp" using namespace Database; diff --git a/src/ui/explore/TracksView.cpp b/src/ui/explore/TracksView.cpp index 36eb1d22..2b1827e2 100644 --- a/src/ui/explore/TracksView.cpp +++ b/src/ui/explore/TracksView.cpp @@ -28,7 +28,7 @@ #include "database/Track.hpp" #include "utils/Logger.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" #include "resource/ImageResource.hpp" @@ -78,7 +78,7 @@ _filters {filters} std::vector Tracks::getTracks(std::optional offset, std::optional size, bool& moreResults) { - const auto searchKeywords {splitString(_search->text().toUTF8(), " ")}; + const auto searchKeywords {StringUtils::splitString(_search->text().toUTF8(), " ")}; const auto clusterIds {_filters->getClusterIds()}; auto transaction {LmsApp->getDbSession().createSharedTransaction()}; diff --git a/src/ui/resource/ImageResource.cpp b/src/ui/resource/ImageResource.cpp index 5ae08324..f0bade0c 100644 --- a/src/ui/resource/ImageResource.cpp +++ b/src/ui/resource/ImageResource.cpp @@ -27,7 +27,7 @@ #include "utils/Exception.hpp" #include "utils/Logger.hpp" #include "utils/Service.hpp" -#include "utils/Utils.hpp" +#include "utils/String.hpp" #include "LmsApplication.hpp" @@ -65,7 +65,7 @@ ImageResource::handleRequest(const Wt::Http::Request& request, Wt::Http::Respons if (!sizeStr) return; - const auto size {readAs(*sizeStr)}; + const auto size {StringUtils::readAs(*sizeStr)}; if (!size || *size > maxSize) return; @@ -73,7 +73,7 @@ ImageResource::handleRequest(const Wt::Http::Request& request, Wt::Http::Respons if (trackIdStr) { - const auto trackId {readAs(*trackIdStr)}; + const auto trackId {StringUtils::readAs(*trackIdStr)}; if (!trackId) return; @@ -85,7 +85,7 @@ ImageResource::handleRequest(const Wt::Http::Request& request, Wt::Http::Respons } else if (releaseIdStr) { - const auto releaseId {readAs(*releaseIdStr)}; + const auto releaseId {StringUtils::readAs(*releaseIdStr)}; if (!releaseId) return; diff --git a/src/metadata/MetaData.cpp b/src/utils/Random.cpp similarity index 73% rename from src/metadata/MetaData.cpp rename to src/utils/Random.cpp index ec188d3f..c7114ddf 100644 --- a/src/metadata/MetaData.cpp +++ b/src/utils/Random.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Emeric Poupon + * Copyright (C) 2020 Emeric Poupon * * This file is part of LMS. * @@ -17,14 +17,17 @@ * along with LMS. If not, see . */ -#include "MetaData.hpp" +#include "Random.hpp" -#include "utils/Utils.hpp" +namespace Random { -namespace MetaData +RandGenerator& getRandGenerator() { + static thread_local std::random_device rd; + static thread_local std::mt19937 randGenerator(rd()); + return randGenerator; +} - -} // namespace MetaData +} // Random diff --git a/src/utils/Random.hpp b/src/utils/Random.hpp new file mode 100644 index 00000000..6c7ede58 --- /dev/null +++ b/src/utils/Random.hpp @@ -0,0 +1,64 @@ +/* + * 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 . + */ + +#pragma once + +#include +#include + +namespace Random { + +using RandGenerator = std::mt19937; +RandGenerator& getRandGenerator(); + +template +T +getRandom(T min, T max) +{ + std::uniform_int_distribution<> dist {min, max}; + return dist (getRandGenerator()); +} + +template +T +getRealRandom(T min, T max) +{ + std::uniform_real_distribution<> dist {min, max}; + return dist (getRandGenerator()); +} + +template +void +shuffleContainer(Container& container) +{ + std::shuffle(std::begin(container), std::end(container), getRandGenerator()); +} + +template +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(container.size() - 1))); +} + +} + diff --git a/src/utils/Utils.cpp b/src/utils/String.cpp similarity index 93% rename from src/utils/Utils.cpp rename to src/utils/String.cpp index 3a98ba67..299c177e 100644 --- a/src/utils/Utils.cpp +++ b/src/utils/String.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Emeric Poupon + * Copyright (C) 2020 Emeric Poupon * * This file is part of LMS. * @@ -17,18 +17,16 @@ * along with LMS. If not, see . */ -#include "Utils.hpp" +#include "String.hpp" -#include -#include -#include #include -#include #include #include #include +namespace StringUtils { + bool readList(const std::string& str, const std::string& separators, std::list& results) { @@ -200,11 +198,5 @@ stringFromHex(const std::string& str) return res; } -RandGenerator& getRandGenerator() -{ - static thread_local std::random_device rd; - static thread_local std::mt19937 randGenerator(rd()); - - return randGenerator; -} +} // StringUtils diff --git a/src/utils/String.hpp b/src/utils/String.hpp new file mode 100644 index 00000000..44f67faa --- /dev/null +++ b/src/utils/String.hpp @@ -0,0 +1,73 @@ +/* + * 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 . + */ + +#pragma once + +#include +#include +#include +#include + +namespace StringUtils { + +std::vector +splitString(const std::string& string, const std::string& separators); + +std::string +joinStrings(const std::vector& strings, const std::string& delimiter); + +std::string +stringTrim(const std::string& str, const std::string& whitespaces = " \t"); + +std::string +stringTrimEnd(const std::string& str, const std::string& whitespaces = " \t"); + +std::string +stringToLower(const std::string& str); + +std::string +bufferToString(const std::vector& data); + +template +std::optional readAs(const std::string& str) +{ + T res; + + std::istringstream iss ( str ); + iss >> res; + if (iss.fail()) + return std::nullopt; + + return res; +} + +std::string +replaceInString(const std::string& str, const std::string& from, const std::string& to); + +std::string +jsEscape(const std::string& str); + +bool +stringEndsWith(const std::string& str, const std::string& ending); + +std::optional +stringFromHex(const std::string& str); + +} // StringUtils + diff --git a/src/utils/UUID.cpp b/src/utils/UUID.cpp index 82e3213d..9edbdad4 100644 --- a/src/utils/UUID.cpp +++ b/src/utils/UUID.cpp @@ -21,21 +21,28 @@ #include -#include "Utils.hpp" +namespace StringUtils +{ + template <> + std::optional + readAs(const std::string& str) + { + return UUID::fromString(str); + } +} static bool -stringIsUUID(const std::string& str) +stringIsUUID(std::string_view str) { static const std::regex re { R"([0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12})"}; - return std::regex_match(str, re); + return std::regex_match(std::cbegin(str), std::cend(str), re); } -template<> std::optional -readAs(const std::string& str) +UUID::fromString(std::string_view str) { if (!stringIsUUID(str)) return std::nullopt; diff --git a/src/utils/UUID.hpp b/src/utils/UUID.hpp index 45a2ba4f..daf561d0 100644 --- a/src/utils/UUID.hpp +++ b/src/utils/UUID.hpp @@ -19,27 +19,29 @@ #pragma once +#include #include #include -#include "Utils.hpp" +#include "utils/String.hpp" class UUID { public: + static std::optional fromString(std::string_view str); + std::string_view getAsString() const { return _value; } private: - - template - friend std::optional readAs(const std::string& str); - UUID(std::string_view value) : _value {value} {} std::string _value; }; -template<> -std::optional -readAs(const std::string& str); +namespace StringUtils +{ + template <> + std::optional + readAs(const std::string& str); +} diff --git a/src/utils/Utils.hpp b/src/utils/Utils.hpp index 562dbad7..60cd80fc 100644 --- a/src/utils/Utils.hpp +++ b/src/utils/Utils.hpp @@ -19,92 +19,7 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -bool -readList(const std::string& str, const std::string& separators, std::list& results); - -std::vector -splitString(const std::string& string, const std::string& separators); - -std::string -joinStrings(const std::vector& strings, const std::string& delimiter); - -std::string -stringTrim(const std::string& str, const std::string& whitespaces = " \t"); - -std::string -stringTrimEnd(const std::string& str, const std::string& whitespaces = " \t"); - -std::string -stringToLower(const std::string& str); - -std::string -bufferToString(const std::vector& data); - -template -std::optional readAs(const std::string& str) -{ - T res; - - std::istringstream iss ( str ); - iss >> res; - if (iss.fail()) - return std::nullopt; - - return res; -} - -std::string -replaceInString(const std::string& str, const std::string& from, const std::string& to); - -std::string -jsEscape(const std::string& str); - -bool -stringEndsWith(const std::string& str, const std::string& ending); - -std::optional -stringFromHex(const std::string& str); - -// warning: not efficient -template::value_type> -void uniqueAndSortedByOccurence(In first, In last, Out out) -{ - std::map occurencesMap; - - for (In it = first; it != last; ++it) - { - if (occurencesMap.find(*it) == occurencesMap.end()) - occurencesMap[*it] = 0; - - occurencesMap[*it]++; - } - - struct Item - { - U elem; - std::size_t count; - }; - - std::vector occurencesVector; - for (const auto& occurence : occurencesMap) - occurencesVector.emplace_back(Item{occurence.first, occurence.second}); - - std::sort(occurencesVector.begin(), occurencesVector.end(), [](const auto& a, const auto& b) { return a.count > b.count;}); - - for (const auto& occurence : occurencesVector) - *out++ = occurence.elem; -} +#include template> constexpr T clamp(T v, T lo, T hi, Compare comp = {}) @@ -113,40 +28,3 @@ constexpr T clamp(T v, T lo, T hi, Compare comp = {}) return comp(v, lo) ? lo : comp(hi, v) ? hi : v; } -using RandGenerator = std::mt19937; -RandGenerator& getRandGenerator(); - -template -T -getRandom(T min, T max) -{ - std::uniform_int_distribution<> dist {min, max}; - return dist (getRandGenerator()); -} - -template -T -getRealRandom(T min, T max) -{ - std::uniform_real_distribution<> dist {min, max}; - return dist (getRandGenerator()); -} - -template -void -shuffleContainer(Container& container) -{ - std::shuffle(std::begin(container), std::end(container), getRandGenerator()); -} - -template -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(container.size() - 1))); -} - - diff --git a/test/Makefile.am b/test/Makefile.am index 12ea5022..06d88e41 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -28,7 +28,7 @@ test_database_SOURCES = \ $(top_srcdir)/src/database/User.cpp \ $(top_srcdir)/src/utils/Logger.cpp \ $(top_srcdir)/src/utils/StreamLogger.cpp \ - $(top_srcdir)/src/utils/Utils.cpp + $(top_srcdir)/src/utils/String.cpp test_database_CXXFLAGS=-std=c++17 -I${top_srcdir}/src/ diff --git a/tools/metadata/Makefile.am b/tools/metadata/Makefile.am index 765c4941..e2a5fd10 100644 --- a/tools/metadata/Makefile.am +++ b/tools/metadata/Makefile.am @@ -3,12 +3,11 @@ bin_PROGRAMS = lms-metadata lms_metadata_SOURCES = \ $(srcdir)/LmsMetadata.cpp \ $(top_srcdir)/src/av/AvInfo.cpp \ - $(top_srcdir)/src/metadata/MetaData.cpp \ $(top_srcdir)/src/metadata/AvFormat.cpp \ $(top_srcdir)/src/metadata/TagLibParser.cpp \ $(top_srcdir)/src/utils/Logger.cpp \ $(top_srcdir)/src/utils/StreamLogger.cpp \ - $(top_srcdir)/src/utils/Utils.cpp \ + $(top_srcdir)/src/utils/String.cpp \ $(top_srcdir)/src/utils/UUID.cpp lms_metadata_CXXFLAGS=-std=c++17 -I$(top_srcdir)/src -D_REENTRANT diff --git a/tools/similarity-parameters/GeneticAlgorithm.hpp b/tools/similarity-parameters/GeneticAlgorithm.hpp index d4e0e402..3a5c7327 100644 --- a/tools/similarity-parameters/GeneticAlgorithm.hpp +++ b/tools/similarity-parameters/GeneticAlgorithm.hpp @@ -19,7 +19,8 @@ #include -#include "utils/Utils.hpp" +#include "utils/Random.hpp" + #include "ParallelFor.hpp" template @@ -108,7 +109,7 @@ GeneticAlgorithm::simulate(const std::vector& initialPop ScoredIndividual child {_params.breedFunction(itParent1->individual, itParent2->individual)}; - if (getRealRandom(float {}, float {1}) <= _params.mutationProbability) + if (Random::getRealRandom(float {}, float {1}) <= _params.mutationProbability) _params.mutateFunction(child.individual); children.emplace_back(std::move(child)); @@ -156,7 +157,7 @@ template typename std::vector::ScoredIndividual>::const_iterator GeneticAlgorithm::pickRandomRouletteWheel(const std::vector& population, Score totalScore) { - const Score randomScore {getRealRandom(Score {}, totalScore)}; + const Score randomScore {Random::getRealRandom(Score {}, totalScore)}; Score curScore{}; for (auto itScoredIndividual {std::cbegin(population)}; itScoredIndividual != std::cend(population); ++itScoredIndividual ) diff --git a/tools/similarity-parameters/LmsSimilarityParameters.cpp b/tools/similarity-parameters/LmsSimilarityParameters.cpp index ed5b1f66..6929ce31 100644 --- a/tools/similarity-parameters/LmsSimilarityParameters.cpp +++ b/tools/similarity-parameters/LmsSimilarityParameters.cpp @@ -358,7 +358,7 @@ breedFeatureSettingsMap(const FeatureSettingsMap& a, const FeatureSettingsMap& b // just kill random elements until size is good while (res.size() > a.size()) { - const auto itFeature {pickRandom(res)}; + const auto itFeature {Random::pickRandom(res)}; res.erase(itFeature); } @@ -371,11 +371,11 @@ mutateFeatureSettingsMap(FeatureSettingsMap& a) { const std::size_t size {a.size()}; // Replace one of the feature with another one, random - a.erase(pickRandom(a)); + a.erase(Random::pickRandom(a)); while (a.size() != size) { - const auto itFeatureSetting {pickRandom(featuresSettings)}; + const auto itFeatureSetting {Random::pickRandom(featuresSettings)}; a.emplace(itFeatureSetting->first, itFeatureSetting->second); } } @@ -425,7 +425,7 @@ int main(int argc, char *argv[]) while (settings.size() < nbFeatures) { - const auto itFeatureSetting {pickRandom(featuresSettings)}; + const auto itFeatureSetting {Random::pickRandom(featuresSettings)}; settings.emplace(itFeatureSetting->first, itFeatureSetting->second); } diff --git a/tools/similarity-parameters/Makefile.am b/tools/similarity-parameters/Makefile.am index 1d47f224..0f7cb8f8 100644 --- a/tools/similarity-parameters/Makefile.am +++ b/tools/similarity-parameters/Makefile.am @@ -21,8 +21,9 @@ lms_similarity_parameters_SOURCES = \ $(top_srcdir)/src/similarity/features/SimilarityFeaturesDefs.cpp \ $(top_srcdir)/src/utils/Config.cpp \ $(top_srcdir)/src/utils/Logger.cpp \ + $(top_srcdir)/src/utils/Random.cpp \ $(top_srcdir)/src/utils/StreamLogger.cpp \ - $(top_srcdir)/src/utils/Utils.cpp + $(top_srcdir)/src/utils/String.cpp lms_similarity_parameters_CXXFLAGS=-std=c++17 -I$(top_srcdir)/src -D_REENTRANT diff --git a/tools/similarity/Makefile.am b/tools/similarity/Makefile.am index 11657a5e..0473f464 100644 --- a/tools/similarity/Makefile.am +++ b/tools/similarity/Makefile.am @@ -21,7 +21,7 @@ lms_similarity_SOURCES = \ $(top_srcdir)/src/utils/Config.cpp \ $(top_srcdir)/src/utils/Logger.cpp \ $(top_srcdir)/src/utils/StreamLogger.cpp \ - $(top_srcdir)/src/utils/Utils.cpp + $(top_srcdir)/src/utils/String.cpp lms_similarity_CXXFLAGS=-std=c++17 -I$(top_srcdir)/src -D_REENTRANT