/* * Copyright 2013 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "strings.h" #include #include #include #include #include #include //Const char based #include "strings_legacy.cpp" // legacy c functions #include "strings_misc.cpp" // anything non "Strings" scoped std::vector Strings::Split(const std::string &str, const char delim) { std::vector ret; std::string::size_type start = 0; auto end = str.find(delim); while (end != std::string::npos) { ret.emplace_back(str, start, end - start); start = end + 1; end = str.find(delim, start); } // this will catch the last word since the string is unlikely to end with a delimiter if (str.length() > start) { ret.emplace_back(str, start, str.length() - start); } return ret; } // this one takes delimiter length into consideration std::vector Strings::Split(std::string s, std::string delimiter) { size_t pos_start = 0, pos_end, delim_len = delimiter.length(); std::string token; std::vector res; while ((pos_end = s.find(delimiter, pos_start)) != std::string::npos) { token = s.substr(pos_start, pos_end - pos_start); pos_start = pos_end + delim_len; res.push_back(token); } res.push_back(s.substr(pos_start)); return res; } std::string Strings::Strings::GetBetween(const std::string &s, std::string start_delim, std::string stop_delim) { if (s.find(start_delim) == std::string::npos && s.find(stop_delim) == std::string::npos) { return ""; } auto first_split = Strings::Split(s, start_delim); if (!first_split.empty()) { std::string remaining_block = first_split[1]; auto second_split = Strings::Split(remaining_block, stop_delim); if (!second_split.empty()) { std::string between = second_split[0]; return between; } } return ""; } std::string::size_type Strings::SearchDelim(const std::string &haystack, const std::string &needle, const char deliminator) { // this shouldn't go out of bounds, even without obvious bounds checks auto pos = haystack.find(needle); while (pos != std::string::npos) { auto c = haystack[pos + needle.length()]; if ((c == '\0' || c == deliminator) && (pos == 0 || haystack[pos - 1] == deliminator)) { return pos; } pos = haystack.find(needle, pos + needle.length()); } return std::string::npos; } std::string Strings::Implode(std::string glue, std::vector src) { if (src.empty()) { return {}; } std::ostringstream output; std::vector::iterator src_iter; for (src_iter = src.begin(); src_iter != src.end(); src_iter++) { output << *src_iter << glue; } std::string final_output = output.str(); final_output.resize(output.str().size() - glue.size()); return final_output; } std::vector wrap(std::vector &src, std::string character) { std::vector new_vector; new_vector.reserve(src.size()); for (auto &e: src) { if (e == "null") { new_vector.emplace_back(e); continue; } new_vector.emplace_back(character + e + character); } return new_vector; } std::string Strings::Escape(const std::string &s) { std::string ret; size_t sz = s.length(); for (size_t i = 0; i < sz; ++i) { char c = s[i]; switch (c) { case '\x00': ret += "\\x00"; break; case '\n': ret += "\\n"; break; case '\r': ret += "\\r"; break; case '\\': ret += "\\\\"; break; case '\'': ret += "\\'"; break; case '\"': ret += "\\\""; break; case '\x1a': ret += "\\x1a"; break; default: ret.push_back(c); break; } } return ret; } bool Strings::IsNumber(const std::string &s) { try { auto r = stod(s); return true; } catch (std::exception &) { return false; } } std::string Strings::Join(const std::vector &ar, const std::string &delim) { std::string ret; for (size_t i = 0; i < ar.size(); ++i) { if (i != 0) { ret += delim; } ret += ar[i]; } return ret; } void Strings::FindReplace(std::string &string_subject, const std::string &search_string, const std::string &replace_string) { if (string_subject.find(search_string) == std::string::npos) { return; } size_t start_pos = 0; while ((start_pos = string_subject.find(search_string, start_pos)) != std::string::npos) { string_subject.replace(start_pos, search_string.length(), replace_string); start_pos += replace_string.length(); } } std::string Strings::Replace(std::string subject, const std::string &search, const std::string &replace) { size_t pos = 0; while ((pos = subject.find(search, pos)) != std::string::npos) { subject.replace(pos, search.length(), replace); pos += replace.length(); } return subject; } std::string Strings::Repeat(std::string s, int n) { std::string s1 = s; for (int i = 1; i < n; i++) { s += s1; } return s; } bool Strings::Contains(std::vector container, std::string element) { return std::find(container.begin(), container.end(), element) != container.end(); } std::string Strings::Commify(const std::string &number) { std::string temp_string; auto string_length = static_cast(number.length()); int i = 0; for (i = string_length - 3; i >= 0; i -= 3) { if (i > 0) { temp_string = "," + number.substr(static_cast(i), 3) + temp_string; } else { temp_string = number.substr(static_cast(i), 3) + temp_string; } } if (i < 0) { temp_string = number.substr(0, static_cast(3 + i)) + temp_string; } return temp_string; } const std::string Strings::ToLower(std::string s) { std::transform( s.begin(), s.end(), s.begin(), [](unsigned char c) { return ::tolower(c); } ); return s; } const std::string Strings::ToUpper(std::string s) { std::transform( s.begin(), s.end(), s.begin(), [](unsigned char c) { return ::toupper(c); } ); return s; } const std::string Strings::UcFirst(std::string s) { std::string output = s; if (!s.empty()) { output[0] = static_cast(::toupper(s[0])); } return output; } std::vector Strings::Wrap(std::vector &src, std::string character) { std::vector new_vector; new_vector.reserve(src.size()); for (auto &e: src) { if (e == "null") { new_vector.emplace_back(e); continue; } new_vector.emplace_back(character + e + character); } return new_vector; } std::string Strings::NumberToWords(unsigned long long int n) { // string to store word representation of given number std::string res; // this handles digits at ones & tens place res = Strings::ConvertToDigit((n % 100), ""); if (n > 100 && n % 100) { res = "and " + res; } // this handles digit at hundreds place res = Strings::ConvertToDigit(((n / 100) % 10), "Hundred ") + res; // this handles digits at thousands & tens thousands place res = Strings::ConvertToDigit(((n / 1000) % 100), "Thousand ") + res; // this handles digits at hundred thousands & one millions place res = Strings::ConvertToDigit(((n / 100000) % 100), "Lakh, ") + res; // this handles digits at ten millions & hundred millions place res = Strings::ConvertToDigit((n / 10000000) % 100, "Crore, ") + res; // this handles digits at ten millions & hundred millions place res = Strings::ConvertToDigit((n / 1000000000) % 100, "Billion, ") + res; return res; } std::string Strings::Money(uint32 platinum, uint32 gold, uint32 silver, uint32 copper) { std::string money_string = "Unknown"; if (copper && silver && gold && platinum) { // CSGP money_string = fmt::format( "{} Platinum, {} Gold, {} Silver, and {} Copper", Strings::Commify(std::to_string(platinum)), Strings::Commify(std::to_string(gold)), Strings::Commify(std::to_string(silver)), Strings::Commify(std::to_string(copper)) ); } else if (copper && silver && gold && !platinum) { // CSG money_string = fmt::format( "{} Gold, {} Silver, and {} Copper", Strings::Commify(std::to_string(gold)), Strings::Commify(std::to_string(silver)), Strings::Commify(std::to_string(copper)) ); } else if (copper && silver && !gold && !platinum) { // CS money_string = fmt::format( "{} Silver and {} Copper", Strings::Commify(std::to_string(silver)), Strings::Commify(std::to_string(copper)) ); } else if (!copper && silver && gold && platinum) { // SGP money_string = fmt::format( "{} Platinum, {} Gold, and {} Silver", Strings::Commify(std::to_string(platinum)), Strings::Commify(std::to_string(gold)), Strings::Commify(std::to_string(silver)) ); } else if (!copper && silver && gold && !platinum) { // SG money_string = fmt::format( "{} Gold and {} Silver", Strings::Commify(std::to_string(gold)), Strings::Commify(std::to_string(silver)) ); } else if (copper && !silver && gold && platinum) { // CGP money_string = fmt::format( "{} Platinum, {} Gold, and {} Copper", Strings::Commify(std::to_string(platinum)), Strings::Commify(std::to_string(gold)), Strings::Commify(std::to_string(copper)) ); } else if (copper && !silver && gold && !platinum) { // CG money_string = fmt::format( "{} Gold and {} Copper", Strings::Commify(std::to_string(gold)), Strings::Commify(std::to_string(copper)) ); } else if (!copper && !silver && gold && platinum) { // GP money_string = fmt::format( "{} Platinum and {} Gold", Strings::Commify(std::to_string(platinum)), Strings::Commify(std::to_string(gold)) ); } else if (!copper && !silver && !gold && platinum) { // P money_string = fmt::format( "{} Platinum", Strings::Commify(std::to_string(platinum)) ); } else if (!copper && !silver && gold && !platinum) { // G money_string = fmt::format( "{} Gold", Strings::Commify(std::to_string(gold)) ); } else if (!copper && silver && !gold && !platinum) { // S money_string = fmt::format( "{} Silver", Strings::Commify(std::to_string(silver)) ); } else if (copper && !silver && !gold && !platinum) { // C money_string = fmt::format( "{} Copper", Strings::Commify(std::to_string(copper)) ); } return money_string; } std::string Strings::SecondsToTime(int duration, bool is_milliseconds) { if (duration <= 0) { return "Unknown"; } if (is_milliseconds && duration < 1000) { return fmt::format( "{} Millisecond{}", duration, duration != 1 ? "s" : "" ); } int timer_length = ( is_milliseconds ? static_cast(std::ceil(static_cast(duration) / 1000.0f)) : duration ); int days = int(timer_length / 86400); timer_length %= 86400; int hours = int(timer_length / 3600); timer_length %= 3600; int minutes = int(timer_length / 60); timer_length %= 60; int seconds = timer_length; std::string time_string = "Unknown"; std::string day_string = (days == 1 ? "Day" : "Days"); std::string hour_string = (hours == 1 ? "Hour" : "Hours"); std::string minute_string = (minutes == 1 ? "Minute" : "Minutes"); std::string second_string = (seconds == 1 ? "Second" : "Seconds"); if (days && hours && minutes && seconds) { // DHMS time_string = fmt::format( "{} {}, {} {}, {} {}, and {} {}", days, day_string, hours, hour_string, minutes, minute_string, seconds, second_string ); } else if (days && hours && minutes && !seconds) { // DHM time_string = fmt::format( "{} {}, {} {}, and {} {}", days, day_string, hours, hour_string, minutes, minute_string ); } else if (days && hours && !minutes && seconds) { // DHS time_string = fmt::format( "{} {}, {} {}, and {} {}", days, day_string, hours, hour_string, seconds, second_string ); } else if (days && hours && !minutes && !seconds) { // DH time_string = fmt::format( "{} {} and {} {}", days, day_string, hours, hour_string ); } else if (days && !hours && minutes && seconds) { // DMS time_string = fmt::format( "{} {}, {} {}, and {} {}", days, day_string, minutes, minute_string, seconds, second_string ); } else if (days && !hours && minutes && !seconds) { // DM time_string = fmt::format( "{} {} and {} {}", days, day_string, minutes, minute_string ); } else if (days && !hours && !minutes && seconds) { // DS time_string = fmt::format( "{} {} and {} {}", days, day_string, seconds, second_string ); } else if (days && !hours && !minutes && !seconds) { // D time_string = fmt::format( "{} {}", days, day_string ); } else if (!days && hours && minutes && seconds) { // HMS time_string = fmt::format( "{} {}, {} {}, and {} {}", hours, hour_string, minutes, minute_string, seconds, second_string ); } else if (!days && hours && minutes && !seconds) { // HM time_string = fmt::format( "{} {} and {} {}", hours, hour_string, minutes, minute_string ); } else if (!days && hours && !minutes && seconds) { // HS time_string = fmt::format( "{} {} and {} {}", hours, hour_string, seconds, second_string ); } else if (!days && hours && !minutes && !seconds) { // H time_string = fmt::format( "{} {}", hours, hour_string ); } else if (!days && !hours && minutes && seconds) { // MS time_string = fmt::format( "{} {} and {} {}", minutes, minute_string, seconds, second_string ); } else if (!days && !hours && minutes && !seconds) { // M time_string = fmt::format( "{} {}", minutes, minute_string ); } else if (!days && !hours && !minutes && seconds) { // S time_string = fmt::format( "{} {}", seconds, second_string ); } return time_string; } std::string &Strings::LTrim(std::string &str, const std::string &chars) { str.erase(0, str.find_first_not_of(chars)); return str; } std::string Strings::MillisecondsToTime(int duration) { return SecondsToTime(duration, true); } std::string &Strings::RTrim(std::string &str, const std::string &chars) { str.erase(str.find_last_not_of(chars) + 1); return str; } std::string &Strings::Trim(std::string &str, const std::string &chars) { return LTrim(RTrim(str, chars), chars); } // Function to convert single digit or two digit number into words std::string Strings::ConvertToDigit(int n, std::string suffix) { // if n is zero if (n == 0) { return ""; } // split n if it is more than 19 if (n > 19) { return NUM_TO_ENGLISH_Y[n / 10] + NUM_TO_ENGLISH_X[n % 10] + suffix; } else { return NUM_TO_ENGLISH_X[n] + suffix; } }