space-game001/src/utils/Utils.cpp
2026-02-08 22:38:24 +03:00

208 lines
5.8 KiB
C++

#include "utils/Utils.h"
#include <cstring>
#include <iterator>
#include <vector>
#include <iostream>
#include <algorithm>
#include <fstream>
#include <zip.h>
#include <cstdlib>
#include <filesystem>
#include <string>
#include <cctype>
#include <SDL.h>
#ifdef __ANDROID__
#include <android/log.h>
#endif
namespace ZL
{
std::string readTextFile(const std::string &filename) {
#ifdef __ANDROID__
SDL_RWops* file = SDL_RWFromFile(filename.c_str(), "rb");
if (!file) {
#ifdef DEBUG
__android_log_print(ANDROID_LOG_ERROR, "Utils",
"Failed to open: %s", filename.c_str());
#endif
return "";
}
Sint64 size = SDL_RWsize(file);
if (size <= 0) {
SDL_RWclose(file);
return "";
}
std::string content(size, '\0');
if (SDL_RWread(file, &content[0], size, 1) != 1) {
SDL_RWclose(file);
return "";
}
SDL_RWclose(file);
return content;
#else
std::ifstream f(filename);
if (!f.is_open()) {
return "";
}
return std::string((std::istreambuf_iterator<char>(f)),
std::istreambuf_iterator<char>());
#endif
}
std::vector<char> readFile(const std::string &filename) {
#ifdef __ANDROID__
SDL_RWops* file = SDL_RWFromFile(filename.c_str(), "rb");
if (!file) {
return {};
}
Sint64 size = SDL_RWsize(file);
if (size <= 0) {
SDL_RWclose(file);
return {};
}
std::vector<char> data(size);
if (SDL_RWread(file, data.data(), size, 1) != 1) {
SDL_RWclose(file);
return {};
}
SDL_RWclose(file);
return data;
#else
std::ifstream file(filename, std::ios::binary | std::ios::ate);
if (!file) {
return {};
}
std::streamsize size = file.tellg();
if (size <= 0) {
return {};
}
file.seekg(0, std::ios::beg);
std::vector<char> buffer(size);
if (!file.read(buffer.data(), size)) {
return {};
}
return buffer;
#endif
}
std::vector<char> readFileFromZIP(const std::string& filename, const std::string& zipfilename) {
#ifdef EMSCRIPTEN
int zipErr = 0;
zip_t* archive = zip_open(zipfilename.c_str(), ZIP_RDONLY, &zipErr);
if (!archive) {
std::cout << "Failed to open ZIP: " << zipfilename << " (error code " << zipErr << ")" << std::endl;
throw std::runtime_error("Failed to open ZIP: " + zipfilename);
}
std::string cleanFilename = filename;
if (cleanFilename.rfind("./", 0) == 0) cleanFilename = cleanFilename.substr(2);
zip_stat_t fileStat;
zip_stat_init(&fileStat);
if (zip_stat(archive, cleanFilename.c_str(), 0, &fileStat) != 0 || !(fileStat.valid & ZIP_STAT_SIZE)) {
zip_close(archive);
std::cout << "Failed to stat file in ZIP: " << cleanFilename << " in " << zipfilename << std::endl;
throw std::runtime_error("Can't stat file in ZIP: " + cleanFilename);
}
zip_file_t* zipFile = zip_fopen(archive, cleanFilename.c_str(), 0);
if (!zipFile) {
zip_close(archive);
std::cout << "Failed to open file in ZIP: " << cleanFilename << std::endl;
throw std::runtime_error("Can't open file in ZIP: " + cleanFilename);
}
std::vector<char> fileData(static_cast<size_t>(fileStat.size));
zip_int64_t bytesRead = zip_fread(zipFile, fileData.data(), fileStat.size);
// Обязательно закрываем всё перед проверкой результата или throw
zip_fclose(zipFile);
zip_close(archive);
if (bytesRead < 0 || static_cast<zip_uint64_t>(bytesRead) != fileStat.size) {
std::cout << "Failed to read file from ZIP: " << cleanFilename << " (bytes read: " << bytesRead << ", expected: " << fileStat.size << ")" << std::endl;
throw std::runtime_error("Error reading data from ZIP: " + cleanFilename);
}
return fileData;
#else
if (zipfilename.empty()) {
std::cerr << "readFileFromZIP: zipfilename empty" << std::endl;
return {};
}
int zipErr = 0;
zip_t* archive = zip_open(zipfilename.c_str(), ZIP_RDONLY, &zipErr);
if (!archive) {
std::cerr << "readFileFromZIP: zip_open failed for: " << zipfilename
<< " (error code " << zipErr << ")" << std::endl;
return {};
}
std::string cleanFilename = filename;
if (cleanFilename.rfind("./", 0) == 0) {
cleanFilename = cleanFilename.substr(2);
}
zip_stat_t fileStat;
if (zip_stat(archive, cleanFilename.c_str(), 0, &fileStat) != 0) {
std::cerr << "readFileFromZIP: file not found in ZIP: " << cleanFilename
<< " in " << zipfilename << std::endl;
zip_close(archive);
return {};
}
zip_file_t* zipFile = zip_fopen(archive, cleanFilename.c_str(), 0);
if (!zipFile) {
std::cerr << "readFileFromZIP: zip_fopen failed for " << cleanFilename << std::endl;
zip_close(archive);
return {};
}
std::vector<char> fileData;
fileData.resize(static_cast<size_t>(fileStat.size));
zip_int64_t readBytes = zip_fread(zipFile, fileData.data(), static_cast<zip_uint64_t>(fileData.size()));
if (readBytes < 0) {
std::cerr << "readFileFromZIP: zip_fread failed for " << cleanFilename << std::endl;
zip_fclose(zipFile);
zip_close(archive);
return {};
}
zip_fclose(zipFile);
zip_close(archive);
return fileData;
#endif
}
bool findString(const char* in, char* list)
{
size_t thisLength = strlen(in);
while (*list != 0)
{
size_t length = strcspn(list, " ");
if (thisLength == length)
if (!strncmp(in, list, length))
return true;
list += length;
list += 1;
}
return false;
}
};