GroveEngine/tests/helpers/SystemUtils.cpp
StillHammer e004bc015b feat: Windows portage + Phase 4 SceneCollector integration
- Port to Windows (MinGW/Ninja):
  - ModuleFactory/ModuleLoader: LoadLibrary/GetProcAddress
  - SystemUtils: Windows process memory APIs
  - FileWatcher: st_mtime instead of st_mtim
  - IIO.h: add missing #include <cstdint>
  - Tests (09, 10, 11): grove_dlopen/dlsym wrappers

- Phase 4 - SceneCollector & IIO:
  - Implement view/proj matrix calculation in parseCamera()
  - Add IIO routing test with game→renderer pattern
  - test_22_bgfx_sprites_headless: 5 tests, 23 assertions pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 09:48:14 +08:00

159 lines
4.2 KiB
C++

#include "SystemUtils.h"
#include <fstream>
#include <string>
#include <sstream>
#include <cstring>
#include <filesystem>
#ifdef _WIN32
#include <windows.h>
#include <psapi.h>
#else
#include <dirent.h>
#include <glob.h>
#endif
namespace grove {
size_t getCurrentMemoryUsage() {
#ifdef _WIN32
PROCESS_MEMORY_COUNTERS pmc;
if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
return pmc.WorkingSetSize;
}
return 0;
#else
// Linux: /proc/self/status -> VmRSS
std::ifstream file("/proc/self/status");
std::string line;
while (std::getline(file, line)) {
if (line.substr(0, 6) == "VmRSS:") {
std::istringstream iss(line.substr(7));
size_t kb;
iss >> kb;
return kb * 1024; // Convert to bytes
}
}
return 0;
#endif
}
int getOpenFileDescriptors() {
#ifdef _WIN32
// Windows: Not easily available, return 0
return 0;
#else
// Linux: /proc/self/fd
int count = 0;
DIR* dir = opendir("/proc/self/fd");
if (dir) {
struct dirent* entry;
while ((entry = readdir(dir)) != nullptr) {
count++;
}
closedir(dir);
}
return count - 2; // Exclude . and ..
#endif
}
float getCurrentCPUUsage() {
// Simplifié - retourne 0 pour l'instant
// Implémentation complète nécessite tracking du /proc/self/stat
// entre deux lectures (utime + stime delta)
return 0.0f;
}
int countTempFiles(const std::string& pattern) {
#ifdef _WIN32
// Windows: Use std::filesystem to count matching files
int count = 0;
try {
std::filesystem::path dirPath = std::filesystem::path(pattern).parent_path();
std::string filename = std::filesystem::path(pattern).filename().string();
// Simple pattern matching - just count files starting with the prefix
// This is a simplification; for full glob support, use a library
if (std::filesystem::exists(dirPath)) {
for (const auto& entry : std::filesystem::directory_iterator(dirPath)) {
if (entry.is_regular_file()) {
std::string name = entry.path().filename().string();
// Check if name starts with the pattern prefix (before *)
size_t starPos = filename.find('*');
if (starPos != std::string::npos) {
std::string prefix = filename.substr(0, starPos);
if (name.find(prefix) == 0) {
count++;
}
}
}
}
}
} catch (...) {
// Ignore errors
}
return count;
#else
glob_t globResult;
memset(&globResult, 0, sizeof(globResult));
int result = glob(pattern.c_str(), GLOB_TILDE, nullptr, &globResult);
if (result != 0) {
globfree(&globResult);
return 0;
}
int count = globResult.gl_pathc;
globfree(&globResult);
return count;
#endif
}
int getMappedLibraryCount() {
#ifdef _WIN32
// Windows: Count loaded modules
HMODULE hMods[1024];
DWORD cbNeeded;
int count = 0;
if (EnumProcessModules(GetCurrentProcess(), hMods, sizeof(hMods), &cbNeeded)) {
count = cbNeeded / sizeof(HMODULE);
}
return count;
#else
// Count unique .so libraries in /proc/self/maps
std::ifstream file("/proc/self/maps");
std::string line;
int count = 0;
std::string lastLib;
while (std::getline(file, line)) {
// Look for lines containing ".so"
size_t soPos = line.find(".so");
if (soPos != std::string::npos) {
// Extract library path (after last space)
size_t pathStart = line.rfind(' ');
if (pathStart != std::string::npos) {
std::string libPath = line.substr(pathStart + 1);
// Only count if different from last one (avoid duplicates)
if (libPath != lastLib) {
count++;
lastLib = libPath;
}
}
}
}
return count;
#endif
}
} // namespace grove