filewin.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  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. // FILEWIN.CPP
  21. //
  22. // History:
  23. // 09/19/95 JMI Started.
  24. //
  25. // 09/20/95 JMI Made read only.
  26. //
  27. //////////////////////////////////////////////////////////////////////////////
  28. //
  29. // This object maintains a window on the file. It fills the panes on
  30. // interval to be read by the user.
  31. //
  32. //////////////////////////////////////////////////////////////////////////////
  33. //////////////////////////////////////////////////////////////////////////////
  34. // C Headers.
  35. //////////////////////////////////////////////////////////////////////////////
  36. #include <malloc.h>
  37. //////////////////////////////////////////////////////////////////////////////
  38. // Blue Headers.
  39. //////////////////////////////////////////////////////////////////////////////
  40. #include "System.h"
  41. #include "bdebug.h"
  42. #include "bcritic.h"
  43. //////////////////////////////////////////////////////////////////////////////
  44. // Green Headers.
  45. //////////////////////////////////////////////////////////////////////////////
  46. #include "filewin.h"
  47. //////////////////////////////////////////////////////////////////////////////
  48. // Orange Headers.
  49. //////////////////////////////////////////////////////////////////////////////
  50. //////////////////////////////////////////////////////////////////////////////
  51. // Yellow Headers.
  52. //////////////////////////////////////////////////////////////////////////////
  53. //////////////////////////////////////////////////////////////////////////////
  54. // Module specific macros.
  55. //////////////////////////////////////////////////////////////////////////////
  56. #define WINDOWINDEX(l) (l % m_lWinSize)
  57. //////////////////////////////////////////////////////////////////////////////
  58. // Module specific typedefs.
  59. //////////////////////////////////////////////////////////////////////////////
  60. //////////////////////////////////////////////////////////////////////////////
  61. // Module specific (static) variables.
  62. //////////////////////////////////////////////////////////////////////////////
  63. //////////////////////////////////////////////////////////////////////////////
  64. // Construction/Destruction Functions.
  65. //////////////////////////////////////////////////////////////////////////////
  66. //////////////////////////////////////////////////////////////////////////////
  67. //
  68. // Default constructor.
  69. //
  70. //////////////////////////////////////////////////////////////////////////////
  71. CFileWin::CFileWin()
  72. {
  73. Set();
  74. }
  75. //////////////////////////////////////////////////////////////////////////////
  76. //
  77. // Destructor.
  78. //
  79. //////////////////////////////////////////////////////////////////////////////
  80. CFileWin::~CFileWin()
  81. {
  82. Close();
  83. }
  84. //////////////////////////////////////////////////////////////////////////////
  85. // Internal Functions.
  86. //////////////////////////////////////////////////////////////////////////////
  87. //////////////////////////////////////////////////////////////////////////////
  88. //
  89. // Sets variables w/o regard to current values.
  90. //
  91. //////////////////////////////////////////////////////////////////////////////
  92. void CFileWin::Set(void)
  93. {
  94. m_pucWindow = NULL;
  95. m_paneUser.puc = NULL;
  96. m_paneIn.puc = NULL;
  97. m_usStatus = 0;
  98. m_call = NULL;
  99. m_fnTime = NULL;
  100. m_sActive = FALSE;
  101. m_sSuspend = 1; // Start out suspended.
  102. }
  103. //////////////////////////////////////////////////////////////////////////////
  104. //
  105. // Resets variables. Performs deallocation if necessary.
  106. //
  107. //////////////////////////////////////////////////////////////////////////////
  108. void CFileWin::Reset(void)
  109. {
  110. ASSERT(m_sActive == FALSE);
  111. Suspend();
  112. Free();
  113. Set();
  114. }
  115. //////////////////////////////////////////////////////////////////////////////
  116. //
  117. // Allocates the file window of size lSize.
  118. // Returns 0 on success.
  119. //
  120. //////////////////////////////////////////////////////////////////////////////
  121. short CFileWin::Alloc(long lSize)
  122. {
  123. short sRes = 0; // Assume success.
  124. // Allocate new window . . .
  125. m_pucWindow = (UCHAR*)malloc(lSize);
  126. if (m_pucWindow != NULL)
  127. {
  128. m_paneUser.puc = m_pucWindow;
  129. m_paneIn.puc = m_pucWindow;
  130. m_lWinSize = lSize;
  131. m_paneUser.lPos = 0L;
  132. m_paneIn.lPos = 0L;
  133. }
  134. else
  135. {
  136. TRACE("Alloc(%ld): Unable to allocate file window.\n", lSize);
  137. sRes = -1;
  138. }
  139. return sRes;
  140. }
  141. //////////////////////////////////////////////////////////////////////////////
  142. //
  143. // Frees the file window.
  144. //
  145. //////////////////////////////////////////////////////////////////////////////
  146. void CFileWin::Free(void)
  147. {
  148. if (m_pucWindow != NULL)
  149. {
  150. free(m_pucWindow);
  151. m_pucWindow = NULL;
  152. m_paneUser.puc = NULL;
  153. m_paneIn.puc = NULL;
  154. }
  155. }
  156. //////////////////////////////////////////////////////////////////////////////
  157. //
  158. // Move to next i/o pane.
  159. // Returns 0 on success.
  160. //
  161. //////////////////////////////////////////////////////////////////////////////
  162. short CFileWin::NextIOPane(void)
  163. {
  164. short sRes = 0; // Assume success.
  165. // If next pane complete . . .
  166. if (IsNextInputPaneReady() == TRUE)
  167. {
  168. // Get position of next pane.
  169. m_paneIn.lPos += m_paneIn.lSize;
  170. // Move ptr to position.
  171. m_paneIn.puc = m_pucWindow + WINDOWINDEX(m_paneIn.lPos);
  172. }
  173. else
  174. {
  175. sRes = -1;
  176. }
  177. return sRes;
  178. }
  179. //////////////////////////////////////////////////////////////////////////////
  180. //
  181. // Implied this version of CriticalStatic. Reads/writes file.
  182. //
  183. //////////////////////////////////////////////////////////////////////////////
  184. void CFileWin::Critical(void)
  185. {
  186. // If time to update . . .
  187. if (GetTime() > m_lNextTime)
  188. {
  189. if (NextIOPane() == 0)
  190. {
  191. // Attempt to fill pane.
  192. m_paneIn.lSize = m_file.Read(m_paneIn.puc, m_paneIn.lSize);
  193. // Get next read time.
  194. m_lNextTime = GetTime() + m_lInputInterval;
  195. }
  196. else
  197. {
  198. TRACE("Critical(): Waiting for application to free up current "
  199. "pane!\n");
  200. m_usStatus |= STATUS_WAITING;
  201. }
  202. }
  203. // If callback provided . . .
  204. if (m_call != NULL)
  205. {
  206. // If next user pane is complete . . .
  207. if (NextPane() == 0)
  208. {
  209. // Call user.
  210. (*m_call)(&m_paneUser, m_lUser);
  211. }
  212. else
  213. {
  214. // If EOF . . .
  215. if (m_file.IsEOF() == TRUE)
  216. {
  217. m_usStatus |= STATUS_EOF;
  218. }
  219. else
  220. {
  221. // If read error . . .
  222. if (m_file.Error() == TRUE)
  223. {
  224. TRACE("Critical(): A read error stopped reading before complete.\n");
  225. m_usStatus |= ERROR_FILEACCESS;
  226. }
  227. }
  228. // If not ready b/c file input has stopped . . .
  229. if (m_usStatus & (STATUS_EOF | ERROR_FILEACCESS))
  230. {
  231. // If there is not a full pane of data . . .
  232. if (m_paneUser.lPos + m_paneUser.lSize * 2 > m_paneIn.lPos + m_paneIn.lSize)
  233. {
  234. // Advance.
  235. m_paneUser.lPos += m_paneUser.lSize;
  236. m_paneUser.puc = m_pucWindow + WINDOWINDEX(m_paneUser.lPos);
  237. // Adjust pane size.
  238. m_paneUser.lSize = (m_paneIn.lPos + m_paneIn.lSize) - m_paneUser.lPos;
  239. // Call user.
  240. (*m_call)(&m_paneUser, m_lUser);
  241. }
  242. // Suspend this.
  243. Suspend();
  244. }
  245. else
  246. {
  247. // User pane caught up with input even though no error nor EOF.
  248. // This could occur if the user pane is larger than the input
  249. // pane.
  250. }
  251. }
  252. }
  253. }
  254. //////////////////////////////////////////////////////////////////////////////
  255. //
  256. // Called by Blue every time Blu_System is called.
  257. //
  258. //////////////////////////////////////////////////////////////////////////////
  259. void CFileWin::CriticalStatic(CFileWin* pfw)
  260. {
  261. pfw->Critical();
  262. }
  263. //////////////////////////////////////////////////////////////////////////////
  264. // Public Functions.
  265. //////////////////////////////////////////////////////////////////////////////
  266. //////////////////////////////////////////////////////////////////////////////
  267. //
  268. // Opens a window into pszFile. sMode indicates read or write
  269. // { FW_MODE_READ, FW_MODE_WRITE }.
  270. // Returns 0 on success.
  271. //
  272. //////////////////////////////////////////////////////////////////////////////
  273. short CFileWin::Open(char* pszFile)
  274. {
  275. short sRes = 0; // Assume success.
  276. // Attempt to open file . . .
  277. // Endianness doesn't matter (only UCHAR reads).
  278. if (m_file.Open(pszFile, "rb", ENDIAN_BIG) == 0)
  279. {
  280. }
  281. else
  282. {
  283. TRACE("Open(\"%s\"): Unable to open file.\n");
  284. sRes = -1;
  285. }
  286. return sRes;
  287. }
  288. //////////////////////////////////////////////////////////////////////////////
  289. //
  290. // Closes the currently open file.
  291. // Returns 0 on success.
  292. //
  293. //////////////////////////////////////////////////////////////////////////////
  294. short CFileWin::Close(void)
  295. {
  296. short sRes = 0; // Assume success.
  297. // If file is open . . .
  298. if (m_file.IsOpen() == TRUE)
  299. {
  300. // Close.
  301. if (m_file.Close() == 0)
  302. {
  303. // Success.
  304. Suspend();
  305. Reset();
  306. }
  307. else
  308. {
  309. TRACE("Close(): CNFile::Close() failed.\n");
  310. sRes = -1;
  311. }
  312. }
  313. return sRes;
  314. }
  315. //////////////////////////////////////////////////////////////////////////////
  316. //
  317. // Sets size of window, user pane, and i/o pane. Anything currently in the
  318. // window will be lost.
  319. // This function causes a seek.
  320. // If this fails you could end up with no more buffer, even if you had one
  321. // before calling this, so CHECK THE RETURN VALUE!
  322. // ASSUMPTIONS: File is open.
  323. // Returns 0 on success.
  324. //
  325. //////////////////////////////////////////////////////////////////////////////
  326. short CFileWin::SetSize(long lWinSize, long lIOPaneSize, long lUserPaneSize)
  327. {
  328. short sRes = 0; // Assume success.
  329. ASSERT(m_file.IsOpen() == TRUE);
  330. ASSERT(lWinSize % lIOPaneSize == 0);
  331. ASSERT(lWinSize % lUserPaneSize == 0);
  332. // Free current window.
  333. Free();
  334. // Allocate new window . . .
  335. if (Alloc(lWinSize) == 0)
  336. {
  337. m_paneUser.lSize = lUserPaneSize;
  338. // Store current file position. Changing the buffer size of a stream
  339. // requires a seek.
  340. long lPos = m_file.Tell();
  341. // Attempt to set file buffer size . . .
  342. if (m_file.SetBufferSize(lIOPaneSize) == 0)
  343. {
  344. m_paneIn.lSize = lIOPaneSize;
  345. // Attempt to seek back to current position . . .
  346. if (m_file.Seek(lPos, SEEK_SET) == 0)
  347. {
  348. // Success.
  349. }
  350. else
  351. {
  352. TRACE("SetSize(): CNFile::Seek failed.\n");
  353. sRes = -3;
  354. }
  355. }
  356. else
  357. {
  358. TRACE("SetSize(): CNFile::SetBufferSize failed.\n");
  359. sRes = -2;
  360. }
  361. // If any errors occurred after allocation . . .
  362. if (sRes != 0)
  363. {
  364. Free();
  365. }
  366. }
  367. else
  368. {
  369. TRACE("SetSize(): Unable to allocate new window.\n");
  370. sRes = -1;
  371. }
  372. return sRes;
  373. }
  374. //////////////////////////////////////////////////////////////////////////////
  375. //
  376. // Move to next user pane.
  377. // Returns 0 on success.
  378. //
  379. //////////////////////////////////////////////////////////////////////////////
  380. short CFileWin::NextPane(void)
  381. {
  382. short sRes = 0; // Assume success.
  383. // If next pane complete . . .
  384. if (IsNextPaneReady() == TRUE)
  385. {
  386. // Get position of next pane.
  387. m_paneUser.lPos += m_paneUser.lSize;
  388. // Move ptr to position.
  389. m_paneUser.puc = m_pucWindow + WINDOWINDEX(m_paneUser.lPos);
  390. }
  391. else
  392. {
  393. sRes = -1;
  394. }
  395. return sRes;
  396. }
  397. //////////////////////////////////////////////////////////////////////////////
  398. //
  399. // Start reading/writing.
  400. // Returns 0 on success.
  401. //
  402. //////////////////////////////////////////////////////////////////////////////
  403. short CFileWin::Start(void)
  404. {
  405. short sRes = 0; // Assume success.
  406. if (--m_sSuspend == 0)
  407. {
  408. if (m_sActive == FALSE)
  409. {
  410. if (Blu_AddCritical((CRITICALL)CriticalStatic, (ULONG)this) == 0)
  411. {
  412. // Pick up where we left off.
  413. m_lNextTime = GetTime() + m_lNextTime;
  414. m_sActive = TRUE;
  415. }
  416. else
  417. {
  418. sRes = -1;
  419. TRACE("Start(): Unable to add critical function.\n");
  420. }
  421. }
  422. }
  423. return sRes;
  424. }
  425. //////////////////////////////////////////////////////////////////////////////
  426. //
  427. // Suspend reading/writing.
  428. // Returns 0 on success.
  429. //
  430. //////////////////////////////////////////////////////////////////////////////
  431. short CFileWin::Suspend(void)
  432. {
  433. short sRes = 0; // Assume success.
  434. m_sSuspend++;
  435. if (m_sActive == TRUE)
  436. {
  437. if (Blu_RemoveCritical((CRITICALL)CriticalStatic) == 0)
  438. {
  439. m_sActive = FALSE;
  440. // Remember how long from suspension until next.
  441. m_lNextTime = m_lNextTime - GetTime();
  442. }
  443. else
  444. {
  445. sRes = -1;
  446. TRACE("Suspend(): Unable to remove critical function.\n");
  447. }
  448. }
  449. return sRes;
  450. }
  451. //////////////////////////////////////////////////////////////////////////////
  452. //
  453. // Returns TRUE if next user pane is ready; FALSE otherwise.
  454. //
  455. //////////////////////////////////////////////////////////////////////////////
  456. short CFileWin::IsNextPaneReady(void)
  457. {
  458. short sRes = TRUE; // Assume ready.
  459. // If next pane is where the next read is going to occur . . .
  460. if (m_paneUser.lPos + m_paneUser.lSize * 2L > m_paneIn.lPos + m_paneIn.lSize)
  461. {
  462. sRes = FALSE;
  463. }
  464. return sRes;
  465. }
  466. //////////////////////////////////////////////////////////////////////////////
  467. //
  468. // Returns TRUE if next input pane is ready; FALSE otherwise.
  469. //
  470. //////////////////////////////////////////////////////////////////////////////
  471. short CFileWin::IsNextInputPaneReady(void)
  472. {
  473. short sRes = TRUE; // Assume ready.
  474. long lNextInputPaneStart = WINDOWINDEX(m_paneIn.lPos + m_paneIn.lSize);
  475. long lNextInputPaneEnd = WINDOWINDEX(m_paneIn.lPos + m_paneIn.lSize * 2L);
  476. long lCurUserPaneStart = WINDOWINDEX(m_paneUser.lPos);
  477. long lCurUserPaneEnd = WINDOWINDEX(m_paneUser.lPos + m_paneUser.lSize);
  478. // If the next input pane intersects the current user pane . . .
  479. if ( lNextInputPaneStart < lCurUserPaneEnd
  480. && lNextInputPaneEnd > lCurUserPaneStart)
  481. {
  482. // You can't fight the seither.
  483. sRes = FALSE;
  484. }
  485. return sRes;
  486. }
  487. //////////////////////////////////////////////////////////////////////////////
  488. // EOF
  489. //////////////////////////////////////////////////////////////////////////////