#include "of_path.h" #include "of_str.h" #include #ifdef USE_BOOST_FILESYSTEM #include namespace fs = boost::filesystem; #else #include namespace fs = std::filesystem; #endif #ifdef _WIN32 #include #elif defined(__clang__) && defined(__APPLE__) #include #include #else #include #endif #ifndef PATH_MAX #define PATH_MAX 256 #endif namespace ofen { COfPath::COfPath() { } COfPath::~COfPath() { } bool COfPath::is_same_path(const ofString& pa, const ofString& pb) { return normalize(pa) == normalize(pb); } ofString COfPath::normalize(const ofString& path) { ofString normalized = COfStr::replace(path, ofT("\\"), ofT("/")); if (!normalized.empty() && normalized.back() == ofT('/')) { normalized.pop_back(); } return normalized; } ofString COfPath::get_full_path() { ofString path; #ifdef _WIN32 ofChar buffer[MAX_PATH]; DWORD length = GetModuleFileName(NULL, buffer, MAX_PATH); if (length == 0) { return ofT(""); } return ofString(buffer, length); #elif defined(__clang__) && defined(__APPLE__) uint32_t size = 0; _NSGetExecutablePath(NULL, &size); // 获取路径缓冲区的大小 std::vector buffer(size); // 创建缓冲区 if (_NSGetExecutablePath(buffer.data(), &size) != 0) { return ofT(""); } return ofString(buffer.data()); #else ofChar buffer[PATH_MAX]; ssize_t len = readlink("/proc/self/exe", buffer, sizeof(buffer) - 1); if (len == -1) { return ofT(""); } buffer[len] = ofT('\0'); // 确保字符串以null终止 return ofString(buffer); #endif } ofString COfPath::get_home() { #if defined(_WIN32) ofChar* value = nullptr; std::size_t len = 0; // _dupenv_s() 在 Visual Studio 2008 的 CRT (msvcr90) 中引入的,似乎没有进入系统 CRT (msvcrt)。 // mingw-w64 GCC 通常默认只链接到系统 CRT,所以所以找不到这个符号。 #if defined(__MINGW32__) || defined(__MINGW64__) #ifdef UNICODE_OFSTR ofChar* homedir = _wgetenv(ofT("USERPROFILE")); #else ofChar* homedir = getenv("USERPROFILE"); #endif if (homedir) { return ofString(homedir); } return ofT(""); #else #ifdef UNICODE_OFSTR auto err = _wdupenv_s(&value, &len, ofT("USERPROFILE")); #else auto err = _dupenv_s(&value, &len, "USERPROFILE"); #endif if (err == 0 && value != nullptr) { ofString ret(value); free(value); return ret; } else { return ofT(""); } #endif #else ofChar* homedir = getenv("HOME"); if (homedir) { return ofString(homedir); } return ofT(""); #endif } ofString COfPath::get_config_dir(const ofString& sub_dir, bool create) { fs::path userHome = fs::path(get_home()); userHome.append(".config"); userHome.append(sub_dir); if (create) { if (!fs::exists(userHome)) { fs::create_directories(userHome); } } #ifdef UNICODE_OFSTR return ofString(userHome.wstring()); #else return ofString(userHome.string()); #endif } ofString COfPath::get_full(const ofString& path, const ofString& sub_file_path) { fs::path p(path); p.append(sub_file_path); #ifdef UNICODE_OFSTR return ofString(p.wstring()); #else return ofString(p.string()); #endif } bool COfPath::exist(const ofString& path) { fs::path p(path); return fs::exists(p); } bool COfPath::write(const ofString& path, const char* data, int len) { FILE* f = nullptr; #ifdef UNICODE_OFSTR f = _wfopen(path.c_str(), ofT("wb")); #else f = fopen(path.c_str(), ofT("wb")); #endif if (!f) { return false; } fwrite(data, 1, len, f); fclose(f); return true; } ofString COfPath::to_full(const ofString& path) { fs::path base; if (fs::path(path).is_relative()) { base = fs::current_path(); base.append(path); } else { base = fs::path(path); } fs::path ret = fs::absolute(base); #ifdef UNICODE_OFSTR return ofString(ret.wstring()); #else return ofString(ret.string()); #endif } } // namespace ofen