diff --git a/src/musikcore/library/query/CategoryListQuery.cpp b/src/musikcore/library/query/CategoryListQuery.cpp index 39c3d3e61..7ac35bed0 100755 --- a/src/musikcore/library/query/CategoryListQuery.cpp +++ b/src/musikcore/library/query/CategoryListQuery.cpp @@ -36,6 +36,7 @@ #include "CategoryListQuery.h" #include #include +#include #include #include #include @@ -43,6 +44,7 @@ using musik::core::db::Statement; using musik::core::db::Row; +using namespace musik::core::sdk; using namespace musik::core::db; using namespace musik::core::library::constants; using namespace musik::core::library::query; @@ -208,7 +210,7 @@ void CategoryListQuery::ProcessResult(musik::core::db::Statement &stmt) { SdkValueList unknowns; while (stmt.Step() == Row) { int64_t id = stmt.ColumnInt64(0); - std::string displayValue = musik::core::Trim(stmt.ColumnText(1)); + std::string displayValue = str::Trim(stmt.ColumnText(1)); /* we track empty / blank values separately, then sort them to the bottom of the returned list so they don't pollute the first results */ diff --git a/src/musikcore/library/query/CategoryTrackListQuery.cpp b/src/musikcore/library/query/CategoryTrackListQuery.cpp index 2aa4f790c..ee5e49f0f 100755 --- a/src/musikcore/library/query/CategoryTrackListQuery.cpp +++ b/src/musikcore/library/query/CategoryTrackListQuery.cpp @@ -40,12 +40,7 @@ #include #include #include - -#pragma warning(push, 0) -#include -#include -#include -#pragma warning(pop) +#include using musik::core::db::Statement; using musik::core::db::Row; @@ -57,7 +52,6 @@ using namespace musik::core::db; using namespace musik::core::library::query; using namespace musik::core::library::query::serialization; using namespace musik::core::library::constants; -using namespace boost::algorithm; const std::string CategoryTrackListQuery::kQueryName = "CategoryTrackListQuery"; @@ -154,7 +148,7 @@ void CategoryTrackListQuery::RegularQuery(musik::core::db::Connection &db) { std::string limitAndOffset = this->GetLimitAndOffset(); if (this->filter.size()) { - trackFilterValue = "%" + trim_copy(to_lower_copy(filter)) + "%"; + trackFilterValue = "%" + sdk::str::Trim(sdk::str::ToLowerCopy(filter)) + "%"; trackFilterClause = category::CATEGORY_TRACKLIST_FILTER; args.push_back(category::StringArgument(trackFilterValue)); args.push_back(category::StringArgument(trackFilterValue)); diff --git a/src/musikcore/library/query/SearchTrackListQuery.cpp b/src/musikcore/library/query/SearchTrackListQuery.cpp index 8adb13511..b4729c14a 100755 --- a/src/musikcore/library/query/SearchTrackListQuery.cpp +++ b/src/musikcore/library/query/SearchTrackListQuery.cpp @@ -39,13 +39,12 @@ #include #include #include +#include #include +#include #pragma warning(push, 0) #include - -#include -#include #pragma warning(pop) using musik::core::db::Statement; @@ -54,11 +53,12 @@ using musik::core::TrackPtr; using musik::core::LibraryTrack; using musik::core::ILibraryPtr; +using namespace musik::core; +using namespace musik::core::sdk; using namespace musik::core::db; using namespace musik::core::library::constants; using namespace musik::core::library::query; using namespace musik::core::library::query::serialization; -using namespace boost::algorithm; const std::string SearchTrackListQuery::kQueryName = "SearchTrackListQuery"; @@ -129,7 +129,7 @@ bool SearchTrackListQuery::OnRun(Connection& db) { " AND tracks.album_id=al.id AND tracks.visual_genre_id=gn.id AND tracks.visual_artist_id=ar.id " "ORDER BY " + this->orderBy + " "; - ReplaceAll(query, "{{match_type}}", useRegex ? "REGEXP" : "LIKE"); + str::ReplaceAll(query, "{{match_type}}", useRegex ? "REGEXP" : "LIKE"); } else { query = @@ -148,7 +148,7 @@ bool SearchTrackListQuery::OnRun(Connection& db) { if (hasFilter) { std::string patternToMatch = useRegex - ? filter : "%" + trim_copy(to_lower_copy(filter)) + "%"; + ? filter : "%" + sdk::str::Trim(sdk::str::ToLowerCopy(filter)) + "%"; trackQuery.BindText(0, patternToMatch); trackQuery.BindText(1, patternToMatch); diff --git a/src/musikcore/library/query/TrackMetadataBatchQuery.cpp b/src/musikcore/library/query/TrackMetadataBatchQuery.cpp index b3eb36e23..bb5331f5e 100644 --- a/src/musikcore/library/query/TrackMetadataBatchQuery.cpp +++ b/src/musikcore/library/query/TrackMetadataBatchQuery.cpp @@ -38,6 +38,8 @@ #include #include #include +#include + #include #pragma warning(push, 0) @@ -45,6 +47,7 @@ #pragma warning(pop) using namespace musik::core; +using namespace musik::core::sdk; using namespace musik::core::db; using namespace musik::core::library; using namespace musik::core::library::query; @@ -70,7 +73,7 @@ bool TrackMetadataBatchQuery::OnRun(Connection& db) { } std::string query = tracks::kAllMetadataQueryByIdBatch; - ReplaceAll(query, "{{ids}}", idList); + str::ReplaceAll(query, "{{ids}}", idList.c_str()); Statement trackQuery(query.c_str(), db); diff --git a/src/musikcore/net/WebSocketClient.cpp b/src/musikcore/net/WebSocketClient.cpp index dbdc6542d..a5ce33b8c 100644 --- a/src/musikcore/net/WebSocketClient.cpp +++ b/src/musikcore/net/WebSocketClient.cpp @@ -35,7 +35,7 @@ #include "pch.hpp" #include -#include +#include #include #include #include @@ -46,6 +46,7 @@ #pragma warning(pop) using namespace musik::core; +using namespace musik::core::sdk; using namespace musik::core::net; using namespace musik::core::runtime; @@ -112,7 +113,7 @@ static inline bool extractRawQueryResult( } static inline bool isVersionCompatible(const std::string& str) { - auto parts = Split(str, "."); + auto parts = str::Split(str, "."); return parts.size() == 3 && parts[0] == std::to_string(VERSION_MAJOR) && diff --git a/src/musikcore/sdk/String.h b/src/musikcore/sdk/String.h index 899f54521..915f0751e 100644 --- a/src/musikcore/sdk/String.h +++ b/src/musikcore/sdk/String.h @@ -37,6 +37,8 @@ #include #include #include +#include +#include #ifdef WIN32 #include @@ -45,7 +47,7 @@ namespace musik { namespace core { namespace sdk { namespace str { #ifdef WIN32 - template + template static inline String u16to8(const wchar_t* utf16) { if (!utf16) return ""; int size = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, 0, 0, 0, 0); @@ -57,7 +59,7 @@ namespace musik { namespace core { namespace sdk { namespace str { return utf8str; } - template + template static inline Wstring u8to16(const char* utf8) { int size = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, 0, 0); if (size <= 0) return L""; @@ -70,7 +72,7 @@ namespace musik { namespace core { namespace sdk { namespace str { #endif template - static std::string format(const std::string& format, Args ... args) { + static std::string Format(const std::string& format, Args ... args) { /* https://stackoverflow.com/a/26221725 */ size_t size = std::snprintf(nullptr, 0, format.c_str(), args ...) + 1; /* extra space for '\0' */ std::unique_ptr buf(new char[size]); @@ -78,4 +80,89 @@ namespace musik { namespace core { namespace sdk { namespace str { return std::string(buf.get(), buf.get() + size - 1); /* omit the '\0' */ } + static inline bool IsSpace(const char c) { + return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\v' || c == '\f'; + } + + template + static String Trim(const String& str) { + if (str.size()) { + int start = 0; + for (size_t i = 0; i < str.length(); i++) { + if (!IsSpace(str[i])) { + break; + } + ++start; + } + int end = (int)str.length(); + for (size_t i = str.length() - 1; i >= 0; i--) { + if (!IsSpace(str[i])) { + break; + } + --end; + } + if (end > start) { + std::string result = str.substr((size_t)start, (size_t)end - start); + return result; + } + } + return str; + } + + template + static String Trim(const char* str) { + return Trim(String(str)); + } + + template> + static Result Split(const String& in, const String& delim) { + Result result; + size_t last = 0, next = 0; + while ((next = in.find(delim, last)) != std::string::npos) { + result.push_back(std::move(Trim(in.substr(last, next - last)))); + last = next + 1; + } + result.push_back(std::move(Trim(in.substr(last)))); + return result; + } + + template> + static Result Split(const String& in, const char* delim) { + return Split(in, String(delim)); + } + + template + static void ReplaceAll(String& input, const String& find, const String& replace) { + size_t pos = input.find(find); + while (pos != std::string::npos) { + input.replace(pos, find.size(), replace); + pos = input.find(find, pos + replace.size()); + } + } + + template + static void ReplaceAll(String& input, const char* find, const char* replace) { + ReplaceAll(input, String(find), String(replace)); + } + + template + static String ReplaceAllCopy(const String& input, const String& find, const String& replace) { + String copy = input; + ReplaceAll(copy, find, replace); + return copy; + } + + template + static String ReplaceAllCopy(const String& input, const char* find, const char* replace) { + return ReplaceAllCopy(input, String(find), String(replace)); + } + + template + static String ToLowerCopy(const String& input) { + String copy = input; + std::transform(copy.begin(), copy.end(), copy.begin(), + [](unsigned char c) { return std::tolower(c); }); + return copy; + } + } } } } diff --git a/src/musikcore/support/Common.cpp b/src/musikcore/support/Common.cpp index 44b34b9c7..05cffc709 100644 --- a/src/musikcore/support/Common.cpp +++ b/src/musikcore/support/Common.cpp @@ -291,55 +291,6 @@ namespace musik { namespace core { return path; } - void ReplaceAll(std::string& input, const std::string& find, const std::string& replace) { - size_t pos = input.find(find); - while (pos != std::string::npos) { - input.replace(pos, find.size(), replace); - pos = input.find(find, pos + replace.size()); - } - } - - static inline bool IsSpace(const char c) { - return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\v' || c == '\f'; - } - - std::string Trim(const std::string& str) { - if (str.size()) { - int start = 0; - for (size_t i = 0; i < str.length(); i++) { - if (!IsSpace(str[i])) { - break; - } - ++start; - } - int end = (int)str.length(); - for (size_t i = str.length() - 1; i >= 0; i--) { - if (!IsSpace(str[i])) { - break; - } - --end; - } - if (end > start) { - std::string result = str.substr((size_t)start, (size_t)end - start); - return result; - } - } - return str; - } - - std::vector Split( - const std::string& in, const std::string& delim) - { - std::vector result; - size_t last = 0, next = 0; - while ((next = in.find(delim, last)) != std::string::npos) { - result.push_back(std::move(Trim(in.substr(last, next - last)))); - last = next + 1; - } - result.push_back(std::move(Trim(in.substr(last)))); - return result; - } - void OpenFile(const std::string& path) { #ifdef WIN32 ShellExecuteA(nullptr, nullptr, path.c_str(), nullptr, nullptr, SW_SHOWNORMAL); diff --git a/src/musikcore/support/Common.h b/src/musikcore/support/Common.h index 959135c11..9bb7768a1 100644 --- a/src/musikcore/support/Common.h +++ b/src/musikcore/support/Common.h @@ -50,9 +50,6 @@ namespace musik { namespace core { bool CopyFile(const std::string& from, const std::string& to); int64_t Checksum(char *data,unsigned int bytes); size_t CopyString(const std::string& src, char* dst, size_t size); - void ReplaceAll(std::string& input, const std::string& find, const std::string& replace); - std::vector Split(const std::string& in, const std::string& delim); - std::string Trim(const std::string& str); bool FileToByteArray(const std::string& path, char** target, int& size, bool nullTerminate = false); } } diff --git a/src/musikcube/app/layout/HotkeysLayout.cpp b/src/musikcube/app/layout/HotkeysLayout.cpp index dd508a158..873f96522 100644 --- a/src/musikcube/app/layout/HotkeysLayout.cpp +++ b/src/musikcube/app/layout/HotkeysLayout.cpp @@ -34,7 +34,7 @@ #include #include "HotkeysLayout.h" -#include +#include #include #include #include @@ -48,6 +48,7 @@ using namespace cursespp; using namespace musik::cube; using namespace musik::core; +using namespace musik::core::sdk; using Entry = IScrollAdapter::EntryPtr; using Callback = std::function; @@ -92,8 +93,8 @@ static void checkConflictAndSave(Hotkeys::Id id, const std::string& key, Callbac auto dialog = std::make_shared(); std::string message = _TSTR("hotkeys_conflict_message"); - ReplaceAll(message, "{{hotkey}}", key); - ReplaceAll(message, "{{existing}}", existing); + str::ReplaceAll(message, "{{hotkey}}", key.c_str()); + str::ReplaceAll(message, "{{existing}}", existing.c_str()); (*dialog) .SetTitle(_TSTR("hotkeys_conflict_title")) @@ -125,7 +126,7 @@ static void backupAndShowDialog() { auto dialog = std::make_shared(); std::string message = _TSTR("hotkeys_backup_success_message"); - ReplaceAll(message, "{{path}}", out); + str::ReplaceAll(message, "{{path}}", out.c_str()); (*dialog) .SetTitle(_TSTR("hotkeys_backup_success_title")) @@ -138,7 +139,7 @@ static void backupAndShowDialog() { auto dialog = std::make_shared(); std::string message = _TSTR("hotkeys_backup_failure_message"); - ReplaceAll(message, "{{path}}", dir); + str::ReplaceAll(message, "{{path}}", dir.c_str()); (*dialog) .SetTitle(_TSTR("hotkeys_backup_failure_title")) @@ -153,8 +154,8 @@ static void showDeleteOverlay(Hotkeys::Id id, Callback cb) { auto dialog = std::make_shared(); std::string message = _TSTR("hotkeys_delete_binding_message"); - ReplaceAll(message, "{{key}}", Hotkeys::Name(id)); - ReplaceAll(message, "{{default}}", Hotkeys::Default(id)); + str::ReplaceAll(message, "{{key}}", Hotkeys::Name(id).c_str()); + str::ReplaceAll(message, "{{default}}", Hotkeys::Default(id).c_str()); (*dialog) .SetTitle(_TSTR("hotkeys_delete_binding_title")) diff --git a/src/musikcube/app/layout/LyricsLayout.cpp b/src/musikcube/app/layout/LyricsLayout.cpp index b9c35d99a..ec85b38ec 100644 --- a/src/musikcube/app/layout/LyricsLayout.cpp +++ b/src/musikcube/app/layout/LyricsLayout.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include @@ -183,9 +183,9 @@ void LyricsLayout::LoadLyricsForCurrentTrack() { void LyricsLayout::UpdateAdapter() { std::string fixed = this->currentLyrics; - ReplaceAll(fixed, "\r\n", "\n"); - ReplaceAll(fixed, "\r", "\n"); - auto items = Split(fixed, "\n"); + str::ReplaceAll(fixed, "\r\n", "\n"); + str::ReplaceAll(fixed, "\r", "\n"); + auto items = str::Split(fixed, "\n"); this->adapter->Clear(); for (auto& text : items) { this->adapter->AddEntry(std::make_shared(text)); diff --git a/src/musikcube/app/overlay/LastFmOverlay.cpp b/src/musikcube/app/overlay/LastFmOverlay.cpp index 7e639f8c1..d50987006 100644 --- a/src/musikcube/app/overlay/LastFmOverlay.cpp +++ b/src/musikcube/app/overlay/LastFmOverlay.cpp @@ -36,13 +36,14 @@ #include "LastFmOverlay.h" #include #include -#include +#include #include #include #include using namespace musik::cube; using namespace musik::core; +using namespace musik::core::sdk; using namespace musik; using namespace cursespp; @@ -122,14 +123,14 @@ void LastFmOverlay::UpdateMessage() { switch (this->state) { case State::Registered: { auto session = lastfm::LoadSession(); - core::ReplaceAll(message, "{{username}}", session.username); + str::ReplaceAll(message, "{{username}}", session.username.c_str()); break; } case State::WaitingForUser: case State::RegisterError: { std::string url = lastfm::CreateAccountLinkUrl(this->linkToken); - core::ReplaceAll(message, "{{link}}", url); + str::ReplaceAll(message, "{{link}}", url.c_str()); break; } diff --git a/src/musikcube/app/overlay/PluginOverlay.cpp b/src/musikcube/app/overlay/PluginOverlay.cpp index 23e49feb1..17c6c6298 100644 --- a/src/musikcube/app/overlay/PluginOverlay.cpp +++ b/src/musikcube/app/overlay/PluginOverlay.cpp @@ -36,11 +36,11 @@ #include "PluginOverlay.h" -#include #include #include #include #include +#include #include #include @@ -76,7 +76,7 @@ using SchemaPtr = std::shared_ptr; static void showConfigureOverlay(IPlugin* plugin, SchemaPtr schema) { std::string title = _TSTR("settings_configure_plugin_title"); - ReplaceAll(title, "{{name}}", plugin->Name()); + str::ReplaceAll(title, "{{name}}", plugin->Name()); auto prefs = Preferences::ForPlugin(plugin->Name()); SchemaOverlay::Show(title, prefs, schema, [](bool) {}); } @@ -85,7 +85,7 @@ static void showNoSchemaDialog(const std::string& name) { std::shared_ptr dialog(new DialogOverlay()); std::string message = _TSTR("settings_no_plugin_config_message"); - ReplaceAll(message, "{{name}}", name); + str::ReplaceAll(message, "{{name}}", name.c_str()); (*dialog) .SetTitle(_TSTR("settings_no_plugin_config_title")) diff --git a/src/musikcube/app/overlay/SettingsOverlays.cpp b/src/musikcube/app/overlay/SettingsOverlays.cpp index 95a3a4189..1b4c2b7dd 100644 --- a/src/musikcube/app/overlay/SettingsOverlays.cpp +++ b/src/musikcube/app/overlay/SettingsOverlays.cpp @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include @@ -54,6 +54,7 @@ using namespace musik; using namespace musik::core; +using namespace musik::core::sdk; using namespace musik::cube; using namespace musik::cube::SettingsOverlays; using namespace cursespp; @@ -201,7 +202,7 @@ void musik::cube::SettingsOverlays::CheckShowTlsWarningDialog() { auto dialog = std::make_shared(); std::string message = _TSTR("settings_library_type_remote_tls_warning_overlay_message"); - musik::core::ReplaceAll(message, "{{link}}", kTlsInfoUrl); + str::ReplaceAll(message, "{{link}}", kTlsInfoUrl.c_str()); (*dialog) .SetTitle(_TSTR("settings_library_type_remote_tls_warning_overlay_title")) diff --git a/src/musikcube/stdafx.h b/src/musikcube/stdafx.h index bddba3cd7..5ab4c0117 100644 --- a/src/musikcube/stdafx.h +++ b/src/musikcube/stdafx.h @@ -68,8 +68,6 @@ asio's streambuf. include it up front so work around this */ #include #pragma warning(push, 0) -#include -#include #include #include #pragma warning(pop) diff --git a/src/plugins/cddadecoder/CddaIndexerSource.cpp b/src/plugins/cddadecoder/CddaIndexerSource.cpp index df46cfbf5..e2642cb5d 100644 --- a/src/plugins/cddadecoder/CddaIndexerSource.cpp +++ b/src/plugins/cddadecoder/CddaIndexerSource.cpp @@ -37,6 +37,7 @@ #include "CddaIndexerSource.h" #include +#include #include @@ -45,10 +46,6 @@ #include #include -#pragma warning(push, 0) -#include -#pragma warning(pop) - using namespace musik::core::sdk; struct CddbMetadata { @@ -179,18 +176,15 @@ static void cddbLookup(const std::string& discId, std::string listQueryParams) { std::string discQueryParams; if (result == CURLE_OK) { /* well... we got something back */ - listResponse = boost::replace_all_copy(listResponse, "\r\n", "\n"); + listResponse = str::ReplaceAllCopy(listResponse, "\r\n", "\n"); - std::vector lines; - boost::algorithm::split(lines, listResponse, boost::is_any_of("\n")); + std::vector lines = str::Split(listResponse, "\n"); /* just choose the first disc for now. we don't have a way to present a UI to the user, so this is really all we can do. */ if (lines.size() >= 1) { if (lines.at(0).find("200") == 0) { - std::vector parts; - boost::algorithm::split(parts, lines.at(0), boost::is_any_of(" ")); - + std::vector parts = str::Split(lines.at(0), " "); if (parts.size() >= 3) { discQueryParams = "cmd=cddb+read+" + parts[1] + "+" + parts[2] + FREEDB_HELLO; } @@ -198,9 +192,7 @@ static void cddbLookup(const std::string& discId, std::string listQueryParams) { /* the first line of the response has a status code. anything in the 200 range is fine. */ else if (lines.at(0).find("21") == 0) { - std::vector parts; - boost::algorithm::split(parts, lines.at(1), boost::is_any_of(" ")); - + std::vector parts = str::Split(lines.at(1), " "); if (parts.size() >= 2) { discQueryParams = "cmd=cddb+read+" + parts[0] + "+" + parts[1] + FREEDB_HELLO; } @@ -219,11 +211,8 @@ static void cddbLookup(const std::string& discId, std::string listQueryParams) { curl_easy_cleanup(details); if (result == CURLE_OK) { - discResponse = boost::replace_all_copy(discResponse, "\r\n", "\n"); - - std::vector lines; - boost::algorithm::split(lines, discResponse, boost::is_any_of("\n")); - + discResponse = str::ReplaceAllCopy(discResponse, "\r\n", "\n"); + std::vector lines = str::Split(discResponse, " "); std::shared_ptr metadata(new CddbMetadata()); for (auto line : lines) { @@ -231,8 +220,8 @@ static void cddbLookup(const std::string& discId, std::string listQueryParams) { if (len) { auto eq = line.find_first_of('='); if (eq != std::string::npos) { - std::string key = boost::trim_copy(line.substr(0, eq)); - std::string value = boost::trim_copy(line.substr(eq + 1)); + std::string key = str::Trim(line.substr(0, eq)); + std::string value = str::Trim(line.substr(eq + 1)); if (key == "DTITLE") { auto slash = value.find_first_of('/'); @@ -242,8 +231,8 @@ static void cddbLookup(const std::string& discId, std::string listQueryParams) { artist = album = value; } else { - artist = boost::trim_copy(value.substr(0, slash)); - album = boost::trim_copy(value.substr(slash + 1)); + artist = str::Trim(value.substr(0, slash)); + album = str::Trim(value.substr(slash + 1)); } metadata->artist = artist; diff --git a/src/plugins/gmedecoder/GmeIndexerSource.cpp b/src/plugins/gmedecoder/GmeIndexerSource.cpp index fabcc5175..8149fc290 100644 --- a/src/plugins/gmedecoder/GmeIndexerSource.cpp +++ b/src/plugins/gmedecoder/GmeIndexerSource.cpp @@ -85,7 +85,7 @@ ScanResult GmeIndexerSource::Scan( this->UpdateMetadata(path, this, indexer); } catch (...) { - std::string error = str::format("error reading metadata for %s", path.c_str()); + std::string error = str::Format("error reading metadata for %s", path.c_str()); debug->Error(PLUGIN_NAME, error.c_str()); } } @@ -159,7 +159,7 @@ void GmeIndexerSource::UpdateMetadata( gme_t* data = nullptr; gme_err_t err = gme_open_file(fn.c_str(), &data, gme_info_only); if (err) { - debug->Error(PLUGIN_NAME, str::format("error opening %s", fn.c_str()).c_str()); + debug->Error(PLUGIN_NAME, str::Format("error opening %s", fn.c_str()).c_str()); invalidFiles.insert(fn); } else { @@ -174,7 +174,7 @@ void GmeIndexerSource::UpdateMetadata( if (m3u.size()) { err = gme_load_m3u(data, m3u.c_str()); if (err) { - debug->Error(PLUGIN_NAME, str::format("m3u found, but load failed '%s'", err).c_str()); + debug->Error(PLUGIN_NAME, str::Format("m3u found, but load failed '%s'", err).c_str()); } } } @@ -201,7 +201,7 @@ void GmeIndexerSource::UpdateMetadata( gme_info_t* info = nullptr; err = gme_track_info(data, &info, i); if (err) { - debug->Error(PLUGIN_NAME, str::format("error getting track %d: %s", i, err).c_str()); + debug->Error(PLUGIN_NAME, str::Format("error getting track %d: %s", i, err).c_str()); track->SetValue("duration", defaultDuration.c_str()); track->SetValue("title", defaultTitle.c_str()); } diff --git a/src/plugins/httpdatastream/HttpDataStream.cpp b/src/plugins/httpdatastream/HttpDataStream.cpp index f5d7362ea..2e581c654 100755 --- a/src/plugins/httpdatastream/HttpDataStream.cpp +++ b/src/plugins/httpdatastream/HttpDataStream.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -51,9 +52,6 @@ #include #pragma warning(push, 0) -#include - -/* meh... */ #include <../../3rdparty/include/nlohmann/json.hpp> #include <../../3rdparty/include/websocketpp/base64/base64.hpp> #pragma warning(pop) @@ -70,7 +68,6 @@ using namespace std::chrono; using namespace musik::core::sdk; -namespace al = boost::algorithm; static std::mutex globalMutex; static IEnvironment* environment; @@ -119,12 +116,12 @@ extern "C" DLLEXPORT musik::core::sdk::ISchema * GetSchema() { } static bool parseHeader(std::string raw, std::string& key, std::string& value) { - al::replace_all(raw, "\r\n", ""); + str::ReplaceAll(raw, "\r\n", ""); size_t splitAt = raw.find_first_of(":"); if (splitAt != std::string::npos) { - key = boost::trim_copy(raw.substr(0, splitAt)); - value = boost::trim_copy(raw.substr(splitAt + 1)); + key = str::Trim(raw.substr(0, splitAt)); + value = str::Trim(raw.substr(splitAt + 1)); return true; } diff --git a/src/plugins/httpdatastream/LruDiskCache.cpp b/src/plugins/httpdatastream/LruDiskCache.cpp index c1a017d52..554743fcb 100644 --- a/src/plugins/httpdatastream/LruDiskCache.cpp +++ b/src/plugins/httpdatastream/LruDiskCache.cpp @@ -36,19 +36,17 @@ #include "LruDiskCache.h" +#include + #include #include #include -#pragma warning(push, 0) -#include -#pragma warning(pop) - const std::string PREFIX = "musikcube"; const std::string TEMP_EXTENSION = ".tmp"; namespace fs = std::filesystem; -namespace al = boost::algorithm; +using namespace musik::core::sdk; using Lock = std::unique_lock; @@ -57,7 +55,7 @@ static std::string tempFilename(const std::string& root, size_t id, int64_t inst } static std::string finalFilename(const std::string& root, size_t id, std::string type) { - al::replace_all(type, "/", "-"); + str::ReplaceAll(type, "/", "-"); return root + "/" + PREFIX + "_" + std::to_string(id) + "_" + type; } @@ -152,8 +150,7 @@ void LruDiskCache::Purge() { LruDiskCache::EntryPtr LruDiskCache::Parse(const fs::path& path) { std::string fn = path.stem().u8string() + path.extension().u8string(); - std::vector parts; - boost::split(parts, fn, boost::is_any_of("_")); + std::vector parts = str::Split(fn, "_"); if (parts.size() == 3 && parts[0] == PREFIX) { try { auto entry = std::shared_ptr(new Entry()); @@ -161,7 +158,7 @@ LruDiskCache::EntryPtr LruDiskCache::Parse(const fs::path& path) { entry->path = path.u8string(); entry->type = parts[2]; entry->time = fs::last_write_time(path); - al::replace_all(entry->type, "-", "/"); + str::ReplaceAll(entry->type, "-", "/"); return entry; } catch (...) { diff --git a/src/plugins/libopenmptdecoder/OpenMptIndexerSource.cpp b/src/plugins/libopenmptdecoder/OpenMptIndexerSource.cpp index 7b5a84527..5f3d27595 100644 --- a/src/plugins/libopenmptdecoder/OpenMptIndexerSource.cpp +++ b/src/plugins/libopenmptdecoder/OpenMptIndexerSource.cpp @@ -93,7 +93,7 @@ ScanResult OpenMptIndexerSource::Scan( this->UpdateMetadata(path, this, indexer); } catch (...) { - std::string error = str::format("error reading metadata for %s", path.c_str()); + std::string error = str::Format("error reading metadata for %s", path.c_str()); debug->Error(PLUGIN_NAME.c_str(), error.c_str()); } } @@ -161,7 +161,7 @@ static std::string formatDefaultValue(const char* key, const char* defaultValue, prefs->GetString(key, threadLocalBuffer, 4096, defaultValue); std::string value(threadLocalBuffer); threadLocalBuffer[0] = 0; - return str::format(value, type.c_str()); + return str::Format(value, type.c_str()); } void OpenMptIndexerSource::UpdateMetadata( @@ -184,7 +184,7 @@ void OpenMptIndexerSource::UpdateMetadata( nullptr, nullptr, nullptr, nullptr, nullptr); if (!module) { - debug->Error(PLUGIN_NAME.c_str(), str::format("error opening %s", fn.c_str()).c_str()); + debug->Error(PLUGIN_NAME.c_str(), str::Format("error opening %s", fn.c_str()).c_str()); invalidFiles.insert(fn); } else { diff --git a/src/plugins/server/HttpServer.cpp b/src/plugins/server/HttpServer.cpp index a538dd90f..679b76f61 100644 --- a/src/plugins/server/HttpServer.cpp +++ b/src/plugins/server/HttpServer.cpp @@ -42,7 +42,6 @@ #include #pragma warning(push, 0) -#include #include #pragma warning(pop, 0) @@ -105,9 +104,7 @@ struct Range { static std::string contentType(const std::string& fn) { try { std::fs::path p(std::fs::u8path(fn)); - std::string ext = boost::trim_copy(p.extension().u8string()); - boost::to_lower(ext); - + std::string ext = str::ToLowerCopy(str::Trim(p.extension().u8string())); auto it = CONTENT_TYPE_MAP.find(ext); if (it != CONTENT_TYPE_MAP.end()) { return it->second; @@ -122,9 +119,8 @@ static std::string contentType(const std::string& fn) { static std::string fileExtension(const std::string& fn) { try { std::fs::path p(std::fs::u8path(fn)); - std::string ext = boost::trim_copy(p.extension().u8string()); + std::string ext = str::ToLowerCopy(str::Trim(p.extension().u8string())); if (ext.size()) { - boost::to_lower(ext); return ext[0] == '.' ? ext.substr(1) : ext; } } @@ -181,17 +177,14 @@ static Range* parseRange(IDataStream* file, const char* range) { if (str.substr(0, 6) == "bytes=") { str = str.substr(6); - - std::vector parts; - boost::split(parts, str, boost::is_any_of("-")); - + std::vector parts = str::Split(str, "-"); if (parts.size() == 2) { try { - size_t from = (size_t) std::max(0, std::stoi(boost::algorithm::trim_copy(parts[0]))); + size_t from = (size_t) std::max(0, std::stoi(str::Trim(parts[0]))); size_t to = size; if (parts.at(1).size()) { - to = (size_t) std::min((int) size, std::stoi(boost::algorithm::trim_copy(parts[1]))); + to = (size_t) std::min((int) size, std::stoi(str::Trim(parts[1]))); } if (to > from) { @@ -269,10 +262,7 @@ static bool isAuthenticated(MHD_Connection *connection, Context& context) { std::string encoded = auth.substr(6); if (encoded.size()) { std::string decoded = websocketpp::base64_decode(encoded); - - std::vector userPass; - boost::split(userPass, decoded, boost::is_any_of(":")); - + std::vector userPass = str::Split(decoded, ":"); if (userPass.size() == 2) { std::string password = GetPreferenceString(context.prefs, key::password, defaults::password); return userPass[0] == "default" && userPass[1] == password; @@ -372,7 +362,7 @@ MHD_Result HttpServer::HandleRequest( auto server = static_cast(cls); #ifdef ENABLE_DEBUG - server->context.debug->Info(TAG, str::format("new request: %s", url).c_str()); + server->context.debug->Info(TAG, str::Format("new request: %s", url).c_str()); #endif struct MHD_Response* response = nullptr; @@ -397,8 +387,7 @@ MHD_Result HttpServer::HandleRequest( urlStr = urlStr.substr(1); } - std::vector parts; - boost::split(parts, urlStr, boost::is_any_of("/")); + std::vector parts = str::Split(urlStr, "/"); if (parts.size() > 0) { /* /audio/id/ OR /audio/external_id/ */ if (parts.at(0) == fragment::audio && parts.size() == 3) { @@ -417,7 +406,7 @@ MHD_Result HttpServer::HandleRequest( if (response) { #ifdef ENABLE_DEBUG - server->context.debug->Info(TAG, str::format("return http %d", status).c_str()); + server->context.debug->Info(TAG, str::Format("return http %d", status).c_str()); #endif ret = MHD_queue_response(connection, status, response); @@ -484,7 +473,7 @@ int HttpServer::HandleAudioTrackRequest( bool isOnDemandTranscoder = !!dynamic_cast(file); #ifdef ENABLE_DEBUG - server->context.debug->Info(TAG, str::format( + server->context.debug->Info(TAG, str::Format( "range request: %s, resolved range: %s, isOnDemandTranscoder=%s", rangeVal ? rangeVal : "[unspecified]", range ? range->HeaderValue().c_str() : "[unresolved]", @@ -547,7 +536,7 @@ int HttpServer::HandleAudioTrackRequest( &fileFreeCallback); #ifdef ENABLE_DEBUG - server->context.debug->Info(TAG, str::format("response length=%d", ((length == 0) ? 0 : length + 1)).c_str()); + server->context.debug->Info(TAG, str::Format("response length=%d", ((length == 0) ? 0 : length + 1)).c_str()); #endif if (response) { @@ -591,7 +580,7 @@ int HttpServer::HandleAudioTrackRequest( status = MHD_HTTP_PARTIAL_CONTENT; #ifdef ENABLE_DEBUG if (rangeVal) { - server->context.debug->Info(TAG, str::format("range header: %s", range->HeaderValue().c_str()).c_str()); + server->context.debug->Info(TAG, str::Format("range header: %s", range->HeaderValue().c_str()).c_str()); } #endif } diff --git a/src/plugins/server/WebSocketServer.cpp b/src/plugins/server/WebSocketServer.cpp index 6179556ee..26ada77f6 100644 --- a/src/plugins/server/WebSocketServer.cpp +++ b/src/plugins/server/WebSocketServer.cpp @@ -36,6 +36,7 @@ #include "Constants.h" #include +#include using websocketpp::lib::placeholders::_1; using websocketpp::lib::placeholders::_2; @@ -49,19 +50,8 @@ static const char* TAG = "WebSocketServer"; /* UTILITY METHODS */ -namespace str { - template - static std::string format(const std::string& format, Args ... args) { - /* https://stackoverflow.com/a/26221725 */ - size_t size = std::snprintf(nullptr, 0, format.c_str(), args ...) + 1; /* extra space for '\0' */ - std::unique_ptr buf(new char[size]); - std::snprintf(buf.get(), size, format.c_str(), args ...); - return std::string(buf.get(), buf.get() + size - 1); /* omit the '\0' */ - } -} - static std::string nextMessageId() { - return str::format("musikcube-server-%d", ++nextId); + return str::Format("musikcube-server-%d", ++nextId); } static std::shared_ptr jsonToStringArray(const json& jsonArray) { @@ -194,10 +184,10 @@ void WebSocketServer::ThreadProc() { wss->run(); } catch (websocketpp::exception const & e) { - this->context.debug->Error(TAG, str::format("[ThreadProc] websocketpp::exception: %s", e.what()).c_str()); + this->context.debug->Error(TAG, str::Format("[ThreadProc] websocketpp::exception: %s", e.what()).c_str()); } catch (std::exception& e) { - this->context.debug->Error(TAG, str::format("[ThreadProc] sttd::exception: %s", e.what()).c_str()); + this->context.debug->Error(TAG, str::Format("[ThreadProc] sttd::exception: %s", e.what()).c_str()); } catch (...) { this->context.debug->Error(TAG, "[ThreadProc] unknown/unexpected exception"); @@ -1655,11 +1645,11 @@ void WebSocketServer::OnMessage(server* s, connection_hdl hdl, message_ptr msg) } } catch (std::exception& e) { - this->context.debug->Error(TAG, str::format("OnMessage failed: %s", e.what()).c_str()); + this->context.debug->Error(TAG, str::Format("OnMessage failed: %s", e.what()).c_str()); this->RespondWithInvalidRequest(hdl, value::invalid, value::invalid); } catch (...) { - this->context.debug->Error(TAG, str::format("message parse failed: %s", msg->get_payload().c_str()).c_str()); + this->context.debug->Error(TAG, str::Format("message parse failed: %s", msg->get_payload().c_str()).c_str()); this->RespondWithInvalidRequest(hdl, value::invalid, value::invalid); } } diff --git a/src/plugins/taglib_plugin/TaglibMetadataReader.cpp b/src/plugins/taglib_plugin/TaglibMetadataReader.cpp index a912a594f..cc8572352 100644 --- a/src/plugins/taglib_plugin/TaglibMetadataReader.cpp +++ b/src/plugins/taglib_plugin/TaglibMetadataReader.cpp @@ -34,6 +34,8 @@ #include "TaglibMetadataReader.h" +#include + #ifdef WIN32 #include #include @@ -94,57 +96,6 @@ using namespace musik::core::sdk; -namespace str { - static std::string lower(std::string input) { - std::transform(input.begin(), input.end(), input.begin(), ::tolower); - return input; - } - - static inline bool isSpace(const char c) { - return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\v' || c == '\f'; - } - - std::string trim(const std::string& str) { - if (str.size()) { - int length = (size_t) str.size(); - int start = 0, end = length; - int i = 0; - while (i < length) { - if (!isSpace(str[i])) { - break; - } - ++start; - ++i; - } - i = end - 1; - while (i >= 0) { - if (!isSpace(str[i])) { - break; - } - --i; - } - if (end >= start) { - std::string result = str.substr((size_t) start, (size_t) end - start); - return result; - } - } - return str; - } - - static std::vector split( - const std::string& in, const std::string& delim) - { - std::vector result; - size_t last = 0, next = 0; - while ((next = in.find(delim, last)) != std::string::npos) { - result.push_back(std::move(trim(in.substr(last, next - last)))); - last = next + 1; - } - result.push_back(std::move(trim(in.substr(last)))); - return result; - } -} - #ifdef WIN32 static inline std::wstring utf8to16(const char* utf8) { int size = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, 0, 0); @@ -200,7 +151,7 @@ static bool isValidYear(const std::string& year) { static float toReplayGainFloat(const std::string& input) { /* trim any trailing " db" or "db" noise... */ - std::string lower = str::lower(input); + std::string lower = str::ToLowerCopy(input); if (lower.find(" db") == lower.length() - 3) { lower = lower.substr(0, lower.length() - 3); } @@ -252,7 +203,8 @@ void TaglibMetadataReader::Release() { bool TaglibMetadataReader::CanRead(const char *extension) { if (extension && strlen(extension)) { - std::string ext(str::lower(extension[0] == '.' ? &extension[1] : extension)); + std::string withoutLeadingDot = std::string(extension[0] == '.' ? &extension[1] : extension); + std::string ext = str::ToLowerCopy(withoutLeadingDot); return ext.compare("opus") == 0 || ext.compare("wv") == 0 || @@ -294,7 +246,7 @@ bool TaglibMetadataReader::Read(const char* uri, ITagStore *track) { /* ID3v2 is a trainwreck, so it requires special processing */ if (extension.size()) { - if (str::lower(extension) == "mp3") { + if (str::ToLowerCopy(extension) == "mp3") { this->ReadID3V2(uri, track); } } @@ -522,7 +474,7 @@ void TaglibMetadataReader::ExtractReplayGain(const T& map, ITagStore *target) void TaglibMetadataReader::SetTagValueWithPossibleTotal( const std::string& value, const std::string& valueKey, const std::string& totalKey, ITagStore* track) { - std::vector parts = str::split(value, "/"); + std::vector parts = str::Split(value, "/"); this->SetTagValue(valueKey.c_str(), parts[0].c_str(), track); if (parts.size() > 1) { this->SetTagValue(totalKey.c_str(), parts[1].c_str(), track); @@ -809,7 +761,7 @@ void TaglibMetadataReader::SetSlashSeparatedValues( { if (!tagString.isEmpty()) { std::string value(tagString.to8Bit(true)); - std::vector splitValues = str::split(value, "/"); + std::vector splitValues = str::Split(value, "/"); std::vector::iterator it = splitValues.begin(); for( ; it != splitValues.end(); ++it) { track->SetValue(key, it->c_str());