/Core/Pak.cpp
https://bitbucket.org/veltarn/nectar-editor · C++ · 306 lines · 196 code · 46 blank · 64 comment · 37 complexity · 580294aa4db5affe035f3c756c7f3067 MD5 · raw file
- #include "Pak.h"
-
- using namespace std;
- PAK::PAK()
- {
- m_buffer = NULL;
- }
-
- PAK::~PAK()
- {
- if(m_buffer != NULL)
- delete m_buffer;
- }
-
- void PAK::create( string destination )
- {
- //Sera utilisé pour stocker les informations des fichiers et les placer dans le vecteur m_entries
- sFileEntry entry;
-
- //Fichier d'entrée pour lire chaque fichier demandé
- ifstream file;
-
- //Fichier de sortie pour écrire le fichier Pak
- ofstream pakfile;
-
- //Buffer utilisé pour lire et écrire dans le fichier Pak
- char buffer[1];
- std::string uId( "NECP" );
- //Header du Pak
- //On rempli la structure de 0
- memset(&m_header, 0, sizeof(m_header));
- //On place l'ID unique
- memcpy(m_header.uniqueID, uId.c_str(), strlen( uId.c_str() ) );;
- //Puis la version
- memcpy(m_header.version, "1", 3);
- //Puis on mets le nombre de fichiers à ajouter
- m_header.nb_files = m_filesList.size();
-
- //On ouvre chaque fichier pour créer la table des fichier (m_entries)
- for( map<string, string>::iterator it = m_filesList.begin(); it != m_filesList.end(); ++it )
- {
- string sourceFileName = it->first;
- string destinationFileName = it->second;
-
- file.open( sourceFileName.c_str(), ifstream::in | ifstream::binary );
- if( file.is_open() )
- {
- //Filling entry structure with 0
- memset( &entry, 0, sizeof( sFileEntry ) );
-
- //Writing file name
- memcpy( entry.name, destinationFileName.c_str(), strlen( destinationFileName.c_str() ) );
-
- //Calculating file size
- file.seekg( 0, ios::end );
- entry.size = file.tellg();
-
- //Initiating offset to 0 because we don't know what is the position of the file in the pak file
- entry.offset = 0;
-
- file.close();
-
- m_entries.push_back( entry );
- }
- else
- {
- throw PakFileException( "An error has occured during processing of file \"" + sourceFileName + "\"" );
- }
- }
-
- /*for(unsigned int i = 0; i < m_filesList.size(); i++)
- {
- file.open(files[i].c_str(), ifstream::in | ifstream::binary);
- if(file.is_open())
- {
- //On met a 0 la structure entry
- memset(&entry, 0, sizeof(sFileEntry));
-
- //On écrit le nom du fichier (à revoir concernant le c_str)
- memcpy(entry.name, files[i].c_str(), strlen(files[i].c_str()));
-
- //Calcul de la taille du fichier en se positionnant au dernier octet
- file.seekg(0, ios::end);
- entry.size = file.tellg();
-
- //On initie l'offset à 0 puisqu'on ne connait pas encore sa position dans le fichier pak
- entry.offset = 0;
-
- //Fermeture du fichier actuel
- file.close();
-
- //Ajout de l'entry au vecteur des entries
- m_entries.push_back(entry);
- }
- else
- {
- throw PakFileException( "An error has occured during processing of file \"" + files[i] + "\"" );
- }
- }*/
-
- //Maintenant qu'on connait la taille de tous nos fichiers, on va calculer l'offset
- long current_offset = 0;
- //On réserve suffisament de place dans le fichier Pak pour stocker en début le Header et la table des fichiers
- current_offset += sizeof(sPAKHeader);
- current_offset += sizeof(sFileEntry) * m_header.nb_files;
-
- for(unsigned int i = 0; i < m_entries.size(); i++)
- {
- //On inscrit la position actuelle dans le Pak comme offset du fichier actuel.
- //Cela correspond au début du fichier
- m_entries[i].offset = current_offset;
-
- //Puis on incrémente current_offset de la taille du fichier courant pour passer au suivant
- current_offset += m_entries[i].size;
- }
-
- //Puis on écrit dans le fichier Pak
- pakfile.open(destination.c_str(), ofstream::out | ofstream::binary);
-
- //Ecriture du header
- pakfile.write((char*)&m_header, sizeof(sPAKHeader));
-
- //Puis la table des fichiers
- for(unsigned int i = 0; i < m_entries.size(); i++)
- {
- pakfile.write((char*)&m_entries[i], sizeof(sFileEntry));
- }
-
- //Puis on écrit chaque fichier
- for(unsigned int i = 0; i < m_entries.size(); i++)
- {
- // On récupère le fichier source
- string source = getSourcePath( m_entries[i].name );
- file.open( source.c_str(), ifstream::in | ifstream::binary);
- if(file.is_open())
- {
- file.seekg(0, ios::beg);
- while(file.read(buffer, 1))
- {
- pakfile.write(buffer, 1);
- }
- file.close();
- }
- else
- {
- throw PakFileException( "Cannot open \"" + string( m_entries[i].name ) + "\" no such file or directory" );
- }
- file.clear();
- }
- //Fermeture du fichier Pak
- pakfile.close();
-
- }
-
- void PAK::read( string source )
- {
- //Fichier sur lequel on veut les informations
- ifstream pakfile;
-
- //Vidage de m_entries
- m_entries.clear();
-
- sFileEntry entry;
-
- memset(&m_header, 0, sizeof(sPAKHeader));
- pakfile.open(source.c_str(), ifstream::in | ifstream::binary);
- if(pakfile.is_open())
- {
- //Positionnement sur le header
- pakfile.seekg(0, ios::beg);
- //Lecture du header
-
- pakfile.read((char*)&m_header, sizeof(sPAKHeader));
-
- if( strcmp( m_header.uniqueID, "NECP" ) == 0 )
- {
- //Puis on lit chaque entrée de la table des fichiers
- for(unsigned int i = 0; i < m_header.nb_files; i++)
- {
- pakfile.read((char*)&entry, sizeof(sFileEntry));
- m_entries.push_back(entry);
- }
-
- m_pakfileName = source;
- }
- else
- {
- throw PakFileException( source + " is not a valide Nectar Package File" );
- }
-
- }
- else
- {
- throw PakFileException( "An error has occured during file reading (" + source + "), no such file or directory" );
- }
-
- pakfile.close();
- }
-
- char *PAK::getFile( string filename )
- {
- ifstream pakfile;
-
- //On vide l'ancien buffer
- if(m_buffer != NULL)
- {
- delete m_buffer;
- m_buffer = NULL;
- }
-
- //On cherche en premier temps le fichier dont on a besoin
- for(unsigned int i = 0; i < m_entries.size(); i++)
- {
- if(m_entries[i].name == filename)
- {
- //On alloue de la mémoire pour le buffer
- m_buffer = new char[(m_entries[i].size)];
- //Si l'allocation a échouée
- if(m_buffer == NULL)
- return NULL;
-
- //On ouvre le fichier pak pour récupérer ce dont on a besoin
- pakfile.open(m_pakfileName.c_str(), ifstream::in | ifstream::binary);
- if(pakfile.is_open())
- {
- pakfile.seekg(m_entries[i].offset, ios::beg);
- pakfile.read(m_buffer, m_entries[i].size);
- pakfile.close();
- return m_buffer;
- }
- }
- }
-
- return NULL;
- }
-
- long int PAK::getFileSize(std::string filename)
- {
- for(unsigned int i = 0; i < m_entries.size(); i++)
- {
- if(m_entries[i].name == filename)
- {
- return m_entries[i].size;
- }
- }
- return 0;
- }
-
- void PAK::addFile( std::string fileName, std::string destinationName )
- {
- string pakFileName( "" );
- if( destinationName.empty() )
- {
- pakFileName = filename( fileName );
- }
- else
- {
- pakFileName = destinationName;
- }
-
- m_filesList[fileName] = pakFileName;
- }
-
- void PAK::removeFile( string fileName)
- {
- bool found = false;
- for( map<string, string>::iterator it = m_filesList.begin(); it != m_filesList.end() && !found; ++it )
- {
- if( it->first == fileName )
- {
- found = true;
- m_filesList.erase( it );
- }
- }
- }
-
- string PAK::filename( std::string filepath )
- {
- size_t pos = filepath.find_last_of( '/' );
-
- if( pos != string::npos )
- {
- string tmp = filepath.substr( pos + 1, filepath.size() - 1 );
- return tmp;
- }
-
- return string( filepath );
- }
-
- vector<sFileEntry> PAK::entriesList() const
- {
- return m_entries;
- }
-
- string PAK::getSourcePath(std::string destination)
- {
- for( map<string, string>::iterator it = m_filesList.begin(); it != m_filesList.end(); ++it )
- {
- if( it->second == destination )
- {
- return it->first;
- }
- }
-
- return destination;
- }