RAMFile.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. //----------------------------------------------------------------------------
  24. //
  25. // Westwood Studios Pacific.
  26. //
  27. // Confidential Information
  28. // Copyright(C) 2001 - All Rights Reserved
  29. //
  30. //----------------------------------------------------------------------------
  31. //
  32. // Project: WSYS Library
  33. //
  34. // Module: IO
  35. //
  36. // File name: WSYS_RAMFile.cpp
  37. //
  38. // Created: 11/08/01
  39. //
  40. //----------------------------------------------------------------------------
  41. //----------------------------------------------------------------------------
  42. // Includes
  43. //----------------------------------------------------------------------------
  44. #include "PreRTS.h"
  45. #include <stdio.h>
  46. #include <fcntl.h>
  47. #include <io.h>
  48. #include <string.h>
  49. #include <sys/stat.h>
  50. #include "Common/AsciiString.h"
  51. #include "Common/FileSystem.h"
  52. #include "Common/RAMFile.h"
  53. #include "Common/PerfTimer.h"
  54. //----------------------------------------------------------------------------
  55. // Externals
  56. //----------------------------------------------------------------------------
  57. //----------------------------------------------------------------------------
  58. // Defines
  59. //----------------------------------------------------------------------------
  60. //----------------------------------------------------------------------------
  61. // Private Types
  62. //----------------------------------------------------------------------------
  63. //----------------------------------------------------------------------------
  64. // Private Data
  65. //----------------------------------------------------------------------------
  66. //----------------------------------------------------------------------------
  67. // Public Data
  68. //----------------------------------------------------------------------------
  69. //----------------------------------------------------------------------------
  70. // Private Prototypes
  71. //----------------------------------------------------------------------------
  72. //----------------------------------------------------------------------------
  73. // Private Functions
  74. //----------------------------------------------------------------------------
  75. //=================================================================
  76. // RAMFile::RAMFile
  77. //=================================================================
  78. RAMFile::RAMFile()
  79. : m_size(0),
  80. m_data(NULL),
  81. //Added By Sadullah Nader
  82. //Initializtion(s) inserted
  83. m_pos(0)
  84. //
  85. {
  86. }
  87. //----------------------------------------------------------------------------
  88. // Public Functions
  89. //----------------------------------------------------------------------------
  90. //=================================================================
  91. // RAMFile::~RAMFile
  92. //=================================================================
  93. RAMFile::~RAMFile()
  94. {
  95. if (m_data != NULL) {
  96. delete [] m_data;
  97. }
  98. File::close();
  99. }
  100. //=================================================================
  101. // RAMFile::open
  102. //=================================================================
  103. /**
  104. * This function opens a file using the standard C open() call. Access flags
  105. * are mapped to the appropriate open flags. Returns true if file was opened
  106. * successfully.
  107. */
  108. //=================================================================
  109. //DECLARE_PERF_TIMER(RAMFile)
  110. Bool RAMFile::open( const Char *filename, Int access )
  111. {
  112. //USE_PERF_TIMER(RAMFile)
  113. File *file = TheFileSystem->openFile( filename, access );
  114. if ( file == NULL )
  115. {
  116. return FALSE;
  117. }
  118. Bool result = open( file );
  119. file->close();
  120. return result;
  121. }
  122. //============================================================================
  123. // RAMFile::open
  124. //============================================================================
  125. Bool RAMFile::open( File *file )
  126. {
  127. //USE_PERF_TIMER(RAMFile)
  128. if ( file == NULL )
  129. {
  130. return NULL;
  131. }
  132. Int access = file->getAccess();
  133. if ( !File::open( file->getName(), access ))
  134. {
  135. return FALSE;
  136. }
  137. // read whole file in to memory
  138. m_size = file->size();
  139. m_data = MSGNEW("RAMFILE") char [ m_size ]; // pool[]ify
  140. if ( m_data == NULL )
  141. {
  142. return FALSE;
  143. }
  144. m_size = file->read( m_data, m_size );
  145. if ( m_size < 0 )
  146. {
  147. delete [] m_data;
  148. m_data = NULL;
  149. return FALSE;
  150. }
  151. m_pos = 0;
  152. return TRUE;
  153. }
  154. //============================================================================
  155. // RAMFile::openFromArchive
  156. //============================================================================
  157. Bool RAMFile::openFromArchive(File *archiveFile, const AsciiString& filename, Int offset, Int size)
  158. {
  159. //USE_PERF_TIMER(RAMFile)
  160. if (archiveFile == NULL) {
  161. return FALSE;
  162. }
  163. if (File::open(filename.str(), File::READ | File::BINARY) == FALSE) {
  164. return FALSE;
  165. }
  166. if (m_data != NULL) {
  167. delete[] m_data;
  168. m_data = NULL;
  169. }
  170. m_data = MSGNEW("RAMFILE") Char [size]; // pool[]ify
  171. m_size = size;
  172. if (archiveFile->seek(offset, File::START) != offset) {
  173. return FALSE;
  174. }
  175. if (archiveFile->read(m_data, size) != size) {
  176. return FALSE;
  177. }
  178. m_nameStr = filename;
  179. return TRUE;
  180. }
  181. //=================================================================
  182. // RAMFile::close
  183. //=================================================================
  184. /**
  185. * Closes the current file if it is open.
  186. * Must call RAMFile::close() for each successful RAMFile::open() call.
  187. */
  188. //=================================================================
  189. void RAMFile::close( void )
  190. {
  191. if ( m_data )
  192. {
  193. delete [] m_data;
  194. m_data = NULL;
  195. }
  196. File::close();
  197. }
  198. //=================================================================
  199. // RAMFile::read
  200. //=================================================================
  201. // if buffer is null, just advance the current position by 'bytes'
  202. Int RAMFile::read( void *buffer, Int bytes )
  203. {
  204. if( m_data == NULL )
  205. {
  206. return -1;
  207. }
  208. Int bytesLeft = m_size - m_pos ;
  209. if ( bytes > bytesLeft )
  210. {
  211. bytes = bytesLeft;
  212. }
  213. if (( bytes > 0 ) && ( buffer != NULL ))
  214. {
  215. memcpy ( buffer, &m_data[m_pos], bytes );
  216. }
  217. m_pos += bytes;
  218. return bytes;
  219. }
  220. //=================================================================
  221. // RAMFile::write
  222. //=================================================================
  223. Int RAMFile::write( const void *buffer, Int bytes )
  224. {
  225. return -1;
  226. }
  227. //=================================================================
  228. // RAMFile::seek
  229. //=================================================================
  230. Int RAMFile::seek( Int pos, seekMode mode)
  231. {
  232. Int newPos;
  233. switch( mode )
  234. {
  235. case START:
  236. newPos = pos;
  237. break;
  238. case CURRENT:
  239. newPos = m_pos + pos;
  240. break;
  241. case END:
  242. DEBUG_ASSERTCRASH(pos <= 0, ("RAMFile::seek - position should be <= 0 for a seek starting from the end."));
  243. newPos = m_size + pos;
  244. break;
  245. default:
  246. // bad seek mode
  247. return -1;
  248. }
  249. if ( newPos < 0 )
  250. {
  251. newPos = 0;
  252. }
  253. else if ( newPos > m_size )
  254. {
  255. newPos = m_size;
  256. }
  257. m_pos = newPos;
  258. return m_pos;
  259. }
  260. //=================================================================
  261. // RAMFile::scanInt
  262. //=================================================================
  263. Bool RAMFile::scanInt(Int &newInt)
  264. {
  265. newInt = 0;
  266. AsciiString tempstr;
  267. while ((m_pos < m_size) && ((m_data[m_pos] < '0') || (m_data[m_pos] > '9')) && (m_data[m_pos] != '-')) {
  268. ++m_pos;
  269. }
  270. if (m_pos >= m_size) {
  271. m_pos = m_size;
  272. return FALSE;
  273. }
  274. do {
  275. tempstr.concat(m_data[m_pos]);
  276. ++m_pos;
  277. } while ((m_pos < m_size) && ((m_data[m_pos] >= '0') && (m_data[m_pos] <= '9')));
  278. // if (m_pos < m_size) {
  279. // --m_pos;
  280. // }
  281. newInt = atoi(tempstr.str());
  282. return TRUE;
  283. }
  284. //=================================================================
  285. // RAMFile::scanInt
  286. //=================================================================
  287. Bool RAMFile::scanReal(Real &newReal)
  288. {
  289. newReal = 0.0;
  290. AsciiString tempstr;
  291. Bool sawDec = FALSE;
  292. while ((m_pos < m_size) && ((m_data[m_pos] < '0') || (m_data[m_pos] > '9')) && (m_data[m_pos] != '-') && (m_data[m_pos] != '.')) {
  293. ++m_pos;
  294. }
  295. if (m_pos >= m_size) {
  296. m_pos = m_size;
  297. return FALSE;
  298. }
  299. do {
  300. tempstr.concat(m_data[m_pos]);
  301. if (m_data[m_pos] == '.') {
  302. sawDec = TRUE;
  303. }
  304. ++m_pos;
  305. } while ((m_pos < m_size) && (((m_data[m_pos] >= '0') && (m_data[m_pos] <= '9')) || ((m_data[m_pos] == '.') && !sawDec)));
  306. // if (m_pos < m_size) {
  307. // --m_pos;
  308. // }
  309. newReal = atof(tempstr.str());
  310. return TRUE;
  311. }
  312. //=================================================================
  313. // RAMFile::scanString
  314. //=================================================================
  315. Bool RAMFile::scanString(AsciiString &newString)
  316. {
  317. newString.clear();
  318. while ((m_pos < m_size) && isspace(m_data[m_pos])) {
  319. ++m_pos;
  320. }
  321. if (m_pos >= m_size) {
  322. m_pos = m_size;
  323. return FALSE;
  324. }
  325. do {
  326. newString.concat(m_data[m_pos]);
  327. ++m_pos;
  328. } while ((m_pos < m_size) && (!isspace(m_data[m_pos])));
  329. return TRUE;
  330. }
  331. //=================================================================
  332. // RAMFile::nextLine
  333. //=================================================================
  334. void RAMFile::nextLine(Char *buf, Int bufSize)
  335. {
  336. Int i = 0;
  337. // seek to the next new-line character
  338. while ((m_pos < m_size) && (m_data[m_pos] != '\n')) {
  339. if ((buf != NULL) && (i < (bufSize-1))) {
  340. buf[i] = m_data[m_pos];
  341. ++i;
  342. }
  343. ++m_pos;
  344. }
  345. // we got to the new-line character, now go one past it.
  346. if (m_pos < m_size) {
  347. if ((buf != NULL) && (i < bufSize)) {
  348. buf[i] = m_data[m_pos];
  349. ++i;
  350. }
  351. ++m_pos;
  352. }
  353. if (buf != NULL) {
  354. if (i < bufSize) {
  355. buf[i] = 0;
  356. } else {
  357. buf[bufSize] = 0;
  358. }
  359. }
  360. if (m_pos >= m_size) {
  361. m_pos = m_size;
  362. }
  363. }
  364. //=================================================================
  365. // RAMFile::nextLine
  366. //=================================================================
  367. Bool RAMFile::copyDataToFile(File *localFile)
  368. {
  369. if (localFile == NULL) {
  370. return FALSE;
  371. }
  372. if (localFile->write(m_data, m_size) == m_size) {
  373. return TRUE;
  374. }
  375. return FALSE;
  376. }
  377. //=================================================================
  378. //=================================================================
  379. File* RAMFile::convertToRAMFile()
  380. {
  381. return this;
  382. }
  383. //=================================================================
  384. // RAMFile::readEntireAndClose
  385. //=================================================================
  386. /**
  387. Allocate a buffer large enough to hold entire file, read
  388. the entire file into the buffer, then close the file.
  389. the buffer is owned by the caller, who is responsible
  390. for freeing is (via delete[]). This is a Good Thing to
  391. use because it minimizes memory copies for BIG files.
  392. */
  393. char* RAMFile::readEntireAndClose()
  394. {
  395. if (m_data == NULL)
  396. {
  397. DEBUG_CRASH(("m_data is NULL in RAMFile::readEntireAndClose -- should not happen!\n"));
  398. return NEW char[1]; // just to avoid crashing...
  399. }
  400. char* tmp = m_data;
  401. m_data = NULL; // will belong to our caller!
  402. close();
  403. return tmp;
  404. }