FileHandler.cpp h - JulianKerignard/ProjetJeuDeLaVie_POO GitHub Wiki

Bien sûr ! Voici la documentation complète pour les fichiers FileHandler.cpp et FileHandler.h, expliquant les classes et les fonctions présentes dans ces fichiers.

Fichier FileHandler.h

#ifndef FILE_HANDLER_H
#define FILE_HANDLER_H

#include "Grid.h"
#include <string>
#include <utility>
#include <vector>

// Énumération pour les différents formats de fichier
enum class FileFormat {
    TXT,     // Format texte
    CELLS,   // Format cells
    UNKNOWN  // Format inconnu
};

// Classe de gestion des fichiers pour le Jeu de la Vie
class FileHandler {
private:
    static const int DEFAULT_CELLS_WIDTH;   // Largeur par défaut pour les fichiers .cells
    static const int DEFAULT_CELLS_HEIGHT;  // Hauteur par défaut pour les fichiers .cells

    // Méthodes privées de gestion des formats de fichier
    static FileFormat getFileFormat(const std::string& path);
    static Grid loadTxtFile(const std::string& path);
    static Grid loadCellsFile(const std::string& path);
    static std::pair<int, int> parseGridDimensions(const std::string& line);
    static bool validateTxtFormat(const std::string& content);
    static bool validateCellsFormat(const std::string& content);

public:
    // Méthodes principales de chargement et sauvegarde des grilles
    static Grid loadGridFromFile(const std::string& path);
    static void loadGridFromFile(const std::string& path, Grid& grid);
    static void saveGridToFile(const Grid& grid, const std::string& path);

    // Méthodes de chargement spécifiques aux différents formats
    static void loadTxtFile(const std::string& path, Grid& grid);
    static void loadCellsFile(const std::string& path, Grid& grid);

    // Nouvelle méthode publique pour valider le format des fichiers
    bool validateFileFormat(const std::string& content);
};

#endif // FILE_HANDLER_H

Documentation des Membres

  • Enumération FileFormat :

    • Détermine les différents formats de fichiers supportés.
    • TXT : Format texte.
    • CELLS : Format cells.
    • UNKNOWN : Format inconnu.
  • Classe FileHandler :

    • Gère la lecture et l'écriture des fichiers de configuration pour la grille du Jeu de la Vie.

    • Membres privés :

      • static const int DEFAULT_CELLS_WIDTH : Largeur par défaut pour les fichiers .cells.
      • static const int DEFAULT_CELLS_HEIGHT : Hauteur par défaut pour les fichiers .cells.
      • static FileFormat getFileFormat(const std::string& path) : Détermine le format du fichier en fonction de son extension.
      • static Grid loadTxtFile(const std::string& path) : Charge une grille à partir d'un fichier .txt.
      • static Grid loadCellsFile(const std::string& path) : Charge une grille à partir d'un fichier .cells.
      • static std::pair<int, int> parseGridDimensions(const std::string& line) : Analyse les dimensions de la grille à partir d'une ligne de texte.
      • static bool validateTxtFormat(const std::string& content) : Valide le format d'un fichier .txt.
      • static bool validateCellsFormat(const std::string& content) : Valide le format d'un fichier .cells.
    • Membres publics :

      • static Grid loadGridFromFile(const std::string& path) : Charge une grille à partir d'un fichier.
      • static void loadGridFromFile(const std::string& path, Grid& grid) : Charge une grille à partir d'un fichier et met à jour un objet Grid existant.
      • static void saveGridToFile(const Grid& grid, const std::string& path) : Sauvegarde une grille dans un fichier.
      • static void loadTxtFile(const std::string& path, Grid& grid) : Charge une grille à partir d'un fichier .txt et met à jour un objet Grid existant.
      • static void loadCellsFile(const std::string& path, Grid& grid) : Charge une grille à partir d'un fichier .cells et met à jour un objet Grid existant.
      • bool validateFileFormat(const std::string& content) : Valide le format d'un fichier.

Fichier FileHandler.cpp

Implémentation de la Classe FileHandler

Définition des constantes statiques

const int FileHandler::DEFAULT_CELLS_WIDTH = 50;
const int FileHandler::DEFAULT_CELLS_HEIGHT = 50;

Ces constantes définissent la largeur et la hauteur par défaut pour les fichiers .cells.

Méthodes

  • FileFormat getFileFormat(const std::string& path)
    • Détermine le format du fichier en fonction de son extension.
FileFormat FileHandler::getFileFormat(const std::string& path) {
    std::string extension = std::filesystem::path(path).extension().string();
    std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);

    if (extension == ".txt") return FileFormat::TXT;
    if (extension == ".cells") return FileFormat::CELLS;
    return FileFormat::UNKNOWN;
}
  • Grid loadGridFromFile(const std::string& path)
    • Charge une grille à partir d'un fichier.
Grid FileHandler::loadGridFromFile(const std::string& path) {
    FileFormat format = getFileFormat(path);
    switch (format) {
        case FileFormat::TXT:
            return loadTxtFile(path);
        case FileFormat::CELLS:
            return loadCellsFile(path);
        default:
            throw std::runtime_error("Format de fichier non supporté : " + path);
    }
}
  • void loadGridFromFile(const std::string& path, Grid& grid)
    • Charge une grille à partir d'un fichier et met à jour un objet Grid existant.
void FileHandler::loadGridFromFile(const std::string& path, Grid& grid) {
    FileFormat format = getFileFormat(path);
    switch (format) {
        case FileFormat::TXT:
            loadTxtFile(path, grid);
            break;
        case FileFormat::CELLS:
            loadCellsFile(path, grid);
            break;
        default:
            throw std::runtime_error("Format de fichier non supporté : " + path);
    }
}
  • Grid loadTxtFile(const std::string& path)
    • Charge une grille à partir d'un fichier .txt.
Grid FileHandler::loadTxtFile(const std::string& path) {
    std::ifstream file(path);
    if (!file.is_open()) {
        throw std::runtime_error("Impossible d'ouvrir le fichier : " + path);
    }

    std::string line;
    std::getline(file, line);
    auto [width, height] = parseGridDimensions(line);

    Grid grid(width, height);
    for (int y = 0; y < height; y++) {
        std::getline(file, line);
        std::istringstream lineStream(line);
        for (int x = 0; x < width; x++) {
            int state;
            if (!(lineStream >> state)) {
                throw std::runtime_error("Format de grille invalide à la ligne " + std::to_string(y + 1));
            }
            if (state == 2) {
                grid.addObstacle(x, y);
            } else {
                grid.setCellAt(x, y, state ? CellState::ALIVE : CellState::DEAD);
            }
        }
    }

    return grid;
}
  • void loadTxtFile(const std::string& path, Grid& grid)
    • Charge une grille à partir d'un fichier .txt et met à jour un objet Grid existant.
void FileHandler::loadTxtFile(const std::string& path, Grid& grid) {
    std::ifstream file(path);
    if (!file.is_open()) {
        throw std::runtime_error("Impossible d'ouvrir le fichier : " + path);
    }

    std::string line;
    std::getline(file, line);
    auto [width, height] = parseGridDimensions(line);

    if (width != grid.getWidth() || height != grid.getHeight()) {
        throw std::runtime_error("Les dimensions du fichier ne correspondent pas à la grille");
    }

    for (int y = 0; y < height; y++) {
        std::getline(file, line);
        std::istringstream lineStream(line);
        for (int x = 0; x < width; x++) {
            int state;
            if (!(lineStream >> state)) {
                throw std::runtime_error("Format de grille invalide à la ligne " + std::to_string(y + 1));
            }
            if (state == 2) {
                grid.addObstacle(x, y);
            } else {
                grid.setCellAt(x, y, state ? CellState::ALIVE : CellState::DEAD);
            }
        }
    }
}
  • Grid loadCellsFile(const std::string& path) (suite)
    • Charge une grille à partir d'un fichier .cells.
Grid FileHandler::loadCellsFile(const std::string& path) {
    std::ifstream file(path);
    if (!file.is_open()) {
        throw std::runtime_error("Impossible d'ouvrir le fichier : " + path);
    }

    // Créer une grille avec les dimensions par défaut
    Grid grid(DEFAULT_CELLS_WIDTH, DEFAULT_CELLS_HEIGHT);

    // Première passe : lire le motif pour obtenir ses dimensions
    std::vector<std::string> pattern;
    std::string line;
    int patternWidth = 0;

    while (std::getline(file, line)) {
        if (line.empty() || line[0] == '!') continue;
        patternWidth = std::max(patternWidth, static_cast<int>(line.length()));
        pattern.push_back(line);
    }

    int patternHeight = pattern.size();

    // Calculer les coordonnées pour centrer le motif
    int startX = (DEFAULT_CELLS_WIDTH - patternWidth) / 2;
    int startY = (DEFAULT_CELLS_HEIGHT - patternHeight) / 2;

    std::cout << "Création d'une grille " << DEFAULT_CELLS_WIDTH << "x" << DEFAULT_CELLS_HEIGHT << std::endl;
    std::cout << "Motif de taille " << patternWidth << "x" << patternHeight
              << " centré à la position (" << startX << "," << startY << ")" << std::endl;

    // Placer le motif au centre
    for (size_t y = 0; y < pattern.size(); y++) {
        for (size_t x = 0; x < pattern[y].length(); x++) {
            if (pattern[y][x] == 'O' || pattern[y][x] == '*') {
                int gridX = startX + x;
                int gridY = startY + y;
                if (gridX >= 0 && gridX < DEFAULT_CELLS_WIDTH &&
                    gridY >= 0 && gridY < DEFAULT_CELLS_HEIGHT) {
                    grid.setCellAt(gridX, gridY, CellState::ALIVE);
                }
            }
        }
    }

    return grid;
}
  • void loadCellsFile(const std::string& path, Grid& grid)
    • Charge une grille à partir d'un fichier .cells et met à jour un objet Grid existant.
void FileHandler::loadCellsFile(const std::string& path, Grid& grid) {
    std::ifstream file(path);
    if (!file.is_open()) {
        throw std::runtime_error("Impossible d'ouvrir le fichier : " + path);
    }

    // Réinitialiser la grille
    for (int y = 0; y < grid.getHeight(); y++) {
        for (int x = 0; x < grid.getWidth(); x++) {
            grid.setCellAt(x, y, CellState::DEAD);
        }
    }

    // Première passe : lire le motif
    std::vector<std::string> pattern;
    std::string line;
    int patternWidth = 0;

    while (std::getline(file, line)) {
        if (line.empty() || line[0] == '!') continue;
        patternWidth = std::max(patternWidth, static_cast<int>(line.length()));
        pattern.push_back(line);
    }

    int patternHeight = pattern.size();

    // Centrer le motif dans la grille existante
    int startX = (grid.getWidth() - patternWidth) / 2;
    int startY = (grid.getHeight() - patternHeight) / 2;

    // Placer le motif
    for (size_t y = 0; y < pattern.size(); y++) {
        for (size_t x = 0; x < pattern[y].length(); x++) {
            if (pattern[y][x] == 'O' || pattern[y][x] == '*') {
                int gridX = startX + x;
                int gridY = startY + y;
                if (gridX >= 0 && gridX < grid.getWidth() &&
                    gridY >= 0 && gridY < grid.getHeight()) {
                    grid.setCellAt(gridX, gridY, CellState::ALIVE);
                }
            }
        }
    }
}
  • void saveGridToFile(const Grid& grid, const std::string& path)
    • Sauvegarde une grille dans un fichier.
void FileHandler::saveGridToFile(const Grid& grid, const std::string& path) {
    FileFormat format = getFileFormat(path);
    std::ofstream file(path);

    if (!file.is_open()) {
        throw std::runtime_error("Impossible de créer le fichier : " + path);
    }

    switch (format) {
        case FileFormat::TXT: {
            file << grid.getWidth() << " " << grid.getHeight() << "\n";
            for (int y = 0; y < grid.getHeight(); y++) {
                for (int x = 0; x < grid.getWidth(); x++) {
                    const Cell& cell = grid.getCellAt(x, y);
                    if (cell.isObstacleCell()) {
                        file << "2";
                    } else {
                        file << (cell.getCurrentState() == CellState::ALIVE ? "1" : "0");
                    }
                    if (x < grid.getWidth() - 1) file << " ";
                }
                file << "\n";
            }
            break;
        }
        case FileFormat::CELLS: {
            file << "!Name: Pattern sauvegardé\n";
            file << "!Author: Game of Life\n\n";

            for (int y = 0; y < grid.getHeight(); y++) {
                for (int x = 0; x < grid.getWidth(); x++) {
                    const Cell& cell = grid.getCellAt(x, y);
                    file << (cell.getCurrentState() == CellState::ALIVE ? 'O' : '.');
                }
                file << "\n";
            }
            break;
        }
        default:
            throw std::runtime_error("Format de fichier non supporté pour la sauvegarde");
    }
}
  • std::pair<int, int> parseGridDimensions(const std::string& line)
    • Analyse les dimensions de la grille à partir d'une ligne de texte.
std::pair<int, int> FileHandler::parseGridDimensions(const std::string& line) {
    std::istringstream iss(line);
    int width, height;
    if (!(iss >> width >> height) || width <= 0 || height <= 0) {
        throw std::runtime_error("Format de dimensions invalide");
    }
    return {width, height};
}
  • bool validateTxtFormat(const std::string& content)
    • Valide le format d'un fichier .txt.
bool FileHandler::validateTxtFormat(const std::string& content) {
    std::istringstream iss(content);
    std::string firstLine;
    if (!std::getline(iss, firstLine)) return false;

    try {
        auto [width, height] = parseGridDimensions(firstLine);
        std::string line;
        int lineCount = 0;

        while (std::getline(iss, line) && lineCount < height) {
            std::istringstream lineStream(line);
            int value;
            int columnCount = 0;

            while (lineStream >> value && columnCount < width) {
                if (value != 0 && value != 1 && value != 2) {
                    return false;
                }
                columnCount++;
            }

            if (columnCount != width) return false;
            lineCount++;
        }

        return lineCount == height;
    }
    catch (const std::exception&) {
        return false;
    }
}
  • bool validateCellsFormat(const std::string& content)
    • Valide le format d'un fichier .cells.
bool FileHandler::validateCellsFormat(const std::string& content) {
    std::istringstream iss(content);
    std::string line;

    while (std::getline(iss, line)) {
        if (line.empty() || line[0] == '!') continue;

        for (char c : line) {
            if (c != '.' && c != 'O' && c != '*') {
                return false;
            }
        }
    }

    return true;
}
  • bool validateFileFormat(const std::string& content)
    • Valide le format d'un fichier.
bool FileHandler::validateFileFormat(const std::string& content) {
    return validateTxtFormat(content);
}
⚠️ **GitHub.com Fallback** ⚠️