RAMFILE.CPP 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. //
  2. // Copyright 2020 Electronic Arts Inc.
  3. //
  4. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
  5. // software: you can redistribute it and/or modify it under the terms of
  6. // the GNU General Public License as published by the Free Software Foundation,
  7. // either version 3 of the License, or (at your option) any later version.
  8. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. /* $Header: /CounterStrike/RAMFILE.CPP 1 3/03/97 10:25a Joe_bostic $ */
  15. /***********************************************************************************************
  16. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  17. ***********************************************************************************************
  18. * *
  19. * Project Name : Command & Conquer *
  20. * *
  21. * File Name : RAMFILE.CPP *
  22. * *
  23. * Programmer : Joe L. Bostic *
  24. * *
  25. * Start Date : 06/30/96 *
  26. * *
  27. * Last Update : July 3, 1996 [JLB] *
  28. * *
  29. *---------------------------------------------------------------------------------------------*
  30. * Functions: *
  31. * RAMFileClass::Close -- This will 'close' the ram file. *
  32. * RAMFileClass::Create -- Effectively clears the buffer of data. *
  33. * RAMFileClass::Delete -- Effectively clears the buffer of data. *
  34. * RAMFileClass::Is_Available -- Determines if the "file" is available. *
  35. * RAMFileClass::Is_Open -- Is the file open? *
  36. * RAMFileClass::Open -- Opens a RAM based file for read or write. *
  37. * RAMFileClass::Open -- Opens the RAM based file. *
  38. * RAMFileClass::RAMFileClass -- Construct a RAM buffer based "file" object. *
  39. * RAMFileClass::Read -- Read data from the file. *
  40. * RAMFileClass::Seek -- Controls the ram file virtual read position. *
  41. * RAMFileClass::Size -- Returns with the size of the ram file. *
  42. * RAMFileClass::Write -- Copies data to the ram file. *
  43. * RAMFileClass::~RAMFileClass -- Destructor for the RAM file class. *
  44. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  45. #include "FUNCTION.H"
  46. #include "ramfile.h"
  47. #include <string.h>
  48. /***********************************************************************************************
  49. * RAMFileClass::RAMFileClass -- Construct a RAM buffer based "file" object. *
  50. * *
  51. * This routine will construct a "file" object that actually is just a front end processor *
  52. * for a buffer. Access to the buffer will appear as if it was accessing a file. This *
  53. * is different from the caching ability of the buffered file class in that this file *
  54. * class has no real file counterpart. Typical use of this is for algorithms that were *
  55. * originally designed for file processing, but are now desired to work with a buffer. *
  56. * *
  57. * INPUT: buffer -- Pointer to the buffer to use for this file. The buffer will already *
  58. * contain data if the file is opened for READ. It will be considered *
  59. * a scratch buffer if opened for WRITE. If the buffer pointer is NULL *
  60. * but the length parameter is not, then a buffer will be allocated *
  61. * of the specified length. This case is only useful for opening the *
  62. * file for WRITE. *
  63. * *
  64. * length -- The length of the buffer submitted to this routine. *
  65. * *
  66. * OUTPUT: none *
  67. * *
  68. * WARNINGS: none *
  69. * *
  70. * HISTORY: *
  71. * 07/03/1996 JLB : Created. *
  72. *=============================================================================================*/
  73. RAMFileClass::RAMFileClass(void * buffer, int len) :
  74. Buffer((char *)buffer),
  75. MaxLength(len),
  76. Length(len),
  77. Offset(0),
  78. Access(READ),
  79. IsOpen(false),
  80. IsAllocated(false)
  81. {
  82. if (buffer == NULL && len > 0) {
  83. Buffer = new char[len];
  84. IsAllocated = true;
  85. }
  86. }
  87. /***********************************************************************************************
  88. * RAMFileClass::~RAMFileClass -- Destructor for the RAM file class. *
  89. * *
  90. * The destructor will deallocate any buffer that it allocated. Otherwise it does nothing. *
  91. * *
  92. * INPUT: none *
  93. * *
  94. * OUTPUT: none *
  95. * *
  96. * WARNINGS: none *
  97. * *
  98. * HISTORY: *
  99. * 07/03/1996 JLB : Created. *
  100. *=============================================================================================*/
  101. RAMFileClass::~RAMFileClass(void)
  102. {
  103. Close();
  104. if (IsAllocated) {
  105. delete [] Buffer;
  106. Buffer = NULL;
  107. IsAllocated = false;
  108. }
  109. }
  110. /***********************************************************************************************
  111. * RAMFileClass::Create -- Effectively clears the buffer of data. *
  112. * *
  113. * This routine "clears" the buffer of data. It only makes the buffer appear empty by *
  114. * resetting the internal length to zero. *
  115. * *
  116. * INPUT: none *
  117. * *
  118. * OUTPUT: Was the file reset in this fashion? *
  119. * *
  120. * WARNINGS: If the file was open, then resetting by this routine is not allowed. *
  121. * *
  122. * HISTORY: *
  123. * 07/03/1996 JLB : Created. *
  124. *=============================================================================================*/
  125. int RAMFileClass::Create(void)
  126. {
  127. if (!Is_Open()) {
  128. Length = 0;
  129. return(true);
  130. }
  131. return(false);
  132. }
  133. /***********************************************************************************************
  134. * RAMFileClass::Delete -- Effectively clears the buffer of data. *
  135. * *
  136. * This routine "clears" the buffer of data. It only makes the buffer appear empty by *
  137. * resetting the internal length to zero. *
  138. * *
  139. * INPUT: none *
  140. * *
  141. * OUTPUT: Was the file reset in this fashion? *
  142. * *
  143. * WARNINGS: If the file was open, then resetting by this routine is not allowed. *
  144. * *
  145. * HISTORY: *
  146. * 07/03/1996 JLB : Created. *
  147. *=============================================================================================*/
  148. int RAMFileClass::Delete(void)
  149. {
  150. if (!Is_Open()) {
  151. Length = 0;
  152. return(true);
  153. }
  154. return(false);
  155. }
  156. /***********************************************************************************************
  157. * RAMFileClass::Is_Available -- Determines if the "file" is available. *
  158. * *
  159. * RAM files are always available. *
  160. * *
  161. * INPUT: none *
  162. * *
  163. * OUTPUT: TRUE *
  164. * *
  165. * WARNINGS: none *
  166. * *
  167. * HISTORY: *
  168. * 07/03/1996 JLB : Created. *
  169. *=============================================================================================*/
  170. int RAMFileClass::Is_Available(int )
  171. {
  172. return(true);
  173. }
  174. /***********************************************************************************************
  175. * RAMFileClass::Is_Open -- Is the file open? *
  176. * *
  177. * This answers the question whether the file is open or not. *
  178. * *
  179. * INPUT: none *
  180. * *
  181. * OUTPUT: bool; Is the file open? *
  182. * *
  183. * WARNINGS: none *
  184. * *
  185. * HISTORY: *
  186. * 07/03/1996 JLB : Created. *
  187. *=============================================================================================*/
  188. int RAMFileClass::Is_Open(void) const
  189. {
  190. return(IsOpen);
  191. }
  192. /***********************************************************************************************
  193. * RAMFileClass::Open -- Opens a RAM based file for read or write. *
  194. * *
  195. * This routine will open the ram file. The name is meaningless so that parameter is *
  196. * ignored. If the access mode is for write, then the pseudo-file can be written until the *
  197. * buffer is full. If the file is opened for read, then the buffer is presumed to be full *
  198. * of the data to be read. *
  199. * *
  200. * INPUT: name -- ignored. *
  201. * *
  202. * access-- The access method to use for the data buffer -- either READ or WRITE. *
  203. * *
  204. * OUTPUT: bool; Was the open successful? *
  205. * *
  206. * WARNINGS: none *
  207. * *
  208. * HISTORY: *
  209. * 07/03/1996 JLB : Created. *
  210. *=============================================================================================*/
  211. int RAMFileClass::Open(char const * , int access)
  212. {
  213. return(Open(access));
  214. }
  215. /***********************************************************************************************
  216. * RAMFileClass::Open -- Opens the RAM based file. *
  217. * *
  218. * This will open the ram based file for read or write. If the file is opened for write, *
  219. * the the 'file' can be written up to the limit of the buffer's size. If the file is *
  220. * opened for read, then the buffer is presumed to hold the data to be read. *
  221. * *
  222. * INPUT: *
  223. * *
  224. * OUTPUT: *
  225. * *
  226. * WARNINGS: *
  227. * *
  228. * HISTORY: *
  229. * 07/03/1996 JLB : Created. *
  230. *=============================================================================================*/
  231. int RAMFileClass::Open(int access)
  232. {
  233. if (Buffer == NULL || Is_Open()) {
  234. return(false);
  235. }
  236. Offset = 0;
  237. Access = access;
  238. IsOpen = true;
  239. switch (access) {
  240. default:
  241. case READ:
  242. break;
  243. case WRITE:
  244. Length = 0;
  245. break;
  246. case READ|WRITE:
  247. break;
  248. }
  249. return(Is_Open());
  250. }
  251. /***********************************************************************************************
  252. * RAMFileClass::Read -- Read data from the file. *
  253. * *
  254. * Use this routine just like a normal file read. It will copy the bytes from the ram *
  255. * buffer to the destination specified. When the ram buffer is exhausted, less bytes than *
  256. * requested will be read. *
  257. * *
  258. * INPUT: buffer -- Pointer to the buffer to store the data to. *
  259. * *
  260. * size -- The number of bytes to 'read' into the specified buffer. *
  261. * *
  262. * OUTPUT: Returns with the number of bytes copied to the destination buffer. If the number *
  263. * of bytes returned is less than requested, then this indicates that the source *
  264. * buffer is exhausted. *
  265. * *
  266. * WARNINGS: The read function only applies to ram 'files' opened for read access. *
  267. * *
  268. * HISTORY: *
  269. * 07/03/1996 JLB : Created. *
  270. *=============================================================================================*/
  271. long RAMFileClass::Read(void * buffer, long size)
  272. {
  273. if (Buffer == NULL || buffer == NULL || size == 0) {
  274. return(0);
  275. }
  276. bool hasopened = false;
  277. if (!Is_Open()) {
  278. Open(READ);
  279. hasopened = true;
  280. } else {
  281. if ((Access & READ) == 0) {
  282. return(0);
  283. }
  284. }
  285. int tocopy = (size < (Length-Offset)) ? size : (Length-Offset);
  286. memmove(buffer, &Buffer[Offset], tocopy);
  287. Offset += tocopy;
  288. if (hasopened) {
  289. Close();
  290. }
  291. return(tocopy);
  292. }
  293. /***********************************************************************************************
  294. * RAMFileClass::Seek -- Controls the ram file virtual read position. *
  295. * *
  296. * This routine will move the read/write position of the ram file to the location specified *
  297. * by the offset and direction parameters. It functions similarly to the regular file *
  298. * seek method. *
  299. * *
  300. * INPUT: pos -- The signed offset from the home position specified by the "dir" *
  301. * parameter. *
  302. * *
  303. * dir -- The home position to base the position offset on. This will either be *
  304. * the start of the file, the end of the file, or the current read/write *
  305. * position. *
  306. * *
  307. * OUTPUT: Returns with the new file position. *
  308. * *
  309. * WARNINGS: none *
  310. * *
  311. * HISTORY: *
  312. * 07/03/1996 JLB : Created. *
  313. *=============================================================================================*/
  314. long RAMFileClass::Seek(long pos, int dir)
  315. {
  316. if (Buffer == NULL || !Is_Open()) {
  317. return(Offset);
  318. }
  319. int maxoffset = Length;
  320. if ((Access & WRITE) != 0) {
  321. maxoffset = MaxLength;
  322. }
  323. switch (dir) {
  324. case SEEK_CUR:
  325. Offset += pos;
  326. break;
  327. case SEEK_SET:
  328. Offset = 0 + pos;
  329. break;
  330. case SEEK_END:
  331. Offset = maxoffset + pos;
  332. break;
  333. }
  334. if (Offset < 0) Offset = 0;
  335. if (Offset > maxoffset) Offset = maxoffset;
  336. if (Offset > Length) {
  337. Length = Offset;
  338. }
  339. return(Offset);
  340. }
  341. /***********************************************************************************************
  342. * RAMFileClass::Size -- Returns with the size of the ram file. *
  343. * *
  344. * This will return the size of the 'real' data in the ram file. The real data is either *
  345. * the entire buffer, if opened for READ, or just the written data if opened for WRITE. *
  346. * *
  347. * INPUT: none *
  348. * *
  349. * OUTPUT: Returns with the number of bytes that the ram file system considers to be valid *
  350. * data of the 'file'. *
  351. * *
  352. * WARNINGS: none *
  353. * *
  354. * HISTORY: *
  355. * 07/03/1996 JLB : Created. *
  356. *=============================================================================================*/
  357. long RAMFileClass::Size(void)
  358. {
  359. return(Length);
  360. }
  361. /***********************************************************************************************
  362. * RAMFileClass::Write -- Copies data to the ram file. *
  363. * *
  364. * This function similarly to the regular write operation supported for files. It copies *
  365. * the data specified to the current write position in the ram file. *
  366. * *
  367. * INPUT: buffer -- Pointer to the data to be written. *
  368. * *
  369. * size -- The number of bytes to write to the file. *
  370. * *
  371. * OUTPUT: Returns with the actual number of bytes written. This will be less than requested *
  372. * if the buffer is exhausted of space prematurely. *
  373. * *
  374. * WARNINGS: none *
  375. * *
  376. * HISTORY: *
  377. * 07/03/1996 JLB : Created. *
  378. *=============================================================================================*/
  379. long RAMFileClass::Write(void const * buffer, long size)
  380. {
  381. if (Buffer == NULL || buffer == NULL || size == 0) {
  382. return(0);
  383. }
  384. bool hasopened = false;
  385. if (!Is_Open()) {
  386. Open(WRITE);
  387. hasopened = true;
  388. } else {
  389. if ((Access & WRITE) == 0) {
  390. return(0);
  391. }
  392. }
  393. int maxwrite = MaxLength - Offset;
  394. int towrite = (size < maxwrite) ? size : maxwrite;
  395. memmove(&Buffer[Offset], buffer, towrite);
  396. Offset += towrite;
  397. if (Offset > Length) {
  398. Length = Offset;
  399. }
  400. if (hasopened) {
  401. Close();
  402. }
  403. return(towrite);
  404. }
  405. /***********************************************************************************************
  406. * RAMFileClass::Close -- This will 'close' the ram file. *
  407. * *
  408. * Closing a ram file actually does nothing but record that it is now closed. *
  409. * *
  410. * INPUT: none *
  411. * *
  412. * OUTPUT: none *
  413. * *
  414. * WARNINGS: none *
  415. * *
  416. * HISTORY: *
  417. * 07/03/1996 JLB : Created. *
  418. *=============================================================================================*/
  419. void RAMFileClass::Close(void)
  420. {
  421. IsOpen = false;
  422. }