#include "util.h" #include #include #include #include #include #if defined(__APPLE__) && defined(__MACH__) #include #include #endif #if !defined(_WIN32) #include #include #endif bool ends_with(const std::string& str, const std::string& ending) { if (str.length() >= ending.length()) { return (str.compare(str.length() - ending.length(), ending.length(), ending) == 0); } else { return false; } } bool starts_with(const std::string& str, const std::string& start) { if (str.find(start) == 0) { return true; } return false; } void replace_all_chars(std::string& str, char target, char replacement) { for (size_t i = 0; i < str.length(); ++i) { if (str[i] == target) { str[i] = replacement; } } } std::string format(const char* fmt, ...) { va_list ap; va_list ap2; va_start(ap, fmt); va_copy(ap2, ap); int size = vsnprintf(NULL, 0, fmt, ap); std::vector buf(size + 1); int size2 = vsnprintf(buf.data(), size + 1, fmt, ap2); va_end(ap2); va_end(ap); return std::string(buf.data(), size); } #ifdef _WIN32 // code for windows #include bool file_exists(const std::string& filename) { DWORD attributes = GetFileAttributesA(filename.c_str()); return (attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY)); } bool is_directory(const std::string& path) { DWORD attributes = GetFileAttributesA(path.c_str()); return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY)); } #else // Unix #include #include bool file_exists(const std::string& filename) { struct stat buffer; return (stat(filename.c_str(), &buffer) == 0 && S_ISREG(buffer.st_mode)); } bool is_directory(const std::string& path) { struct stat buffer; return (stat(path.c_str(), &buffer) == 0 && S_ISDIR(buffer.st_mode)); } #endif // get_num_physical_cores is copy from // https://github.com/ggerganov/llama.cpp/blob/master/examples/common.cpp // LICENSE: https://github.com/ggerganov/llama.cpp/blob/master/LICENSE int32_t get_num_physical_cores() { #ifdef __linux__ // enumerate the set of thread siblings, num entries is num cores std::unordered_set siblings; for (uint32_t cpu = 0; cpu < UINT32_MAX; ++cpu) { std::ifstream thread_siblings("/sys/devices/system/cpu" + std::to_string(cpu) + "/topology/thread_siblings"); if (!thread_siblings.is_open()) { break; // no more cpus } std::string line; if (std::getline(thread_siblings, line)) { siblings.insert(line); } } if (siblings.size() > 0) { return static_cast(siblings.size()); } #elif defined(__APPLE__) && defined(__MACH__) int32_t num_physical_cores; size_t len = sizeof(num_physical_cores); int result = sysctlbyname("hw.perflevel0.physicalcpu", &num_physical_cores, &len, NULL, 0); if (result == 0) { return num_physical_cores; } result = sysctlbyname("hw.physicalcpu", &num_physical_cores, &len, NULL, 0); if (result == 0) { return num_physical_cores; } #elif defined(_WIN32) // TODO: Implement #endif unsigned int n_threads = std::thread::hardware_concurrency(); return n_threads > 0 ? (n_threads <= 4 ? n_threads : n_threads / 2) : 4; } std::string basename(const std::string& path) { size_t pos = path.find_last_of('/'); if (pos != std::string::npos) { return path.substr(pos + 1); } pos = path.find_last_of('\\'); if (pos != std::string::npos) { return path.substr(pos + 1); } return path; } std::string path_join(const std::string& p1, const std::string& p2) { if (p1.empty()) { return p2; } if (p2.empty()) { return p1; } if (p1[p1.length() - 1] == '/' || p1[p1.length() - 1] == '\\') { return p1 + p2; } return p1 + "/" + p2; } static SDLogLevel log_level = SDLogLevel::INFO; void set_sd_log_level(SDLogLevel level) { log_level = level; } void log_printf(SDLogLevel level, const char* file, int line, const char* format, ...) { if (level < log_level) { return; } va_list args; va_start(args, format); if (level == SDLogLevel::DEBUG) { printf("[DEBUG] %s:%-4d - ", basename(file).c_str(), line); vprintf(format, args); printf("\n"); fflush(stdout); } else if (level == SDLogLevel::INFO) { printf("[INFO] %s:%-4d - ", basename(file).c_str(), line); vprintf(format, args); printf("\n"); fflush(stdout); } else if (level == SDLogLevel::WARN) { fprintf(stdout, "[WARN] %s:%-4d - ", basename(file).c_str(), line); vfprintf(stdout, format, args); fprintf(stdout, "\n"); fflush(stdout); } else { fprintf(stderr, "[ERROR] %s:%-4d - ", basename(file).c_str(), line); vfprintf(stderr, format, args); fprintf(stderr, "\n"); fflush(stderr); } va_end(args); }