187 lines
5.1 KiB
C++
187 lines
5.1 KiB
C++
#include "util.h"
|
|
|
|
#include <stdarg.h>
|
|
#include <fstream>
|
|
#include <thread>
|
|
#include <unordered_set>
|
|
#include <vector>
|
|
|
|
#if defined(__APPLE__) && defined(__MACH__)
|
|
#include <sys/sysctl.h>
|
|
#include <sys/types.h>
|
|
#endif
|
|
|
|
#if !defined(_WIN32)
|
|
#include <sys/ioctl.h>
|
|
#include <unistd.h>
|
|
#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<char> 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 <windows.h>
|
|
|
|
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 <dirent.h>
|
|
#include <sys/stat.h>
|
|
|
|
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<std::string> 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<int32_t>(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);
|
|
}
|