2
0

DataFile.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #include "DataFile.h"
  2. #include "FileService.h"
  3. #include "PackFile.h"
  4. //---------------------------------------------------------------------------------------------
  5. //DataFileBase
  6. //---------------------------------------------------------------------------------------------
  7. DataFileBase::DataFileBase(const char * _cppFileName, long _cppFileLine)
  8. {
  9. size = 0;
  10. #ifndef STOP_DEBUG
  11. cppFileName = _cppFileName;
  12. cppFileLine = _cppFileLine;
  13. #endif
  14. }
  15. DataFileBase::~DataFileBase()
  16. {
  17. }
  18. //Закрыть файл сообщив об ошибке
  19. void DataFileBase::ErrorRelease()
  20. {
  21. #ifndef STOP_DEBUG
  22. FileService::object->Error("FileService error: IDataFile file not release (file: %s, line %i)", cppFileName, cppFileLine);
  23. #endif
  24. delete this;
  25. }
  26. //Закрыть файл
  27. void DataFileBase::Release()
  28. {
  29. SingleExClassThread(FileService::object)
  30. FileService::object->DeleteDataFile(this);
  31. delete this;
  32. }
  33. //Получить размер файла
  34. dword DataFileBase::Size() const
  35. {
  36. return size;
  37. }
  38. //---------------------------------------------------------------------------------------------
  39. //DataFile
  40. //---------------------------------------------------------------------------------------------
  41. DataFile::DataFile(const char * cppFileName, long cppFileLine) : DataFileBase(cppFileName, cppFileLine)
  42. {
  43. handle = INVALID_HANDLE_VALUE;
  44. }
  45. DataFile::~DataFile()
  46. {
  47. if(handle != INVALID_HANDLE_VALUE)
  48. {
  49. ::CloseHandle(handle);
  50. handle = INVALID_HANDLE_VALUE;
  51. }
  52. }
  53. //Открыть файл
  54. bool DataFile::Open(const char * realPath)
  55. {
  56. handle = ::CreateFile(realPath, GENERIC_READ, FILE_SHARE_READ, null, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, null);
  57. if(handle == INVALID_HANDLE_VALUE)
  58. {
  59. return false;
  60. }
  61. size = ::GetFileSize(handle, null);
  62. if(size == INVALID_FILE_SIZE)
  63. {
  64. return false;
  65. }
  66. return true;
  67. }
  68. //Прочитать данные, возвращает количество прочитаных байт
  69. //если поинтер null то читать во внутрений буффер
  70. //если режим noReadAccess, то память буфера не кэшируемая
  71. dword DataFile::Read(void * buffer, dword size, bool noReadAccess)
  72. {
  73. if(!size) return 0;
  74. Assert(handle != INVALID_HANDLE_VALUE);
  75. if(!buffer)
  76. {
  77. dword curPos = ::SetFilePointer(handle, 0, null, FILE_CURRENT);
  78. dword newPos = ::SetFilePointer(handle, size, null, FILE_CURRENT);
  79. if(curPos == INVALID_SET_FILE_POINTER || newPos == INVALID_SET_FILE_POINTER)
  80. {
  81. return 0;
  82. }
  83. return newPos - curPos;
  84. }
  85. DWORD readBytes = 0;
  86. if(::ReadFile(handle, buffer, size, &readBytes, null))
  87. {
  88. return readBytes;
  89. }
  90. return 0;
  91. }
  92. //---------------------------------------------------------------------------------------------
  93. //DataFileMemUnpack
  94. //---------------------------------------------------------------------------------------------
  95. DataFileMemUnpack::DataFileMemUnpack(const char * cppFileName, long cppFileLine, const byte * data, dword fileSize) : DataFileBase(cppFileName, cppFileLine)
  96. {
  97. ptr = data;
  98. stopPtr = data + fileSize;
  99. size = fileSize;
  100. }
  101. DataFileMemUnpack::~DataFileMemUnpack()
  102. {
  103. }
  104. //Прочитать данные, возвращает количество прочитаных байт
  105. //если поинтер null то читать во внутрений буффер
  106. //если режим noReadAccess, то память буфера не кэшируемая
  107. dword DataFileMemUnpack::Read(void * buffer, dword size, bool noReadAccess)
  108. {
  109. SingleClassThread
  110. if(ptr + size > stopPtr) size = stopPtr - ptr;
  111. if(buffer)
  112. {
  113. memcpy(buffer, ptr, size);
  114. }
  115. ptr += size;
  116. return size;
  117. }
  118. //---------------------------------------------------------------------------------------------
  119. //DataFileMemPack
  120. //---------------------------------------------------------------------------------------------
  121. DataFileMemPack::DataFileMemPack(const char * cppFileName, long cppFileLine, const byte * mem, dword packedSize, dword realSize) : DataFileBase(cppFileName, cppFileLine)
  122. {
  123. Assert(mem);
  124. Assert(packedSize < realSize);
  125. sourceData = mem;
  126. sourceSize = packedSize;
  127. size = realSize;
  128. decompressor = null;
  129. }
  130. DataFileMemPack::~DataFileMemPack()
  131. {
  132. if(decompressor)
  133. {
  134. FileService::object->ReleaseStreamDecompressor(decompressor);
  135. decompressor = null;
  136. }
  137. }
  138. //Прочитать данные, возвращает количество прочитаных байт
  139. //если поинтер null то читать во внутрений буффер
  140. //если режим noReadAccess, то память буфера не кэшируемая
  141. dword DataFileMemPack::Read(void * buffer, dword size, bool noReadAccess)
  142. {
  143. SingleClassThread
  144. if(!sourceData || !size)
  145. {
  146. return 0;
  147. }
  148. if(!decompressor)
  149. {
  150. if(size == this->size && !noReadAccess && sourceData)
  151. {
  152. //Распаковка содержимого за 1 вызов в кэшируемый буфер
  153. if(buffer)
  154. {
  155. if(!XCompressor::Decompress(sourceData, sourceSize, (byte *)buffer, size))
  156. {
  157. //Данные испорчены
  158. size = 0;
  159. #ifndef STOP_DEBUG
  160. FileService::object->Error("FileService error: IDataFile file content damaged (archive in pack file) (file: %s, line %i)", cppFileName, cppFileLine);
  161. #endif
  162. }
  163. }
  164. sourceData = null;
  165. return size;
  166. }
  167. //Компрессор для потоковой распаковки
  168. decompressor = FileService::object->GetStreamDecompressor();
  169. if(!decompressor->Prepare(sourceData, sourceSize, this->size))
  170. {
  171. #ifndef STOP_DEBUG
  172. FileService::object->Error("FileService error: IDataFile file have got invalidate file size (archive in pack file) (file: %s, line %i)", cppFileName, cppFileLine);
  173. #endif
  174. sourceData = null;
  175. return 0;
  176. }
  177. }
  178. Assert(decompressor);
  179. dword readBytes = 0;
  180. if(buffer)
  181. {
  182. if(!decompressor->Process((byte *)buffer, size, readBytes))
  183. {
  184. #ifndef STOP_DEBUG
  185. FileService::object->Error("FileService error: IDataFile file content damaged (archive in pack file) (file: %s, line %i)", cppFileName, cppFileLine);
  186. #endif
  187. sourceData = null;
  188. return 0;
  189. }
  190. }else{
  191. //Надо пропустить часть файла
  192. while(size > 0)
  193. {
  194. static byte skipBuffer[16384];
  195. dword skipBytes = size;
  196. if(skipBytes > sizeof(skipBuffer)) skipBytes = sizeof(skipBuffer);
  197. dword rbytes = 0;
  198. if(!decompressor->Process((byte *)skipBuffer, skipBytes, rbytes))
  199. {
  200. #ifndef STOP_DEBUG
  201. FileService::object->Error("FileService error: IDataFile file content damaged (archive in pack file) (file: %s, line %i)", cppFileName, cppFileLine);
  202. #endif
  203. sourceData = null;
  204. return 0;
  205. }
  206. readBytes += rbytes;
  207. size -= skipBytes;
  208. }
  209. }
  210. return readBytes;
  211. }