file.h 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. //////////////////////////////////////////////////////////////////////////////
  19. //
  20. // File.h
  21. //
  22. // History:
  23. // 07/29/95 JMI Started.
  24. //
  25. // 01/22/97 JMI Added NeutralEndian which never byte swaps and additional
  26. // overload for Open() to open memfiles that grow when writes
  27. // exceed their bounds.
  28. //
  29. // 01/28/97 JMI Added yet another Open() overload that allows one to open
  30. // an existing FILE* stream with an RFile.
  31. //
  32. // 01/28/97 JMI Added yet another Open() overload that allows one to open
  33. // an existing FILE* stream with an RFile.
  34. // And yet another Open() which opens from another RFile
  35. // that is already attached to disk or memory. This is use-
  36. // ful for descended classes such as RIff (so they can sub-
  37. // class an existing RFile).
  38. //
  39. // 02/04/97 MJR/JMI Added RFileEZSave() and RFileEZLoad() that are meant
  40. // to replace the myclass.Load(char*) and
  41. // myclass.Save(char*) that has been written so far for
  42. // nearly every class that loads and saves. These new funcs
  43. // are essentially macros that will allocate an RFile, open
  44. // it with the specified filename, permissions, and endian
  45. // format, call the specified class's Load or Save, check
  46. // for error, close the RFile, and deallocate the RFile.
  47. //
  48. // 02/05/97 JMI Protected Read and Write for void* (see comments there
  49. // for details). Consequently, I had to add an overload
  50. // for char* that was being caught by the void* version
  51. // before.
  52. // Also, added Read and Writes for RPixel32.
  53. //
  54. // 02/10/97 JMI Added rspAnyLoad() and rspAnySave(). There are two types
  55. // of implementations for these functions. One is the
  56. // explicit overload where someone defines an rspAnyLoad/Save
  57. // specific to the overloaded type and the other is implicit
  58. // in that there is a template function that catches all the
  59. // ones that don't have an explicit overload.
  60. // Also, added explicit overloads for most RFile supported
  61. // types.
  62. //
  63. // 02/10/97 JMI RFILE_INSTANTIATE_ANYLOAD and SAVE had a bug where they
  64. // returned the number of items read or written instead of
  65. // 0 indicating success or non-zero indicating failure.
  66. //
  67. // 06/28/97 MJR Metrowerks compiler has a problem with explicit functions
  68. // being created AFTER templates of the same name are
  69. // defined. I simply rearranged the order so it works.
  70. //
  71. // 10/06/99 JMI rspEZSave() was not deleting its RFile when done.
  72. //
  73. //////////////////////////////////////////////////////////////////////////////
  74. //
  75. // See CPP comment for details.
  76. //
  77. //////////////////////////////////////////////////////////////////////////////
  78. #ifndef FILE_H
  79. #define FILE_H
  80. //////////////////////////////////////////////////////////////////////////////
  81. // Headers.
  82. //////////////////////////////////////////////////////////////////////////////
  83. #include <stdio.h>
  84. #include "Blue.h"
  85. // If PATHS_IN_INCLUDES macro is defined, we can utilized relative
  86. // paths to a header file. In this case we generally go off of our
  87. // RSPiX root directory. System.h MUST be included before this macro
  88. // is evaluated. System.h is the header that, based on the current
  89. // platform (or more so in this case on the compiler), defines
  90. // PATHS_IN_INCLUDES. Blue.h includes system.h so you can include that
  91. // instead.
  92. #ifdef PATHS_IN_INCLUDES
  93. #ifdef ALLOW_RFILE_REOPEN
  94. #include "ORANGE/CDT/List.h"
  95. #endif // ALLOW_RFILE_REOPEN
  96. #else
  97. #ifdef ALLOW_RFILE_REOPEN
  98. #include "List.h"
  99. #endif // ALLOW_RFILE_REOPEN
  100. #endif // PATHS_IN_INCLUDES
  101. //////////////////////////////////////////////////////////////////////////////
  102. // Macros.
  103. //////////////////////////////////////////////////////////////////////////////
  104. #ifdef ALLOW_RFILE_REOPEN
  105. #define KEEPCONNECTEDANDUPDATELASTACCESS Reconnect(), m_lLastAccess = rspGetMilliseconds()
  106. #else // ALLOW_RFILE_REOPEN
  107. #define KEEPCONNECTEDANDUPDATELASTACCESS
  108. #endif // ALLOW_RFILE_REOPEN
  109. #define MAX_MODE_LEN 6
  110. #define MAX_NAME_LEN 512
  111. // Size of buffer used to byte swap by Write(). It'd be safe to make sure
  112. // this number is a multiple of 8 (our largest base type is 8 bytes).
  113. #define RFILE_SWAP_SIZE 1024
  114. //////////////////////////////////////////////////////////////////////////////
  115. // Typedefs.
  116. //////////////////////////////////////////////////////////////////////////////
  117. // Forward declared for typedef'd protos.
  118. class RFile;
  119. //////////////////////////////////////////////////////////////////////////////
  120. class RFile
  121. {
  122. public: // Typedefs & Enums.
  123. // Use for flags field of Open():
  124. typedef enum
  125. {
  126. // No flags.
  127. NoFlags = 0x0000,
  128. // Binary mode. All numbers written to file as numbers.
  129. Binary = 0x0001,
  130. // ASCII mode. All numbers written to file as text.
  131. Ascii = 0x0002
  132. } Flags;
  133. // Use for endian field of Open and SetEndian calls.
  134. typedef enum
  135. {
  136. BigEndian, // Big endian (byte swaps on little endian systems).
  137. NeutralEndian, // Neutral endian (Never byte swaps).
  138. LittleEndian // Little endian (byte swaps on big endian systems).
  139. } Endian;
  140. typedef short (*OpenHook)( // Returns 0 to bypass default Open's
  141. // functionality. Non-zero for normal ops.
  142. RFile* pfile, // Pointer to RFile being opened.
  143. const char* pszFileName, // File path and name to open.
  144. const char* pszFlags, // Open flags ala fopen.
  145. Endian endian, // Endian nature of file.
  146. long lUser); // User value.
  147. typedef short (*CloseHook)( // Returns 0 to bypass default Close's
  148. // functionality.
  149. RFile* pfile, // Pointer to RFile being closed.
  150. long lUser); // User value.
  151. // This is the type of the function that is called before every disk
  152. // read or write operation to let the user know of (and, perhaps, act
  153. // upon) delays that may occur.
  154. typedef void (*CritiCall)( // Returns nothing.
  155. long lBytes); // Bytes about to be read or written.
  156. public: // Construction/Destruction.
  157. // Default constructor.
  158. RFile(void);
  159. // Destructor.
  160. ~RFile(void);
  161. //////////////////////////////////////////////////////////////////////////////
  162. public: // Methods.
  163. ////////////////////////////////////////////////////////////////////////
  164. // Open, Close, and operation flags.
  165. ////////////////////////////////////////////////////////////////////////
  166. // Open file pszFileName with fopen flags pszFlags and endian format
  167. // endian { RFile::Big, RFile::Little }.
  168. // Returns 0 on success.
  169. short Open( // Returns 0 on success.
  170. const char* pszFileName, // Filename to open.
  171. const char* pszFlags, // fopen flags to use for opening.
  172. Endian endian, // { RFile::BigEndian | RFile::LittleEndian | RFile::NeutralEndian }.
  173. Flags flags = // See comments in Typedefs & Enums section
  174. Binary); // above.
  175. // Open memory pFile of size lSize and endian format endian.
  176. // Size and location of memory will not be affected by RFile.
  177. // { RFile::Big, RFile::Little }.
  178. // Returns 0 on success.
  179. short Open( // Returns 0 on success.
  180. void* pFile, // Pointer to memory to open.
  181. long lSize, // Size of *pFile in bytes.
  182. Endian endian); // { RFile::BigEndian | RFile::LittleEndian | RFile::NeutralEndian }.
  183. // Open memory pFile of size lSize and endian format endian.
  184. // RFile may size and or relocate the memory in order to expand the memory file.
  185. // Deallocates on Close().
  186. // { RFile::Big, RFile::Little }.
  187. // Returns 0 on success.
  188. short Open( // Returns 0 on success.
  189. long lSize, // Size in bytes to begin with.
  190. long lGrowSize, // Min amount in bytes to grow memory file when written passed end.
  191. // Note: The larger of lGrowSize and the amount overwritten will
  192. // be allocated in the case of an overrun.
  193. Endian endian); // { RFile::BigEndian | RFile::LittleEndian | RFile::NeutralEndian }.
  194. // Open an existing FILE* stream.
  195. // Once a FILE* is opened, you can use this class's Close() instead of fclose(),
  196. // if that is more convenient.
  197. short Open( // Returns 0 on success.
  198. FILE* fs, // FILE* stream to open.
  199. Endian endian, // { RFile::BigEndian | RFile::LittleEndian | RFile::NeutralEndian }.
  200. Flags flags = // See comments in Typedefs & Enums section
  201. Binary); // above.
  202. // Open an existing RFile.
  203. // "Ack!" you say ... and I agree.
  204. // This basically begins what I like to think of as a synchronization between two RFiles.
  205. // This RFile snags the current state (basically copies the members) from the specified
  206. // RFile. Then, one can use the new RFile to access the file/memory/whatever that the
  207. // original RFile is attached to. When Close() is called, the synchronization is finsished
  208. // by updating the original RFile with the state from this.
  209. // Danger: Do not access the original RFile between Open(RFile*)/Close() pairs!
  210. short Open( // Returns 0 on success.
  211. RFile* pfile); // RFile to open.
  212. // Sets an Open(char*...) hook. NOTE: You CAN call any RFile Open from
  213. // within an Open hook. The Open hook should return 0 to bypass RFile's
  214. // functionality.
  215. static void SetOpenHook(OpenHook hook, long lUser)
  216. { ms_hOpen = hook; ms_lOpenUser = lUser; }
  217. // Change the endian format used to read/write the file.
  218. // Returns nothing.
  219. void SetEndian(Endian endian);
  220. // Set the size of the buffer used to read from the disk.
  221. // This function only applies to files open from the disk.
  222. // Returns 0 on success.
  223. short SetBufferSize(size_t stBufSize)
  224. {
  225. if (IsFile() == TRUE)
  226. {
  227. KEEPCONNECTEDANDUPDATELASTACCESS;
  228. return (short)setvbuf(m_fs, NULL, _IOFBF, stBufSize);
  229. }
  230. else
  231. if (IsMemory() == TRUE)
  232. return 0;
  233. else
  234. return -1;
  235. }
  236. // Close a file successfully opened with Open().
  237. // Returns 0 on success.
  238. short Close(void);
  239. // Sets a Close() hook. NOTE: You CAN call any RFile Close from
  240. // within a Close hook. The Close hook should return 0 to bypass RFile's
  241. // functionality.
  242. static void SetCloseHook(CloseHook hook, long lUser)
  243. { ms_hClose = hook; ms_lCloseUser = lUser; }
  244. ////////////////////////////////////////////////////////////////////////
  245. // Position.
  246. ////////////////////////////////////////////////////////////////////////
  247. // Seeks within the file based on the supplied position argument
  248. // { SEEK_SET, SEEK_CUR, SEEK_END }.
  249. // Returns 0 on success.
  250. short Seek(long lPos, long lOrigin);
  251. // Returns the current file position or -1 on error.
  252. long Tell(void);
  253. ////////////////////////////////////////////////////////////////////////
  254. // Read.
  255. ////////////////////////////////////////////////////////////////////////
  256. protected:
  257. // NOTE: THIS FUNCTION IS PROTECTED FOR AN IMPORTANT REASON:
  258. // This function was a catch all for any unsupported type. The dis-
  259. // advantage was that, if you had a type that needed to be swapped
  260. // but was not supported, this API would happily accept it, but not
  261. // swap it. This could cause hard to detect problems.
  262. // If you are reading or writing something that does not require
  263. // swapping, cast it as U8* or S8*.
  264. // Reads lNum bytes from currently open file.
  265. // Returns number of bytes successfully read.
  266. long Read(void* pData, long lNum);
  267. public:
  268. // Reads lNum char values from currently open file.
  269. // Returns number of char values successfully read.
  270. long Read(char* pcData, long lNum)
  271. { return Read((void*)pcData, lNum); }
  272. // Reads lNum U8 values from currently open file.
  273. // Returns number of U8 values successfully read.
  274. long Read(U8* pu8Data, long lNum = 1L);
  275. // Reads lNum S8 values from currently open file.
  276. // Returns number of S8 values successfully read.
  277. long Read(S8* ps8Data, long lNum = 1L);
  278. // Reads lNum U16 values from currently open file.
  279. // Returns number of U16 values successfully read.
  280. long Read(U16* pu16Data, long lNum = 1L);
  281. // Reads lNum S16 values from currently open file.
  282. // Returns number of S16 values successfully read.
  283. long Read(S16* ps16Data, long lNum = 1L);
  284. // Reads lNum RPixel24 values from currently open file.
  285. // Returns number of RPixel24 values successfully read.
  286. long Read(RPixel24* ppix24, long lNum = 1L);
  287. // Reads lNum U32 values from currently open file.
  288. // Returns number of U32 values successfully read.
  289. long Read(U32* pu32Data, long lNum = 1L);
  290. // Reads lNum S32 values from currently open file.
  291. // Returns number of S32 values successfully read.
  292. long Read(S32* ps32Data, long lNum = 1L);
  293. // Reads lNum RPixel32 values from currently open file.
  294. // Returns number of RPixel32 values successfully read.
  295. long Read(RPixel32* ppix32Data, long lNum = 1L)
  296. { return Read((U32*)ppix32Data, lNum); }
  297. // Reads lNum U64 values from currently open file.
  298. // Returns number of U64 values successfully read.
  299. long Read(U64* pu64Data, long lNum = 1L);
  300. // Reads lNum S64 values from currently open file.
  301. // Returns number of S64 values successfully read.
  302. long Read(S64* ps64Data, long lNum = 1L);
  303. // Reads lNum float values from currently open file.
  304. // Returns number of float values successfully read.
  305. long Read(float* pfData, long lNum = 1L);
  306. // Reads lNum double values from currently open file.
  307. // Returns number of double values successfully read.
  308. long Read(double* pdData, long lNum = 1L);
  309. // Reads a NULL terminated string. The '\0' must be
  310. // actually in the file to denote the end of the string.
  311. // pszString must point to a memory block sufficiently large
  312. // enough to hold the string.
  313. // Returns number of characters successfully read,
  314. // including the NULL terminator (unlike strlen()).
  315. long Read(char* pszString);
  316. ////////////////////////////////////////////////////////////////////////
  317. // Write.
  318. ////////////////////////////////////////////////////////////////////////
  319. protected:
  320. // NOTE: THIS FUNCTION IS PROTECTED FOR AN IMPORTANT REASON:
  321. // This function was a catch all for any unsupported type. The dis-
  322. // advantage was that, if you had a type that needed to be swapped
  323. // but was not supported, this API would happily accept it, but not
  324. // swap it. This could cause hard to detect problems.
  325. // If you are reading or writing something that does not require
  326. // swapping, cast it as U8* or S8*.
  327. // Writes lNum bytes from currently open file.
  328. // Returns number of bytes successfully written.
  329. long Write(const void* pData, long lNum);
  330. public:
  331. // Writes lNum char values to currently open file.
  332. // Returns number of U8 values successfully written.
  333. long Write(const char* pcData, long lNum)
  334. { return Write((void*)pcData, lNum); }
  335. // Writes lNum U8 values to currently open file.
  336. // Returns number of U8 values successfully written.
  337. long Write(const U8* pu8Data, long lNum = 1L);
  338. // Writes lNum S8 values to currently open file.
  339. // Returns number of S8 values successfully written.
  340. long Write(const S8* ps8Data, long lNum = 1L);
  341. // Writes lNum U16 values to currently open file.
  342. // Returns number of U16 values successfully written.
  343. long Write(const U16* pu16Data, long lNum = 1L);
  344. // Writes lNum S16 values to currently open file.
  345. // Returns number of S16 values successfully written.
  346. long Write(const S16* ps16Data, long lNum = 1L);
  347. // Writes lNum RPixel24 values to currently open file.
  348. // Returns number of RPixel24 values successfully written.
  349. long Write(const RPixel24* ppix24, long lNum = 1L);
  350. // Writes lNum U32 values to currently open file.
  351. // Returns number of U32 values successfully written.
  352. long Write(const U32* pu32Data, long lNum = 1L);
  353. // Writes lNum S32 values to currently open file.
  354. // Returns number of S32 values successfully written.
  355. long Write(const S32* ps32Data, long lNum = 1L);
  356. // Writes lNum RPixel32 values to currently open file.
  357. // Returns number of RPixel32 values successfully written.
  358. long Write(const RPixel32* ppix32Data, long lNum = 1L)
  359. { return Write((U32*)ppix32Data, lNum); }
  360. // Writes lNum U64 values to currently open file.
  361. // Returns number of U64 values successfully written.
  362. long Write(const U64* pu64Data, long lNum = 1L);
  363. // Writes lNum S64 values to currently open file.
  364. // Returns number of S64 values successfully written.
  365. long Write(const S64* ps64Data, long lNum = 1L);
  366. // Writes lNum float values to the currently open file.
  367. // Returns number of float values successfully written.
  368. long Write(const float* pfData, long lNum = 1L);
  369. // Writes lNum double values to the currently open file.
  370. // Returns number of double values successfully written.
  371. long Write(const double* pdData, long lNum = 1L);
  372. // Writes a NULL terminated string. The '\0' must be
  373. // actually written to file to denote the end of the string.
  374. // Returns number of characters successfully written,
  375. // including the NULL terminator (unlike strlen()).
  376. long Write(const char* pszString);
  377. ////////////////////////////////////////////////////////////////////////
  378. // These functions write one value when passed by value.
  379. // This is useful for writing literals, variables that should be written
  380. // by other than their type, and for variables of types that are not
  381. // pointer overloaded by other Write(type*, long) RFile functions.
  382. ////////////////////////////////////////////////////////////////////////
  383. // Writes one char.
  384. long Write(char cVal)
  385. { return Write(&cVal, 1); }
  386. // Writes one U8.
  387. long Write(U8 u8Val)
  388. { return Write(&u8Val); }
  389. // Writes one S8.
  390. long Write(S8 s8Val)
  391. { return Write(&s8Val); }
  392. // Writes one U16.
  393. long Write(U16 u16Val)
  394. { return Write(&u16Val); }
  395. // Writes one S16.
  396. long Write(S16 s16Val)
  397. { return Write(&s16Val); }
  398. // Writes one RPixel24.
  399. long Write(RPixel24 pix24Val)
  400. { return Write(&pix24Val); }
  401. // Writes one U32.
  402. long Write(U32 u32Val)
  403. { return Write(&u32Val); }
  404. // Writes one S32.
  405. long Write(S32 s32Val)
  406. { return Write(&s32Val); }
  407. // Writes one RPixel32.
  408. long Write(RPixel32 pix32Val)
  409. { return Write(&pix32Val); }
  410. // Writes one float.
  411. long Write(float fVal)
  412. { return Write(&fVal); }
  413. // Writes one U64.
  414. long Write(U64 u64Val)
  415. { return Write(&u64Val); }
  416. // Writes one S64.
  417. long Write(S64 s64Val)
  418. { return Write(&s64Val); }
  419. // Writes one double.
  420. long Write(double dVal)
  421. { return Write(&dVal); }
  422. //////////////////////////////////////////////////////////////////////////////
  423. public: // Querries.
  424. ////////////////////////////////////////////////////////////////////////
  425. // Querries.
  426. ////////////////////////////////////////////////////////////////////////
  427. // Returns TRUE, if open, FALSE if closed.
  428. short IsOpen(void) { return (m_fs == NULL && m_pucFile == NULL ? FALSE : TRUE); }
  429. // Returns TRUE, if connected to a non-memory file.
  430. short IsFile(void) { return (m_fs == NULL ? FALSE : TRUE); }
  431. // Returns TRUE, if connected to a memory file.
  432. short IsMemory(void) { return (m_pucFile == NULL ? FALSE : TRUE); }
  433. // Returns FALSE if no error has occurred on this stream; TRUE if an
  434. // error has occurred.
  435. short Error(void)
  436. {
  437. if (IsFile() == TRUE)
  438. {
  439. KEEPCONNECTEDANDUPDATELASTACCESS;
  440. return (ferror(m_fs) == 0 ? FALSE : TRUE);
  441. }
  442. else
  443. if (IsMemory() == TRUE)
  444. return m_sMemError;
  445. else
  446. return TRUE;
  447. }
  448. // Clears any error that has occurred on this stream.
  449. void ClearError(void)
  450. {
  451. if (IsFile() == TRUE)
  452. {
  453. KEEPCONNECTEDANDUPDATELASTACCESS;
  454. clearerr(m_fs);
  455. }
  456. else
  457. if (IsMemory() == TRUE)
  458. m_sMemError = FALSE;
  459. }
  460. // Returns TRUE if end of file has been reached, FALSE otherwise.
  461. // For disk files, does not return TRUE until the first i/o operation
  462. // fails due to EOF.
  463. short IsEOF(void)
  464. {
  465. if (IsFile() == TRUE)
  466. {
  467. KEEPCONNECTEDANDUPDATELASTACCESS;
  468. return (feof(m_fs) == 0 ? FALSE : TRUE);
  469. }
  470. else
  471. if (IsMemory() == TRUE)
  472. return (m_pucCur == m_pucFile + m_lSize);
  473. else
  474. return TRUE;
  475. }
  476. // Returns the size of the file on success. Negative on error.
  477. long GetSize(void);
  478. // Returns the endian setting for this object.
  479. short GetEndian(void)
  480. { return m_endian; }
  481. // Returns the memory ptr if this is a memory file; NULL, otherwise.
  482. // NOTE: This buffer may move after any Write() call that exceeds the
  483. // existing buffer size.
  484. UCHAR* GetMemory(void)
  485. { return m_pucFile; }
  486. //////////////////////////////////////////////////////////////////////////////
  487. protected: // Functions for my friends.
  488. // Sets the instantiable user value.
  489. void SetUserVal(long lUser)
  490. { m_lUser = lUser; }
  491. // Gets the instantiable user value.
  492. long GetUserVal(void)
  493. { return m_lUser; }
  494. //////////////////////////////////////////////////////////////////////////////
  495. protected: // Internal functions.
  496. /////////// Binary Reads /////////////////////////////////////////////////////
  497. // Reads in 8 bit data, swapped if necessary (BWAH HA).
  498. long Read8( // Returns number of 8 bit items read.
  499. U8* pu8, // In: 8 bit data to read (swapping, if necessary).
  500. long lNum); // In: Number of 8 bit items to read.
  501. // Reads in 16 bit data, swapped if necessary.
  502. long Read16( // Returns number of 16 bit items read.
  503. U16* pu16, // In: 16 bit data to read (swapping, if necessary).
  504. long lNum); // In: Number of 16 bit items to read.
  505. // Reads in 24 bit data, swapped if necessary.
  506. long Read24( // Returns number of 24 bit items read.
  507. RPixel24* ppix24, // In: 24 bit data to read (swapping, if necessary).
  508. long lNum); // In: Number of 24 bit items to read.
  509. // Reads in 32 bit data, swapped if necessary.
  510. long Read32( // Returns number of 32 bit items read.
  511. U32* pu32, // In: 32 bit data to read (swapping, if necessary).
  512. long lNum); // In: Number of 32 bit items to read.
  513. // Reads in 64 bit data, swapped if necessary.
  514. long Read64( // Returns number of 64 bit items read.
  515. U64* pu64, // In: 64 bit data to read (swapping, if necessary).
  516. long lNum); // In: Number of 64 bit items to read.
  517. /////////// Binary Writes ////////////////////////////////////////////////////
  518. // Writes out 8 bit data, swapped if necessary (BWAH HA).
  519. long Write8( // Returns number of 8 bit items written.
  520. const U8* pu8, // In: 8 bit data to write (swapping, if necessary).
  521. long lNum); // In: Number of 8 bit items to write.
  522. // Writes out 16 bit data, swapped if necessary.
  523. long Write16( // Returns number of 16 bit items written.
  524. const U16* pu16, // In: 16 bit data to write (swapping, if necessary).
  525. long lNum); // In: Number of 16 bit items to write.
  526. // Writes out 24 bit data, swapped if necessary.
  527. long Write24( // Returns number of 24 bit items written.
  528. const RPixel24* ppix24, // In: 24 bit data to write (swapping, if necessary).
  529. long lNum); // In: Number of 24 bit items to write.
  530. // Writes out 32 bit data, swapped if necessary.
  531. long Write32( // Returns number of 32 bit items written.
  532. const U32* pu32, // In: 32 bit data to write (swapping, if necessary).
  533. long lNum); // In: Number of 32 bit items to write.
  534. // Writes out 64 bit data, swapped if necessary.
  535. long Write64( // Returns number of 64 bit items written.
  536. const U64* pu64, // In: 64 bit data to write (swapping, if necessary).
  537. long lNum); // In: Number of 64 bit items to write.
  538. #ifdef ALLOW_RFILE_REOPEN
  539. // Disconnects this RFile from the disk temporarily so that another
  540. // can use the FILE* that is made available. Returns 0 on success.
  541. short Disconnect(void);
  542. // Reconnects a disk file that has been previously disconnected.
  543. // Does nothing if connected (i.e., if m_sDisconnected == FALSE).
  544. // Returns 0 on success.
  545. short Reconnect(void);
  546. // Disconnect the RFile attached to disk file that was accessed
  547. // longest ago.
  548. // Returns 0 on success.
  549. static short MakeStreamAvailable(void);
  550. #endif // ALLOW_RFILE_REOPEN
  551. //////////////////////////////////////////////////////////////////////////////
  552. friend class RRes;
  553. //////////////////////////////////////////////////////////////////////////////
  554. public: // Member variables.
  555. FILE* m_fs; // Stdio file stream ptr.
  556. static CritiCall ms_criticall; // Called on every read and write with
  557. // the amount that is about to be
  558. // processed.
  559. protected: // Member variables.
  560. UCHAR* m_pucFile; // Memory file ptr.
  561. short m_sOwnMem; // TRUE, if RFile allocated m_pucFile.
  562. UCHAR* m_pucCur; // Current position in memory file.
  563. long m_lSize; // Size of memory file (in bytes).
  564. long m_lGrowSize; // Amount to grow memfile when buffer
  565. // overwritten.
  566. short m_sMemError; // TRUE if memory file access functions
  567. // caused an error.
  568. Endian m_endian; // Endian type.
  569. Flags m_flags; // Flags. See comments in Typedefs &
  570. // Enums section above.
  571. RFile* m_pfileSynch; // RFile this RFile is synchronized with.
  572. // Used on Close() to resynch.
  573. static U8 ms_au8SwapBuf[RFILE_SWAP_SIZE]; // Used to byte swap by Write().
  574. // Hook stuff.
  575. long m_lUser; // Instantiable hook value.
  576. static OpenHook ms_hOpen; // Hook for calls to Open(char*...).
  577. static long ms_lOpenUser; // User value passed to m_hOpen.
  578. short m_sOpenSem; // Semaphore to block recursion greater
  579. // than 1.
  580. static CloseHook ms_hClose; // Hook for calls to Close().
  581. static long ms_lCloseUser; // User value passed to m_hClose.
  582. short m_sCloseSem; // Semaphore to block recursion greater
  583. // than 1.
  584. #ifdef ALLOW_RFILE_REOPEN
  585. // Reopen stuff.
  586. static RList <RFile> ms_listOpen; // List of open RFiles.
  587. long m_lLastAccess; // Time of last access.
  588. char m_szFlags[MAX_MODE_LEN + 1]; // Last Open's flags.
  589. short m_sDisconnected; // TRUE if file has been
  590. // diskonnected.
  591. char m_szFileName[MAX_NAME_LEN + 1]; // Filename for reopening.
  592. #endif // ALLOW_RFILE_REOPEN
  593. };
  594. ////////////////////////////////////////////////////////////////////////////////
  595. // This template function offers an easy way to use any object's Load()
  596. // function. Most RSPiX objects have a Load() function that expects an RFile*
  597. // as its only parameter. This function opens the file, calls the object's
  598. // Load(), and closes the file, all with full error checking. Note that the
  599. // file mode defaults to "rb" and the endian mode defaults to LittleEndian.
  600. ////////////////////////////////////////////////////////////////////////////////
  601. #define rspEZLoad(a,b) RFileEZLoad(a,b,"rb",RFile::LittleEndian)
  602. #define rspEZSave(a,b) RFileEZSave(a,b,"wb",RFile::LittleEndian)
  603. #ifdef _DEBUG
  604. #define RFileEZLoad(a,b,c,d) RFileEZLoadDebug(__FILE__, __LINE__, a, b, c, d)
  605. #endif
  606. template <class ClassType>
  607. #ifdef _DEBUG
  608. short RFileEZLoadDebug(
  609. char* FILE_MACRO,
  610. long LINE_MACRO,
  611. #else
  612. short RFileEZLoad(
  613. #endif
  614. ClassType* pObject,
  615. char* pszName,
  616. char* pszMode,
  617. RFile::Endian endian)
  618. {
  619. short sResult = 0;
  620. // Create RFile object
  621. RFile* pFile = new RFile;
  622. if (pFile != 0)
  623. {
  624. // Open the file
  625. sResult = pFile->Open(pszName, pszMode, endian);
  626. if (sResult == 0)
  627. {
  628. // Call the specified object's Load()
  629. sResult = pObject->Load(pFile);
  630. // If no error was returned then check for file I/O errors. This
  631. // may be redundant if the object's Load() already checked for file
  632. // errors, but if it didn't then this becomes very important.
  633. if ((sResult == 0) && pFile->Error())
  634. {
  635. sResult = -1;
  636. #ifdef _DEBUG
  637. STRACE("%s(%ld):RFileEZLoad(): File I/O Error!\n", FILE_MACRO, LINE_MACRO);
  638. #endif
  639. }
  640. // Close the file
  641. pFile->Close();
  642. }
  643. else
  644. {
  645. sResult = -1;
  646. #ifdef _DEBUG
  647. STRACE("%s(%ld):RFileEZLoad(): Couldn't open file '%s'!\n", FILE_MACRO, LINE_MACRO, pszName);
  648. #endif
  649. }
  650. // Delete file object
  651. delete pFile;
  652. }
  653. else
  654. {
  655. sResult = -1;
  656. #ifdef _DEBUG
  657. STRACE("%s(%ld):RFileEZLoad(): Couldn't create RFile object!\n", FILE_MACRO, LINE_MACRO);
  658. #endif
  659. }
  660. return sResult;
  661. }
  662. ////////////////////////////////////////////////////////////////////////////////
  663. // This template function offers an easy way to use any object's Save()
  664. // function. Most RSPiX objects have a Save() function that expects an RFile*
  665. // as its only parameter. This function opens the file, calls the object's
  666. // Save(), and closes the file, all with full error checking. Note that the
  667. // file mode defaults to "wb" and the endian mode defaults to LittleEndian.
  668. ////////////////////////////////////////////////////////////////////////////////
  669. #ifdef _DEBUG
  670. #define RFileEZSave(a,b,c,d) RFileEZSaveDebug(__FILE__, __LINE__, a, b, c, d)
  671. #endif
  672. template <class ClassType>
  673. #ifdef _DEBUG
  674. short RFileEZSaveDebug(
  675. char* FILE_MACRO,
  676. long LINE_MACRO,
  677. #else
  678. short RFileEZSave(
  679. #endif
  680. ClassType* pObject,
  681. char* pszName,
  682. char* pszMode,
  683. RFile::Endian endian)
  684. {
  685. short sResult = 0;
  686. // Create RFile object
  687. RFile* pFile = new RFile;
  688. if (pFile != 0)
  689. {
  690. // Open the file
  691. sResult = pFile->Open(pszName, pszMode, endian);
  692. if (sResult == 0)
  693. {
  694. // Call the specified object's Save()
  695. sResult = pObject->Save(pFile);
  696. // If no error was returned then check for file I/O errors. This
  697. // may be redundant if the object's Save() already checked for file
  698. // errors, but if it didn't then this becomes very important.
  699. if ((sResult == 0) && pFile->Error())
  700. {
  701. sResult = -1;
  702. #ifdef _DEBUG
  703. STRACE("%s(%ld):RFileEZSave(): File I/O Error!\n", FILE_MACRO, LINE_MACRO);
  704. #endif
  705. }
  706. // Close the file
  707. pFile->Close();
  708. }
  709. else
  710. {
  711. sResult = -1;
  712. #ifdef _DEBUG
  713. STRACE("%s(%ld):RFileEZSave(): Couldn't open file '%s'!\n", FILE_MACRO, LINE_MACRO, pszName);
  714. #endif
  715. }
  716. delete pFile;
  717. pFile = 0;
  718. }
  719. else
  720. {
  721. sResult = -1;
  722. #ifdef _DEBUG
  723. STRACE("%s(%ld):RFileEZSave(): Couldn't create RFile object!\n", FILE_MACRO, LINE_MACRO);
  724. #endif
  725. }
  726. return sResult;
  727. }
  728. ////////// rspAnyLoad() and rspAnySave() /////////////////////////////////////
  729. // There are two types of implementations for these functions. One is the
  730. // explicit overload where someone defines an rspAnyLoad/Save specific to the
  731. // overloaded type and the other is implicit in that there is a template
  732. // function that catches all the ones that don't have an explicit overload.
  733. //////////////////////////////////////////////////////////////////////////////
  734. //////////////////////////////////////////////////////////////////////////////
  735. // Explicit overloads for rspAnyLoad and rspAnySave.
  736. //
  737. // NOTICE: Metrowerks compiler has a problem with these explicit functions
  738. // being created AFTER the templates for them are defined. The solution is
  739. // simply to define these BEFORE the templates.
  740. //////////////////////////////////////////////////////////////////////////////
  741. // This macro makes it easy to create explicit versions of rspAnyLoad() for
  742. // basic types that are supported by RFile. Could be enhanced by allowing
  743. // caller to specify how to cast the value before calling RFile::Read().
  744. #define RFILE_INSTANTIATE_ANYLOAD(type) \
  745. inline \
  746. short rspAnyLoad( /* Returns 0 on success.*/ \
  747. type* ptype, /* Ptr to type to load.*/ \
  748. RFile* pfile) /* Open RFile to load from. Must have read access.*/ \
  749. { \
  750. return (pfile->Read(ptype) == 1) ? 0 : 1; \
  751. }
  752. // This macro makes it easy to create explicit versions of rspAnySave() for
  753. // basic types that are supported by RFile. Could be enhanced by allowing
  754. // caller to specify how to cast the value before calling RFile::Write().
  755. #define RFILE_INSTANTIATE_ANYSAVE(type) \
  756. inline \
  757. short rspAnySave( /* Returns 0 on success.*/ \
  758. type* ptype, /* Ptr to float to load.*/ \
  759. RFile* pfile) /* Open RFile to save to. Must have write access.*/ \
  760. { \
  761. return (pfile->Write(ptype) == 1) ? 0 : 1; \
  762. }
  763. RFILE_INSTANTIATE_ANYLOAD(U8)
  764. RFILE_INSTANTIATE_ANYSAVE(U8)
  765. RFILE_INSTANTIATE_ANYLOAD(S8)
  766. RFILE_INSTANTIATE_ANYSAVE(S8)
  767. RFILE_INSTANTIATE_ANYLOAD(U16)
  768. RFILE_INSTANTIATE_ANYSAVE(U16)
  769. RFILE_INSTANTIATE_ANYLOAD(S16)
  770. RFILE_INSTANTIATE_ANYSAVE(S16)
  771. RFILE_INSTANTIATE_ANYLOAD(RPixel24)
  772. RFILE_INSTANTIATE_ANYSAVE(RPixel24)
  773. RFILE_INSTANTIATE_ANYLOAD(U32)
  774. RFILE_INSTANTIATE_ANYSAVE(U32)
  775. RFILE_INSTANTIATE_ANYLOAD(S32)
  776. RFILE_INSTANTIATE_ANYSAVE(S32)
  777. RFILE_INSTANTIATE_ANYLOAD(RPixel32)
  778. RFILE_INSTANTIATE_ANYSAVE(RPixel32)
  779. RFILE_INSTANTIATE_ANYLOAD(float)
  780. RFILE_INSTANTIATE_ANYSAVE(float)
  781. RFILE_INSTANTIATE_ANYLOAD(U64)
  782. RFILE_INSTANTIATE_ANYSAVE(U64)
  783. RFILE_INSTANTIATE_ANYLOAD(S64)
  784. RFILE_INSTANTIATE_ANYSAVE(S64)
  785. RFILE_INSTANTIATE_ANYLOAD(double)
  786. RFILE_INSTANTIATE_ANYSAVE(double)
  787. //////////////////////////////////////////////////////////////////////////////
  788. // Loads any type that does not have a specific overload. This implicit one
  789. // only works for types that have their own Load(RFile*) member function.
  790. //////////////////////////////////////////////////////////////////////////////
  791. template <class obj>
  792. short rspAnyLoad( // Returns 0 on success.
  793. obj* pobj, // Ptr to object to load.
  794. RFile* pfile) // Open RFile. Must have read access.
  795. {
  796. return pobj->Load(pfile);
  797. }
  798. //////////////////////////////////////////////////////////////////////////////
  799. // Saves any type that does not have a specific overload. This implicit one
  800. // only works for types that have their own Save(RFile*) member function.
  801. //////////////////////////////////////////////////////////////////////////////
  802. template <class obj>
  803. short rspAnySave( // Returns 0 on success.
  804. obj* pobj, // Ptr to object to save.
  805. RFile* pfile) // Open RFile. Must have write access.
  806. {
  807. return pobj->Save(pfile);
  808. }
  809. // Find the correct file. This will favor the prefpath
  810. // for reading, and always use the prefpath for writing.
  811. // On systems without a prefpath, it just returns pszName, otherwise
  812. // it will find the right file name and return it in platform-
  813. // specific notation.
  814. // This may return a static buffer, and as such is not thread safe.
  815. extern const char *FindCorrectFile(const char *pszName, const char *pszMode);
  816. #endif // FILE_H
  817. //////////////////////////////////////////////////////////////////////////////
  818. // EOF
  819. //////////////////////////////////////////////////////////////////////////////