diff --git a/client/snapClient.cpp b/client/snapClient.cpp index eba291bf..a567bfa0 100644 --- a/client/snapClient.cpp +++ b/client/snapClient.cpp @@ -171,7 +171,7 @@ int main (int argc, char **argv) if (userValue.getValue().empty()) std::invalid_argument("user must not be empty"); - vector user_group = split(userValue.getValue(), ':'); + vector user_group = utils::string::split(userValue.getValue(), ':'); user = user_group[0]; if (user_group.size() > 1) group = user_group[1]; diff --git a/common/sampleFormat.cpp b/common/sampleFormat.cpp index 699cdc41..e03e245c 100644 --- a/common/sampleFormat.cpp +++ b/common/sampleFormat.cpp @@ -22,6 +22,7 @@ #include "sampleFormat.h" #include "common/strCompat.h" +#include "common/utils/string_utils.h" #include "common/utils.h" #include "common/log.h" @@ -57,7 +58,7 @@ string SampleFormat::getFormat() const void SampleFormat::setFormat(const std::string& format) { std::vector strs; - strs = split(format, ':'); + strs = utils::string::split(format, ':'); if (strs.size() == 3) setFormat( cpt::stoul(strs[0]), diff --git a/common/utils.h b/common/utils.h index 7d060e46..83b25984 100644 --- a/common/utils.h +++ b/common/utils.h @@ -20,8 +20,8 @@ #define UTILS_H #include "common/strCompat.h" +#include "common/utils/string_utils.h" -#include #include #include #include @@ -51,94 +51,11 @@ #endif -// trim from start -static inline std::string <rim(std::string &s) -{ - s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); - return s; -} - -// trim from end -static inline std::string &rtrim(std::string &s) -{ - s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); - return s; -} - -// trim from both ends -static inline std::string &trim(std::string &s) -{ - return ltrim(rtrim(s)); -} - -// trim from start -static inline std::string ltrim_copy(const std::string &s) -{ - std::string str(s); - return ltrim(str); -} - -// trim from end -static inline std::string rtrim_copy(const std::string &s) -{ - std::string str(s); - return rtrim(str); -} - -// trim from both ends -static inline std::string trim_copy(const std::string &s) -{ - std::string str(s); - return trim(str); -} - -// decode %xx to char -static std::string uriDecode(const std::string& src) { - std::string ret; - char ch; - for (size_t i=0; i(ii); - ret += ch; - i += 2; - } - else - { - ret += src[i]; - } - } - return (ret); -} - - - -static std::vector &split(const std::string &s, char delim, std::vector &elems) -{ - std::stringstream ss(s); - std::string item; - while (std::getline(ss, item, delim)) - { - elems.push_back(item); - } - return elems; -} - - -static std::vector split(const std::string &s, char delim) -{ - std::vector elems; - split(s, delim, elems); - return elems; -} - +namespace strutils = utils::string; static int mkdirRecursive(const char *path, mode_t mode) { - std::vector pathes = split(path, '/'); + std::vector pathes = strutils::split(path, '/'); std::stringstream ss; int res = 0; for (const auto& p: pathes) @@ -166,7 +83,7 @@ static std::string execGetOutput(const std::string& cmd) if (fgets(buffer, 1024, pipe.get()) != NULL) result += buffer; } - return trim(result); + return strutils::trim(result); } @@ -182,18 +99,18 @@ static std::string getOS() { std::string os; #ifdef ANDROID - os = trim_copy("Android " + getProp("ro.build.version.release")); + os = strutils::trim_copy("Android " + getProp("ro.build.version.release")); #else os = execGetOutput("lsb_release -d"); if ((os.find(":") != std::string::npos) && (os.find("lsb_release") == std::string::npos)) - os = trim_copy(os.substr(os.find(":") + 1)); + os = strutils::trim_copy(os.substr(os.find(":") + 1)); #endif if (os.empty()) { - os = trim_copy(execGetOutput("grep /etc/os-release /etc/openwrt_release -e PRETTY_NAME -e DISTRIB_DESCRIPTION")); + os = strutils::trim_copy(execGetOutput("grep /etc/os-release /etc/openwrt_release -e PRETTY_NAME -e DISTRIB_DESCRIPTION")); if (os.find("=") != std::string::npos) { - os = trim_copy(os.substr(os.find("=") + 1)); + os = strutils::trim_copy(os.substr(os.find("=") + 1)); os.erase(std::remove(os.begin(), os.end(), '"'), os.end()); os.erase(std::remove(os.begin(), os.end(), '\''), os.end()); } @@ -204,7 +121,7 @@ static std::string getOS() uname(&u); os = u.sysname; } - return trim_copy(os); + return strutils::trim_copy(os); } @@ -235,7 +152,7 @@ static std::string getArch() arch = execGetOutput("uname -i"); if (arch.empty() || (arch == "unknown")) arch = execGetOutput("uname -m"); - return trim_copy(arch); + return strutils::trim_copy(arch); } @@ -249,7 +166,7 @@ static long uptime() std::string uptime = execGetOutput("sysctl kern.boottime"); if ((uptime.find(" sec = ") != std::string::npos) && (uptime.find(",") != std::string::npos)) { - uptime = trim_copy(uptime.substr(uptime.find(" sec = ") + 7)); + uptime = strutils::trim_copy(uptime.substr(uptime.find(" sec = ") + 7)); uptime.resize(uptime.find(",")); timeval now; gettimeofday(&now, NULL); @@ -361,7 +278,7 @@ static std::string getMacAddress(int sock) std::string line; if (infile.good() && std::getline(infile, line)) { - trim(line); + strutils::trim(line); if ((line.size() == 17) && (line[2] == ':')) return line; } @@ -391,6 +308,22 @@ static std::string getMacAddress(int sock) } +static std::string getClientId(const std::string defaultId = "") +{ + std::string result = defaultId; + if (!result.empty()) + return result; + +#ifdef ANDROID + result = getProp("ro.serialno"); + if (!result.empty()) + return result; +#endif + + return getHostName(); +} + + #endif diff --git a/common/utils/string_utils.h b/common/utils/string_utils.h new file mode 100644 index 00000000..6e86b4a9 --- /dev/null +++ b/common/utils/string_utils.h @@ -0,0 +1,103 @@ +#ifndef STRING_UTILS_H +#define STRING_UTILS_H + +#include +#include +#include +#include + + +namespace utils +{ +namespace string +{ + +// trim from start +static inline std::string <rim(std::string &s) +{ + s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); + return s; +} + +// trim from end +static inline std::string &rtrim(std::string &s) +{ + s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + return s; +} + +// trim from both ends +static inline std::string &trim(std::string &s) +{ + return ltrim(rtrim(s)); +} + +// trim from start +static inline std::string ltrim_copy(const std::string &s) +{ + std::string str(s); + return ltrim(str); +} + +// trim from end +static inline std::string rtrim_copy(const std::string &s) +{ + std::string str(s); + return rtrim(str); +} + +// trim from both ends +static inline std::string trim_copy(const std::string &s) +{ + std::string str(s); + return trim(str); +} + +// decode %xx to char +static std::string uriDecode(const std::string& src) { + std::string ret; + char ch; + for (size_t i=0; i(ii); + ret += ch; + i += 2; + } + else + { + ret += src[i]; + } + } + return (ret); +} + + + +static std::vector &split(const std::string &s, char delim, std::vector &elems) +{ + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) + { + elems.push_back(item); + } + return elems; +} + + +static std::vector split(const std::string &s, char delim) +{ + std::vector elems; + split(s, delim, elems); + return elems; +} + +} // namespace string +} // namespace utils + +#endif + diff --git a/server/config.h b/server/config.h index 12c3effa..22c5e4fa 100644 --- a/server/config.h +++ b/server/config.h @@ -24,9 +24,11 @@ #include #include #include "externals/json.hpp" +#include "common/utils/string_utils.h" #include "common/utils.h" +namespace strutils = utils::string; using json = nlohmann::json; struct ClientInfo; @@ -93,11 +95,11 @@ struct Host void fromJson(const json& j) { - name = trim_copy(jGet(j, "name", "")); - mac = trim_copy(jGet(j, "mac", "")); - os = trim_copy(jGet(j, "os", "")); - arch = trim_copy(jGet(j, "arch", "")); - ip = trim_copy(jGet(j, "ip", "")); + name = strutils::trim_copy(jGet(j, "name", "")); + mac = strutils::trim_copy(jGet(j, "mac", "")); + os = strutils::trim_copy(jGet(j, "os", "")); + arch = strutils::trim_copy(jGet(j, "arch", "")); + ip = strutils::trim_copy(jGet(j, "ip", "")); } json toJson() @@ -127,7 +129,7 @@ struct ClientConfig void fromJson(const json& j) { - name = trim_copy(jGet(j, "name", "")); + name = strutils::trim_copy(jGet(j, "name", "")); volume.fromJson(j["volume"]); latency = jGet(j, "latency", 0); instance = jGet(j, "instance", 1); @@ -136,7 +138,7 @@ struct ClientConfig json toJson() { json j; - j["name"] = trim_copy(name); + j["name"] = strutils::trim_copy(name); j["volume"] = volume.toJson(); j["latency"] = latency; j["instance"] = instance; @@ -163,16 +165,16 @@ struct Snapcast virtual void fromJson(const json& j) { - name = trim_copy(jGet(j, "name", "")); - version = trim_copy(jGet(j, "version", "")); + name = strutils::trim_copy(jGet(j, "name", "")); + version = strutils::trim_copy(jGet(j, "version", "")); protocolVersion = jGet(j, "protocolVersion", 1); } virtual json toJson() { json j; - j["name"] = trim_copy(name); - j["version"] = trim_copy(version); + j["name"] = strutils::trim_copy(name); + j["version"] = strutils::trim_copy(version); j["protocolVersion"] = protocolVersion; return j; } @@ -266,9 +268,9 @@ struct Group void fromJson(const json& j) { - name = trim_copy(jGet(j, "name", "")); - id = trim_copy(jGet(j, "id", "")); - streamId = trim_copy(jGet(j, "stream_id", "")); + name = strutils::trim_copy(jGet(j, "name", "")); + id = strutils::trim_copy(jGet(j, "id", "")); + streamId = strutils::trim_copy(jGet(j, "stream_id", "")); muted = jGet(j, "muted", false); clients.clear(); if (j.count("clients")) @@ -286,9 +288,9 @@ struct Group json toJson() { json j; - j["name"] = trim_copy(name); - j["id"] = trim_copy(id); - j["stream_id"] = trim_copy(streamId); + j["name"] = strutils::trim_copy(name); + j["id"] = strutils::trim_copy(id); + j["stream_id"] = strutils::trim_copy(streamId); j["muted"] = muted; json jClients = json::array(); diff --git a/server/encoder/encoderFactory.cpp b/server/encoder/encoderFactory.cpp index 292f2d56..75e99add 100644 --- a/server/encoder/encoderFactory.cpp +++ b/server/encoder/encoderFactory.cpp @@ -20,7 +20,7 @@ #include "pcmEncoder.h" #include "oggEncoder.h" #include "flacEncoder.h" -#include "common/utils.h" +#include "common/utils/string_utils.h" #include "common/snapException.h" #include "common/log.h" @@ -35,8 +35,8 @@ Encoder* EncoderFactory::createEncoder(const std::string& codecSettings) const std::string codecOptions; if (codec.find(":") != std::string::npos) { - codecOptions = trim_copy(codec.substr(codec.find(":") + 1)); - codec = trim_copy(codec.substr(0, codec.find(":"))); + codecOptions = utils::string::trim_copy(codec.substr(codec.find(":") + 1)); + codec = utils::string::trim_copy(codec.substr(0, codec.find(":"))); } if (codec == "ogg") encoder = new OggEncoder(codecOptions); diff --git a/server/encoder/oggEncoder.cpp b/server/encoder/oggEncoder.cpp index 1f857bb8..3aef4e89 100644 --- a/server/encoder/oggEncoder.cpp +++ b/server/encoder/oggEncoder.cpp @@ -22,6 +22,7 @@ #include "oggEncoder.h" #include "common/snapException.h" #include "common/strCompat.h" +#include "common/utils/string_utils.h" #include "common/utils.h" #include "common/log.h" @@ -144,11 +145,11 @@ void OggEncoder::initEncoder() { if (codecOptions_.find(":") == string::npos) throw SnapException("Invalid codec options: \"" + codecOptions_ + "\""); - string mode = trim_copy(codecOptions_.substr(0, codecOptions_.find(":"))); + string mode = utils::string::trim_copy(codecOptions_.substr(0, codecOptions_.find(":"))); if (mode != "VBR") throw SnapException("Unsupported codec mode: \"" + mode + "\". Available: \"VBR\""); - string qual = trim_copy(codecOptions_.substr(codecOptions_.find(":") + 1)); + string qual = utils::string::trim_copy(codecOptions_.substr(codecOptions_.find(":") + 1)); double quality = 1.0; try { diff --git a/server/snapServer.cpp b/server/snapServer.cpp index 111f0689..050dd60e 100644 --- a/server/snapServer.cpp +++ b/server/snapServer.cpp @@ -25,6 +25,7 @@ #include "common/daemon.h" #endif #include "common/timeDefs.h" +#include "common/utils/string_utils.h" #include "common/signalHandler.h" #include "common/snapException.h" #include "common/sampleFormat.h" @@ -157,7 +158,7 @@ int main(int argc, char* argv[]) if (userValue.getValue().empty()) std::invalid_argument("user must not be empty"); - vector user_group = split(userValue.getValue(), ':'); + vector user_group = utils::string::split(userValue.getValue(), ':'); user = user_group[0]; if (user_group.size() > 1) group = user_group[1]; diff --git a/server/streamreader/airplayStream.cpp b/server/streamreader/airplayStream.cpp index 7c313038..6ebd3e63 100644 --- a/server/streamreader/airplayStream.cpp +++ b/server/streamreader/airplayStream.cpp @@ -18,6 +18,7 @@ #include "airplayStream.h" #include "common/snapException.h" +#include "common/utils/string_utils.h" #include "common/utils.h" #include "common/log.h" @@ -68,7 +69,7 @@ void AirplayStream::initExeAndPath(const std::string& filename) void AirplayStream::onStderrMsg(const char* buffer, size_t n) { - string logmsg = trim_copy(string(buffer, n)); + string logmsg = utils::string::trim_copy(string(buffer, n)); if (logmsg.empty()) return; logO << "(" << getName() << ") " << logmsg << "\n"; diff --git a/server/streamreader/processStream.cpp b/server/streamreader/processStream.cpp index c301c558..21e03726 100644 --- a/server/streamreader/processStream.cpp +++ b/server/streamreader/processStream.cpp @@ -22,6 +22,7 @@ #include #include "processStream.h" #include "common/snapException.h" +#include "common/utils/string_utils.h" #include "common/utils.h" #include "common/log.h" @@ -120,7 +121,7 @@ void ProcessStream::onStderrMsg(const char* buffer, size_t n) { if (logStderr_) { - string line = trim_copy(string(buffer, n)); + string line = utils::string::trim_copy(string(buffer, n)); if ((line.find('\0') == string::npos) && !line.empty()) logO << "(" << getName() << ") " << line << "\n"; } diff --git a/server/streamreader/spotifyStream.cpp b/server/streamreader/spotifyStream.cpp index f621787f..d82974c9 100644 --- a/server/streamreader/spotifyStream.cpp +++ b/server/streamreader/spotifyStream.cpp @@ -18,6 +18,7 @@ #include "spotifyStream.h" #include "common/snapException.h" +#include "common/utils/string_utils.h" #include "common/utils.h" #include "common/log.h" @@ -101,7 +102,7 @@ void SpotifyStream::onStderrMsg(const char* buffer, size_t n) // 2016-11-03 09-00-18 [out] INFO:librespot::session: Connecting to AP lon3-accesspoint-a34.ap.spotify.com:443 // 2016-11-03 09-00-18 [out] INFO:librespot::session: Authenticated ! watchdog_->trigger(); - string logmsg = trim_copy(string(buffer, n)); + string logmsg = utils::string::trim_copy(string(buffer, n)); if ((logmsg.find("allocated stream") == string::npos) && (logmsg.find("Got channel") == string::npos) && (logmsg.find('\0') == string::npos) && diff --git a/server/streamreader/streamUri.cpp b/server/streamreader/streamUri.cpp index dbdf8e28..eeda6ade 100644 --- a/server/streamreader/streamUri.cpp +++ b/server/streamreader/streamUri.cpp @@ -17,12 +17,13 @@ ***/ #include "streamUri.h" -#include "common/utils.h" +#include "common/utils/string_utils.h" #include "common/strCompat.h" #include "common/log.h" using namespace std; +namespace strutils = utils::string; StreamUri::StreamUri(const std::string& streamUri) @@ -32,13 +33,13 @@ StreamUri::StreamUri(const std::string& streamUri) // would be more elegant with regex. Not yet supported on my dev machine's gcc 4.8 :( logD << "StreamUri: " << streamUri << "\n"; size_t pos; - uri = trim_copy(streamUri); + uri = strutils::trim_copy(streamUri); while (!uri.empty() && ((uri[0] == '\'') || (uri[0] == '"'))) uri = uri.substr(1); while (!uri.empty() && ((uri[uri.length()-1] == '\'') || (uri[uri.length()-1] == '"'))) uri = uri.substr(0, this->uri.length()-1); - string decodedUri = uriDecode(uri); + string decodedUri = strutils::uriDecode(uri); logD << "StreamUri: " << decodedUri << "\n"; string tmp(decodedUri); @@ -46,7 +47,7 @@ StreamUri::StreamUri(const std::string& streamUri) pos = tmp.find(':'); if (pos == string::npos) throw invalid_argument("missing ':'"); - scheme = trim_copy(tmp.substr(0, pos)); + scheme = strutils::trim_copy(tmp.substr(0, pos)); tmp = tmp.substr(pos + 1); logD << "scheme: '" << scheme << "' tmp: '" << tmp << "'\n"; @@ -57,7 +58,7 @@ StreamUri::StreamUri(const std::string& streamUri) pos = tmp.find('/'); if (pos == string::npos) throw invalid_argument("missing path separator: '/'"); - host = trim_copy(tmp.substr(0, pos)); + host = strutils::trim_copy(tmp.substr(0, pos)); tmp = tmp.substr(pos); path = tmp; logD << "host: '" << host << "' tmp: '" << tmp << "' path: '" << path << "'\n"; @@ -66,7 +67,7 @@ StreamUri::StreamUri(const std::string& streamUri) if (pos == string::npos) return; - path = trim_copy(tmp.substr(0, pos)); + path = strutils::trim_copy(tmp.substr(0, pos)); tmp = tmp.substr(pos + 1); string queryStr = tmp; logD << "path: '" << path << "' tmp: '" << tmp << "' query: '" << queryStr << "'\n"; @@ -76,18 +77,18 @@ StreamUri::StreamUri(const std::string& streamUri) { queryStr = tmp.substr(0, pos); tmp = tmp.substr(pos + 1); - fragment = trim_copy(tmp); + fragment = strutils::trim_copy(tmp); logD << "query: '" << queryStr << "' fragment: '" << fragment << "' tmp: '" << tmp << "'\n"; } - vector keyValueList = split(queryStr, '&'); + vector keyValueList = strutils::split(queryStr, '&'); for (auto& kv: keyValueList) { pos = kv.find('='); if (pos != string::npos) { - string key = trim_copy(kv.substr(0, pos)); - string value = trim_copy(kv.substr(pos+1)); + string key = strutils::trim_copy(kv.substr(0, pos)); + string value = strutils::trim_copy(kv.substr(pos+1)); query[key] = value; } }