/Core/Pak.cpp

https://bitbucket.org/veltarn/nectar-editor · C++ · 306 lines · 196 code · 46 blank · 64 comment · 37 complexity · 580294aa4db5affe035f3c756c7f3067 MD5 · raw file

  1. #include "Pak.h"
  2. using namespace std;
  3. PAK::PAK()
  4. {
  5. m_buffer = NULL;
  6. }
  7. PAK::~PAK()
  8. {
  9. if(m_buffer != NULL)
  10. delete m_buffer;
  11. }
  12. void PAK::create( string destination )
  13. {
  14. //Sera utilisé pour stocker les informations des fichiers et les placer dans le vecteur m_entries
  15. sFileEntry entry;
  16. //Fichier d'entrée pour lire chaque fichier demandé
  17. ifstream file;
  18. //Fichier de sortie pour écrire le fichier Pak
  19. ofstream pakfile;
  20. //Buffer utilisé pour lire et écrire dans le fichier Pak
  21. char buffer[1];
  22. std::string uId( "NECP" );
  23. //Header du Pak
  24. //On rempli la structure de 0
  25. memset(&m_header, 0, sizeof(m_header));
  26. //On place l'ID unique
  27. memcpy(m_header.uniqueID, uId.c_str(), strlen( uId.c_str() ) );;
  28. //Puis la version
  29. memcpy(m_header.version, "1", 3);
  30. //Puis on mets le nombre de fichiers à ajouter
  31. m_header.nb_files = m_filesList.size();
  32. //On ouvre chaque fichier pour créer la table des fichier (m_entries)
  33. for( map<string, string>::iterator it = m_filesList.begin(); it != m_filesList.end(); ++it )
  34. {
  35. string sourceFileName = it->first;
  36. string destinationFileName = it->second;
  37. file.open( sourceFileName.c_str(), ifstream::in | ifstream::binary );
  38. if( file.is_open() )
  39. {
  40. //Filling entry structure with 0
  41. memset( &entry, 0, sizeof( sFileEntry ) );
  42. //Writing file name
  43. memcpy( entry.name, destinationFileName.c_str(), strlen( destinationFileName.c_str() ) );
  44. //Calculating file size
  45. file.seekg( 0, ios::end );
  46. entry.size = file.tellg();
  47. //Initiating offset to 0 because we don't know what is the position of the file in the pak file
  48. entry.offset = 0;
  49. file.close();
  50. m_entries.push_back( entry );
  51. }
  52. else
  53. {
  54. throw PakFileException( "An error has occured during processing of file \"" + sourceFileName + "\"" );
  55. }
  56. }
  57. /*for(unsigned int i = 0; i < m_filesList.size(); i++)
  58. {
  59. file.open(files[i].c_str(), ifstream::in | ifstream::binary);
  60. if(file.is_open())
  61. {
  62. //On met a 0 la structure entry
  63. memset(&entry, 0, sizeof(sFileEntry));
  64. //On écrit le nom du fichier (à revoir concernant le c_str)
  65. memcpy(entry.name, files[i].c_str(), strlen(files[i].c_str()));
  66. //Calcul de la taille du fichier en se positionnant au dernier octet
  67. file.seekg(0, ios::end);
  68. entry.size = file.tellg();
  69. //On initie l'offset à 0 puisqu'on ne connait pas encore sa position dans le fichier pak
  70. entry.offset = 0;
  71. //Fermeture du fichier actuel
  72. file.close();
  73. //Ajout de l'entry au vecteur des entries
  74. m_entries.push_back(entry);
  75. }
  76. else
  77. {
  78. throw PakFileException( "An error has occured during processing of file \"" + files[i] + "\"" );
  79. }
  80. }*/
  81. //Maintenant qu'on connait la taille de tous nos fichiers, on va calculer l'offset
  82. long current_offset = 0;
  83. //On réserve suffisament de place dans le fichier Pak pour stocker en début le Header et la table des fichiers
  84. current_offset += sizeof(sPAKHeader);
  85. current_offset += sizeof(sFileEntry) * m_header.nb_files;
  86. for(unsigned int i = 0; i < m_entries.size(); i++)
  87. {
  88. //On inscrit la position actuelle dans le Pak comme offset du fichier actuel.
  89. //Cela correspond au début du fichier
  90. m_entries[i].offset = current_offset;
  91. //Puis on incrémente current_offset de la taille du fichier courant pour passer au suivant
  92. current_offset += m_entries[i].size;
  93. }
  94. //Puis on écrit dans le fichier Pak
  95. pakfile.open(destination.c_str(), ofstream::out | ofstream::binary);
  96. //Ecriture du header
  97. pakfile.write((char*)&m_header, sizeof(sPAKHeader));
  98. //Puis la table des fichiers
  99. for(unsigned int i = 0; i < m_entries.size(); i++)
  100. {
  101. pakfile.write((char*)&m_entries[i], sizeof(sFileEntry));
  102. }
  103. //Puis on écrit chaque fichier
  104. for(unsigned int i = 0; i < m_entries.size(); i++)
  105. {
  106. // On récupère le fichier source
  107. string source = getSourcePath( m_entries[i].name );
  108. file.open( source.c_str(), ifstream::in | ifstream::binary);
  109. if(file.is_open())
  110. {
  111. file.seekg(0, ios::beg);
  112. while(file.read(buffer, 1))
  113. {
  114. pakfile.write(buffer, 1);
  115. }
  116. file.close();
  117. }
  118. else
  119. {
  120. throw PakFileException( "Cannot open \"" + string( m_entries[i].name ) + "\" no such file or directory" );
  121. }
  122. file.clear();
  123. }
  124. //Fermeture du fichier Pak
  125. pakfile.close();
  126. }
  127. void PAK::read( string source )
  128. {
  129. //Fichier sur lequel on veut les informations
  130. ifstream pakfile;
  131. //Vidage de m_entries
  132. m_entries.clear();
  133. sFileEntry entry;
  134. memset(&m_header, 0, sizeof(sPAKHeader));
  135. pakfile.open(source.c_str(), ifstream::in | ifstream::binary);
  136. if(pakfile.is_open())
  137. {
  138. //Positionnement sur le header
  139. pakfile.seekg(0, ios::beg);
  140. //Lecture du header
  141. pakfile.read((char*)&m_header, sizeof(sPAKHeader));
  142. if( strcmp( m_header.uniqueID, "NECP" ) == 0 )
  143. {
  144. //Puis on lit chaque entrée de la table des fichiers
  145. for(unsigned int i = 0; i < m_header.nb_files; i++)
  146. {
  147. pakfile.read((char*)&entry, sizeof(sFileEntry));
  148. m_entries.push_back(entry);
  149. }
  150. m_pakfileName = source;
  151. }
  152. else
  153. {
  154. throw PakFileException( source + " is not a valide Nectar Package File" );
  155. }
  156. }
  157. else
  158. {
  159. throw PakFileException( "An error has occured during file reading (" + source + "), no such file or directory" );
  160. }
  161. pakfile.close();
  162. }
  163. char *PAK::getFile( string filename )
  164. {
  165. ifstream pakfile;
  166. //On vide l'ancien buffer
  167. if(m_buffer != NULL)
  168. {
  169. delete m_buffer;
  170. m_buffer = NULL;
  171. }
  172. //On cherche en premier temps le fichier dont on a besoin
  173. for(unsigned int i = 0; i < m_entries.size(); i++)
  174. {
  175. if(m_entries[i].name == filename)
  176. {
  177. //On alloue de la mémoire pour le buffer
  178. m_buffer = new char[(m_entries[i].size)];
  179. //Si l'allocation a échouée
  180. if(m_buffer == NULL)
  181. return NULL;
  182. //On ouvre le fichier pak pour récupérer ce dont on a besoin
  183. pakfile.open(m_pakfileName.c_str(), ifstream::in | ifstream::binary);
  184. if(pakfile.is_open())
  185. {
  186. pakfile.seekg(m_entries[i].offset, ios::beg);
  187. pakfile.read(m_buffer, m_entries[i].size);
  188. pakfile.close();
  189. return m_buffer;
  190. }
  191. }
  192. }
  193. return NULL;
  194. }
  195. long int PAK::getFileSize(std::string filename)
  196. {
  197. for(unsigned int i = 0; i < m_entries.size(); i++)
  198. {
  199. if(m_entries[i].name == filename)
  200. {
  201. return m_entries[i].size;
  202. }
  203. }
  204. return 0;
  205. }
  206. void PAK::addFile( std::string fileName, std::string destinationName )
  207. {
  208. string pakFileName( "" );
  209. if( destinationName.empty() )
  210. {
  211. pakFileName = filename( fileName );
  212. }
  213. else
  214. {
  215. pakFileName = destinationName;
  216. }
  217. m_filesList[fileName] = pakFileName;
  218. }
  219. void PAK::removeFile( string fileName)
  220. {
  221. bool found = false;
  222. for( map<string, string>::iterator it = m_filesList.begin(); it != m_filesList.end() && !found; ++it )
  223. {
  224. if( it->first == fileName )
  225. {
  226. found = true;
  227. m_filesList.erase( it );
  228. }
  229. }
  230. }
  231. string PAK::filename( std::string filepath )
  232. {
  233. size_t pos = filepath.find_last_of( '/' );
  234. if( pos != string::npos )
  235. {
  236. string tmp = filepath.substr( pos + 1, filepath.size() - 1 );
  237. return tmp;
  238. }
  239. return string( filepath );
  240. }
  241. vector<sFileEntry> PAK::entriesList() const
  242. {
  243. return m_entries;
  244. }
  245. string PAK::getSourcePath(std::string destination)
  246. {
  247. for( map<string, string>::iterator it = m_filesList.begin(); it != m_filesList.end(); ++it )
  248. {
  249. if( it->second == destination )
  250. {
  251. return it->first;
  252. }
  253. }
  254. return destination;
  255. }