#include "utils.h" #include #include #include /** * Clean up the trailing ../ in __FILE__ * * This is used by the logging macro. * * @param filepath * @return const char* */ const char *trim_path(const char *filepath) { if (strncmp(filepath, "../", 3) == 0) { filepath += 3; } return filepath; } #include bool file_exists(const std::string &name) { std::ifstream f(name.c_str()); return f.good(); } bool replace(std::string &str, const std::string &from, const std::string &to) { size_t start_pos = str.find(from); if (start_pos == std::string::npos) return false; do { str.replace(start_pos, from.length(), to); } while ((start_pos = str.find(from)) != std::string::npos); return true; } bool replace(std::string &str, const char *from, const char *to) { size_t start_pos = str.find(from); if (start_pos == std::string::npos) return false; do { str.replace(start_pos, strlen(from), to); } while ((start_pos = str.find(from)) != std::string::npos); return true; } void ansi_clean(std::string &str) { static std::regex ansi_cleaner("\x1b\[[0-9;]*[A-Zmh]", std::regex_constants::ECMAScript); str = std::regex_replace(str, ansi_cleaner, ""); } void high_ascii(std::string &str) { // the + replaces all of them into one. I want each high ascii replaced with // #. static std::regex high_cleaner("[\x80-\xff]", std::regex_constants::ECMAScript); str = std::regex_replace(str, high_cleaner, "#"); } std::smatch ansi_newline(const std::string &str) { static std::regex ansi_nl("\x1b\[[0-9;]*[JK]", std::regex_constants::ECMAScript); std::smatch m; std::regex_search(str, m, ansi_nl); return m; } std::string repr(const std::string &source) { std::string output = source; replace(output, "\n", "\\n"); replace(output, "\r", "\\r"); replace(output, "\b", "\\b"); replace(output, "\x1b", "\\["); high_ascii(output); return output; } std::string clean_string(const std::string &source) { std::string clean = source; /* replace(clean, "\n", "\\n"); replace(clean, "\r", "\\r"); replace(clean, "\b", "\\b"); replace(clean, "\x1b", "\\["); */ replace(clean, "\n", ""); replace(clean, "\r", ""); // ANSI too ansi_clean(clean); // BUGZ_LOG(error) << "cleaned: " << clean; high_ascii(clean); // replace(clean, "\x1b", "^"); return clean; } std::vector split(const std::string &line) { static std::regex rx_split("[^\\s]+"); std::vector results; for (auto it = std::sregex_iterator(line.begin(), line.end(), rx_split); it != std::sregex_iterator(); ++it) { results.push_back(it->str()); } return results; } std::vector split(const std::string &line, const std::string &by) { std::string work = line; std::vector results; size_t pos; while ((pos = work.find(by)) != std::string::npos) { results.push_back(work.substr(0, pos)); work.erase(0, pos + by.length()); } if (!work.empty()) results.push_back(work); return results; } bool in(const std::string &line, const std::string &has) { return (line.find(has) != std::string::npos); } bool startswith(const std::string &line, const std::string &has) { return (line.substr(0, has.length()) == has); } bool endswith(const std::string &line, const std::string &has) { if (line.length() < has.length()) return false; return (line.substr(line.length() - has.length()) == has); } void trim(std::string &str) { while (str.substr(0, 1) == " ") str.erase(0, 1); while (str.substr(str.length() - 1) == " ") str.erase(str.length() - 1); } bool at_command_prompt(const std::string &prompt) { if (startswith(prompt, "Command [")) if (endswith(prompt, "] (?=Help)? : ")) return true; return false; } bool at_computer_prompt(const std::string &prompt) { if (startswith(prompt, "Computer command [")) if (endswith(prompt, "] (?=Help)? ")) return true; return false; } bool at_planet_prompt(const std::string &prompt) { if (startswith(prompt, "Planet command (?=Help)")) if (endswith(prompt, " [D] ")) return true; return false; } bool density_clear(int sector, int density, int navhaz) { if(sector == 0) return false; //if(anomoly) return false; /* http://wiki.classictw.com/index.php?title=Gypsy%27s_Big_Dummy%27s_Guide_to_TradeWars_Text#Trader_Information Density Readings: 0 = Empty Sector or Ferrengi Dreadanought 1 = Marker Beacon 2 = Limpet Type 2 Tracking Mine 5 = Fighter (per Fighter) 10 = Armid Type 1 Mine 21 = Navigation Hazard (Per 1 Percent) 21 = Destroyed Ship (Due to 1 Percent Nav-Haz) 38 = Unmanned Ship 40 = Manned Ship, Alien or Ferrengi Assault Trader 50 = Destroyed Starport (After 25 Percent Nav-Haz Clears) 100 = Starport or Ferrengi Battle Cruiser 210 = Destroyed Planet (Due to 10 Percent Nav-Haz) 462 = Federation Starship under Admiral Nelson 489 = Federation Starship under Captain Zyrain 500 = Planet 512 = Federation Starship under Admiral Clausewitz 575 = Destroyed Port (Before 25% Nav-Haz Clears) */ int dense = density; if((navhaz != 0) && (navhaz <= 5)) { // Adjust density by upto 5% navhaz, exlude greather than 5% dense -= navhaz * 21; } if(navhaz > 5) return false; switch (dense) { case 0: case 1: case 100: case 101: return true; } // Special case for Sector 001. if((sector == 1) && (dense == 601)) return true; return false; } #include #include void str_toupper(std::string &str) { std::transform(str.begin(), str.end(), str.begin(), ::toupper); } void str_tolower(std::string &str) { std::transform(str.begin(), str.end(), str.begin(), ::tolower); } void remove_telnet_commands(std::string &text) { size_t pos; while ((pos = text.find('\xff')) != std::string::npos) { text.erase(pos, pos + 3); } } int sstoi(const std::string &text, int failure) { int result; try { result = stoi(text); } catch (const std::invalid_argument &e) { // BUGZ_LOG(fatal) << e.what(); return failure; } catch (const std::out_of_range &e) { // BUGZ_LOG(fatal) << e.what(); return failure; } return result; }