/
erlang.spawn
/
fallout2-ce
Обзор
Документация
Войти
/
erlang.spawn
/
fallout2-ce
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
continious
src/platform_compat.cc
452 строки
10 KB
Mike Klaas
Better fix for directory detection (#486)
06 июн 2026, 06:24
Не верифицирован
06 июн 2026, 06:24
1afe925
Код
Авторство
О чём код?
#include "platform_compat.h" #include <string.h> #ifdef _WIN32 #include <direct.h> #include <io.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #else #include <dirent.h> #include <sys/stat.h> #include <unistd.h> #endif #ifdef _WIN32 #include <windows.h> #ifdef _WIN64 #include <timeapi.h> #else #include <mmsystem.h> #endif #else #include <chrono> #endif #include <SDL.h> namespace fallout { static void compat_prepare_native_path(char* nativePath, const char* path) { strncpy(nativePath, path, COMPAT_MAX_PATH - 1); nativePath[COMPAT_MAX_PATH - 1] = '\0'; compat_windows_path_to_native(nativePath); compat_resolve_path(nativePath); } int compat_stricmp(const char* string1, const char* string2) { return SDL_strcasecmp(string1, string2); } int compat_strnicmp(const char* string1, const char* string2, size_t size) { return SDL_strncasecmp(string1, string2, size); } char* compat_strupr(char* string) { return SDL_strupr(string); } char* compat_strlwr(char* string) { return SDL_strlwr(string); } char* compat_itoa(int value, char* buffer, int radix) { return SDL_itoa(value, buffer, radix); } void compat_splitpath(const char* path, char* drive, char* dir, char* fname, char* ext) { #ifdef _WIN32 _splitpath(path, drive, dir, fname, ext); #else const char* driveStart = path; if (path[0] == '/' && path[1] == '/') { path += 2; while (*path != '\0' && *path != '/' && *path != '.') { path++; } } if (drive != nullptr) { size_t driveSize = path - driveStart; if (driveSize > COMPAT_MAX_DRIVE - 1) { driveSize = COMPAT_MAX_DRIVE - 1; } strncpy(drive, path, driveSize); drive[driveSize] = '\0'; } const char* dirStart = path; const char* fnameStart = path; const char* extStart = nullptr; const char* end = path; while (*end != '\0') { if (*end == '/') { fnameStart = end + 1; } else if (*end == '.') { extStart = end; } end++; } if (extStart == nullptr) { extStart = end; } if (dir != nullptr) { size_t dirSize = fnameStart - dirStart; if (dirSize > COMPAT_MAX_DIR - 1) { dirSize = COMPAT_MAX_DIR - 1; } strncpy(dir, path, dirSize); dir[dirSize] = '\0'; } if (fname != nullptr) { size_t fileNameSize = extStart - fnameStart; if (fileNameSize > COMPAT_MAX_FNAME - 1) { fileNameSize = COMPAT_MAX_FNAME - 1; } strncpy(fname, fnameStart, fileNameSize); fname[fileNameSize] = '\0'; } if (ext != nullptr) { size_t extSize = end - extStart; if (extSize > COMPAT_MAX_EXT - 1) { extSize = COMPAT_MAX_EXT - 1; } strncpy(ext, extStart, extSize); ext[extSize] = '\0'; } #endif } void compat_makepath(char* path, const char* drive, const char* dir, const char* fname, const char* ext) { #ifdef _WIN32 _makepath(path, drive, dir, fname, ext); #else path[0] = '\0'; if (drive != nullptr) { if (*drive != '\0') { strcpy(path, drive); path = strchr(path, '\0'); if (path[-1] == '/') { path--; } else { *path = '/'; } } } if (dir != nullptr) { if (*dir != '\0') { if (*dir != '/' && *path == '/') { path++; } strcpy(path, dir); path = strchr(path, '\0'); if (path[-1] == '/') { path--; } else { *path = '/'; } } } if (fname != nullptr && *fname != '\0') { if (*fname != '/' && *path == '/') { path++; } strcpy(path, fname); path = strchr(path, '\0'); } else { if (*path == '/') { path++; } } if (ext != nullptr) { if (*ext != '\0') { if (*ext != '.') { *path++ = '.'; } strcpy(path, ext); path = strchr(path, '\0'); } } *path = '\0'; #endif } long compat_tell(int fd) { return lseek(fd, 0, SEEK_CUR); } long compat_filelength(int fd) { long originalOffset = lseek(fd, 0, SEEK_CUR); lseek(fd, 0, SEEK_SET); long filesize = lseek(fd, 0, SEEK_END); lseek(fd, originalOffset, SEEK_SET); return filesize; } int compat_mkdir(const char* path) { char nativePath[COMPAT_MAX_PATH]; compat_prepare_native_path(nativePath, path); #ifdef _WIN32 return mkdir(nativePath); #else return mkdir(nativePath, 0755); #endif } int compat_mkdir_recursive(const char* path) { char drive[COMPAT_MAX_DRIVE]; compat_splitpath(path, drive, nullptr, nullptr, nullptr); char pathCopy[COMPAT_MAX_PATH]; strcpy(pathCopy, path); // Skip drive root (e.g. "C:\\" or leading "/") to avoid mkdir("") or mkdir("C:"). char* sep = pathCopy + strlen(drive); if (*sep == '\\' || *sep == '/') sep++; for (; *sep != '\0'; sep++) { if (*sep == '\\' || *sep == '/') { char saved = *sep; *sep = '\0'; if (compat_mkdir(pathCopy) < 0) { break; } *sep = saved; } } return compat_mkdir(path); } bool compat_is_dir(const char* path) { char nativePath[COMPAT_MAX_PATH]; compat_prepare_native_path(nativePath, path); #ifdef _WIN32 struct _stat info; if (_stat(nativePath, &info) != 0) { return false; } return (info.st_mode & _S_IFDIR) != 0; #else struct stat info; if (stat(nativePath, &info) != 0) { return false; } return S_ISDIR(info.st_mode); #endif } bool compat_file_exists(const char* filePath) { char nativePath[COMPAT_MAX_PATH]; compat_prepare_native_path(nativePath, filePath); #ifdef _WIN32 struct _stat info; if (_stat(nativePath, &info) != 0) { return false; } return (info.st_mode & _S_IFDIR) == 0; #else struct stat info; if (stat(nativePath, &info) != 0) { return false; } return !S_ISDIR(info.st_mode); #endif } unsigned int compat_timeGetTime() { #ifdef _WIN32 return timeGetTime(); #else static auto start = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now(); return static_cast<unsigned int>(std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count()); #endif } FILE* compat_fopen(const char* path, const char* mode) { char nativePath[COMPAT_MAX_PATH]; compat_prepare_native_path(nativePath, path); return fopen(nativePath, mode); } gzFile compat_gzopen(const char* path, const char* mode) { char nativePath[COMPAT_MAX_PATH]; compat_prepare_native_path(nativePath, path); return gzopen(nativePath, mode); } char* compat_fgets(char* buffer, int maxCount, FILE* stream) { buffer = fgets(buffer, maxCount, stream); if (buffer != nullptr) { size_t len = strlen(buffer); if (len >= 2 && buffer[len - 1] == '\n' && buffer[len - 2] == '\r') { buffer[len - 2] = '\n'; buffer[len - 1] = '\0'; } } return buffer; } char* compat_gzgets(gzFile stream, char* buffer, int maxCount) { buffer = gzgets(stream, buffer, maxCount); if (buffer != nullptr) { size_t len = strlen(buffer); if (len >= 2 && buffer[len - 1] == '\n' && buffer[len - 2] == '\r') { buffer[len - 2] = '\n'; buffer[len - 1] = '\0'; } } return buffer; } int compat_remove(const char* path) { char nativePath[COMPAT_MAX_PATH]; compat_prepare_native_path(nativePath, path); return remove(nativePath); } int compat_rename(const char* oldFileName, const char* newFileName) { char nativeOldFileName[COMPAT_MAX_PATH]; compat_prepare_native_path(nativeOldFileName, oldFileName); char nativeNewFileName[COMPAT_MAX_PATH]; compat_prepare_native_path(nativeNewFileName, newFileName); return rename(nativeOldFileName, nativeNewFileName); } void compat_windows_path_to_native(char* path) { #ifndef _WIN32 char* pch = path; while (*pch != '\0') { if (*pch == '\\') { *pch = '/'; } pch++; } #endif } void compat_resolve_path(char* path) { #ifndef _WIN32 char* pch = path; DIR* dir; if (pch[0] == '/') { dir = opendir("/"); pch++; } else { dir = opendir("."); } while (dir != nullptr) { char* sep = strchr(pch, '/'); size_t length; if (sep != nullptr) { length = sep - pch; } else { length = strlen(pch); } bool found = false; struct dirent* entry = readdir(dir); while (entry != nullptr) { if (strlen(entry->d_name) == length && compat_strnicmp(pch, entry->d_name, length) == 0) { strncpy(pch, entry->d_name, length); found = true; break; } entry = readdir(dir); } closedir(dir); dir = nullptr; if (!found) { break; } if (sep == nullptr) { break; } *sep = '\0'; dir = opendir(path); *sep = '/'; pch = sep + 1; } #endif } int compat_access(const char* path, int mode) { char nativePath[COMPAT_MAX_PATH]; compat_prepare_native_path(nativePath, path); return access(nativePath, mode); } char* compat_strdup(const char* string) { return SDL_strdup(string); } // It's a replacement for compat_filelength(fileno(stream)) on platforms without // fileno defined. long getFileSize(FILE* stream) { long originalOffset = ftell(stream); fseek(stream, 0, SEEK_END); long filesize = ftell(stream); fseek(stream, originalOffset, SEEK_SET); return filesize; } } // namespace fallout