Archivator.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #include "Archivator.h"
  2. //---------------------------------------------------------------------------------------------
  3. //Сompressor
  4. //---------------------------------------------------------------------------------------------
  5. PackArchivator::FileInfo::FileInfo()
  6. {
  7. data = null;
  8. size = 0;
  9. offset = 0;
  10. compressedSize = 0;
  11. }
  12. PackArchivator::FileInfo::~FileInfo()
  13. {
  14. if(data)
  15. {
  16. delete data;
  17. data = null;
  18. }
  19. }
  20. PackArchivator::PackArchivator() : files(_FL_, 256),
  21. packedData(_FL_, 65536)
  22. {
  23. }
  24. PackArchivator::~PackArchivator()
  25. {
  26. }
  27. //Добавить файл
  28. void PackArchivator::AddFile(const char * path, void * buffer, dword size)
  29. {
  30. const char * fileName = string::GetFileName(path);
  31. if(string::IsEmpty(fileName))
  32. {
  33. return;
  34. }
  35. if(size == 0)
  36. {
  37. api->Trace("Error pack builder: file \"%s\" have got zero size and not include to pack", path);
  38. return;
  39. }
  40. dword hash = string::HashNoCase(fileName);
  41. for(dword i = 0; i < files.Size(); i++)
  42. {
  43. if(files[i].hash == hash)
  44. {
  45. if(files[i].name == fileName)
  46. {
  47. api->Trace("Error pack builder: file name \"%s\" of path \"%s\" is repeat and not include to pack", fileName, path);
  48. return;
  49. }
  50. }
  51. }
  52. FileInfo & fi = files[files.Add()];
  53. fi.name = fileName;
  54. fi.hash = hash;
  55. fi.data = (byte *)buffer;
  56. fi.size = size;
  57. }
  58. //Процес подготовки данных
  59. void PackArchivator::Process(Method method)
  60. {
  61. for(dword i = 0; i < files.Size(); i++)
  62. {
  63. FileInfo & fi = files[i];
  64. const byte * fileData = fi.data;
  65. dword fileSize = fi.size;
  66. //Сжимаем
  67. if(fi.size > 0 && method == m_archive)
  68. {
  69. if(compressor.Compress(fi.data, fi.size))
  70. {
  71. Assert(compressor.Size() < fi.size);
  72. fileData = compressor.Buffer();
  73. fileSize = compressor.Size();
  74. }
  75. }
  76. fi.offset = packedData.Size();
  77. fi.compressedSize = fileSize;
  78. packedData.AddElements(fileSize);
  79. if(fileSize > 0)
  80. {
  81. memcpy(&packedData[fi.offset], fileData, fileSize);
  82. }
  83. }
  84. }
  85. //Получить количество файлов
  86. dword PackArchivator::GetFilesCount()
  87. {
  88. return files.Size();
  89. }
  90. //Получить общий размер таблицы имён
  91. dword PackArchivator::GetNamesSize()
  92. {
  93. dword size = 0;
  94. for(dword i = 0; i < files.Size(); i++)
  95. {
  96. FileInfo & fi = files[i];
  97. size += fi.name.Len() + 1;
  98. }
  99. return size;
  100. }
  101. //Получить путь архивированого файла
  102. const char * PackArchivator::GetFileName(dword index, dword & len, dword & hash)
  103. {
  104. len = files[index].name.Len();
  105. hash = files[index].hash;
  106. return files[index].name.c_str();
  107. }
  108. //Получить смещение от начала массива данных
  109. dword PackArchivator::GetFileOffset(dword index)
  110. {
  111. return files[index].offset;
  112. }
  113. //Получить размер несжатого файла
  114. dword PackArchivator::GetFileSize(dword index)
  115. {
  116. return files[index].size;
  117. }
  118. //Получить размер сжатого файла
  119. dword PackArchivator::GetFileCompressedSize(dword index)
  120. {
  121. return files[index].compressedSize;
  122. }
  123. //Получить буфер с данными
  124. const void * PackArchivator::GetDataBuffer()
  125. {
  126. return packedData.GetBuffer();
  127. }
  128. //Получить размер данных
  129. dword PackArchivator::GetDataSize()
  130. {
  131. return packedData.Size();
  132. }